Welcome, Guest.
Username: Password: Remember me

TOPIC: Get bit depth of backbuffer?

Get bit depth of backbuffer? 2 months 4 days ago #1

Hello

Can ReShade provide any information about the number of bits per pixel the game uses?

I use high precision floating point numbers in my shader, but in the end they will be typically rounded to the nearest 8-bit value since that is what most games tend to render at.

However some (HDR?) games may use 10 bits and I'd like to be able to detect that, as it affects how my shader needs to work.

I looked at
github.com/crosire/reshade-shaders/blob/master/REFERENCE.md
but couldn't see anything there.

Thanks
Last Edit: 2 months 4 days ago by pneumatic.
The administrator has disabled public write access.

Get bit depth of backbuffer? 2 months 3 days ago #2

This is on the TODO list, but not yet possible.
Cheers, crosire =)
The administrator has disabled public write access.
The following user(s) said Thank You: Bloody Eugene

Get bit depth of backbuffer? 2 months 3 days ago #3

Thanks.

In that case I will just define a var which the user can set, eg. 8|10|12 etc. to match whatever the game happens to use.

A couple of extra questions if I may:

1. When using ReShade with a game that renders in 10 bits (eg. HDR games) does ReShade preserve the 10-bit value through its pipeline, or does it round to 8-bit at some point? I have no 10-bit games or monitor to test with.

2. Is it the bit depth of the back buffer or the front buffer which determines the bit depth of the final colour drawn to screen?

Thanks
The administrator has disabled public write access.

Get bit depth of backbuffer? 2 months 3 days ago #4

1) If the game uses a 10bit backbuffer, ReShade will use the same format for its internal buffers too. So yes, the precision is preserved throughout the pipeline.
2) The frontbuffer should implicitly be created with the same format as the backbuffer (one has no control over this, it is handled by the driver). So if a game requests a 10bit backbuffer, that's what will be used for presentation. But starting with Windows 10 things become a bit more complicated, because there is an additional layer between DX/GL and monitor scanout now (DWM). All the new HDR settings in the Windows Settings now affect how that layer interprets the data before it is finally sent off to your monitor.
Cheers, crosire =)
The administrator has disabled public write access.
The following user(s) said Thank You: pneumatic

Get bit depth of backbuffer? 2 months 1 day ago #5

Thanks
Also does the current version of ReShade still round to the backbuffer format after each effect in the pipeline?
Last Edit: 2 months 1 day ago by pneumatic.
The administrator has disabled public write access.

Get bit depth of backbuffer? 2 months 1 day ago #6

It uses the same buffer as the game does, so yeah.
Cheers, crosire =)
The administrator has disabled public write access.
The following user(s) said Thank You: pneumatic

Get bit depth of backbuffer? 2 months 23 hours ago #7

I noticed in version 2, CeeJay's SweetFX suite avoided that by including several effects in one effect file, which preserved the high precision values between each of his effects, which made it possible for him to use dithering on those final high precision values to avoid banding artefacts on all his effects.

If ReShade could preserve the high precision values through its entire pipeline, this would open up the possibility of having the same kind of high quality dithering and smooth gradients on all effects.

There are currently ways to achieve smooth gradients on all effects, such as applying FilmGrain as the first effect in the pipeline, or applying the Deband shader as the last effect, but these aren't optimal methods and have their drawbacks. Basically dithering works best when operating on high precision values as the very last effect in the pipeline.

Is it trivial to allow preservation of high precision values between effects, or would that require rewriting a lot of stuff?

Cheers
The administrator has disabled public write access.

Get bit depth of backbuffer? 2 months 22 hours ago #8

Actually, you really want to dither BEFORE effects that cause banding from truncation by reshade to RGBA8 for best results. But, that needs to be done within the shaders or functions themselves as CeeJay did like you've already mentioned.
Last Edit: 1 month 4 weeks ago by TreyM.
The administrator has disabled public write access.

Get bit depth of backbuffer? 2 months 20 hours ago #9

TreyM wrote:
Actually, you really want to dither BEFORE effects that cause banding for best results.

The effects themselves don't cause banding though, because they are done with high precision floating point values.
Take CeeJay's Curves shader for example, it produces high precision S-curve using mathematical formulas.
But after the effect is finished, ReShade rounds the final value to the backbuffer format, which causes the banding.
Then the next effect comes along, does its thing, then it too gets rounded to backbuffer format.
Ideally we should preserve the high precision value all the way till the very end, and then apply dithering to it at the very last step to convert high precision to low precision to suit the backbuffer format.
Comment from CeeJay's shared.h: // Dither (should go near the end as it only dithers what went before it)
Last Edit: 2 months 20 hours ago by pneumatic.
The administrator has disabled public write access.

Get bit depth of backbuffer? 2 months 14 hours ago #10

The way you do it is to create a texture with a format that stores the precision you want and use that as render target between passes. That guarantees precision to what you want. RGBA8 is the standard image format and this the one ReShade will use most if the time. If you need more precision you have to opt-in to that yourself the way I described.
Cheers, crosire =)
The administrator has disabled public write access.

Get bit depth of backbuffer? 2 months 11 hours ago #11

crosire wrote:
The way you do it is to create a texture with a format that stores the precision you want and use that as render target between passes. That guarantees precision to what you want. RGBA8 is the standard image format and this the one ReShade will use most if the time. If you need more precision you have to opt-in to that yourself the way I described.

Is it possible to do that between techniques as well?
The administrator has disabled public write access.

Get bit depth of backbuffer? 2 months 10 hours ago #12

Yes, absolutely. Textures are preserved. See the Splitscreen or UIMak shader as an example, which does exactly that.
Cheers, crosire =)
The administrator has disabled public write access.
The following user(s) said Thank You: pneumatic

Get bit depth of backbuffer? 1 month 4 weeks ago #13

pneumatic wrote:
The effects themselves don't cause banding though, because they are done with high precision floating point values.

I'm aware of this, however you can have all the precision you want and it's still going to cause banding due to truncation. Certain effects DO cause banding due to the output being truncated to 8 bit, such as vignette for example. You need to dither within the function/shader containing the effect before the truncation occurs which is what causes banding.

If you want to avoid banding on an 8-bit display on subtle gradients, you're going to need to dither at some point. There is no escaping it.

Some relevant reading here: loopit.dk/banding_in_games.pdf
Last Edit: 1 month 4 weeks ago by TreyM.
The administrator has disabled public write access.

Get bit depth of backbuffer? 1 month 4 weeks ago #14

TreyM wrote:
Certain effects DO cause banding due to the output being truncated to 8 bit, such as vignette for example.

Vignette doesn't actually cause banding though. What I mean by that exactly, is that nowhere in VignettePass() does it round or truncate to the nearest bit step. The gradients it generates for the corners of the screen are mathematically smooth and continuous, limited only by the number of decimal places in the floating point values it uses, which is large and precise. The rounding occurs later on in the Technique section, due to ReShade rounding VignettePass to the backbuffer format since its Technique specifies no render target, which defaults to the backbuffer target which is typically RGBA8. The proof is that when CeeJay's dither.h shader is enabled (ReShade v2.0) it creates a perfectly smooth vignette gradient, otherwise there would be nothing to dither "from", and all we'd be doing is adding noise to the already "baked in" banding artefacts which Vignette created (because remember, CeeJay's dither shader is applied AFTER the vignette).
crosire wrote:
Yes, absolutely. Textures are preserved. See the Splitscreen or UIMask shader as an example, which does exactly that.

Thanks, it works :)
The administrator has disabled public write access.

Get bit depth of backbuffer? 1 month 4 weeks ago #15

Spoke too soon :silly:

It seems multiple techniques can't use the same texture as their render target, otherwise I get a raster full of black pixels.
I can get around it by rendering to a different texture for each pass in the pipeline, but it requires creating 50 textures (1 for each effect) and I'm not sure it's feasible performance wise.

https://github.com/crosire/reshade-shaders/blob/master/REFERENCE.md wrote:
// Be aware that you can only read **OR** write a texture at the same time, so do not sample from it while it is still bound as render target here.
// Clears all bound render targets to zero before rendering when set to true.
ClearRenderTargets = true;

I tried adding ClearRenderTargets = true; but it gives me error: unrecognized pass state 'ClearRenderTargets'.

edit: ah, because ClearRenderTargets was only added in v3.0 and I'm testing on v2.0 atm.

But I'm still not sure this is the problem, as it would seem I'm not reading/writing to the texture at the same time.
Last Edit: 1 month 4 weeks ago by pneumatic.
The administrator has disabled public write access.

Get bit depth of backbuffer? 1 month 4 weeks ago #16

Just to clarify what I'm trying to do, to confirm it should be possible with just one texture:


texture RFX_backbufferTex_RGBA16F { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F;};
sampler RFX_backbufferColor_RGBA16F { Texture = RFX_backbufferTex_RGBA16F; };



float4 Shader1(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
	float4 color = tex2D(RFX_backbufferColor, texcoord);	
	return color;
}
technique Tech1 
{
	pass Pass1
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = Shader1;
		RenderTarget = RFX_backbufferTex_RGBA16F;	
	}
}




float4 Shader2(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
	float4 color = tex2D(RFX_backbufferColor_RGBA16F, texcoord);	
	return color;
}
technique Tech2 
{
	pass Pass2
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = Shader2;
		RenderTarget = RFX_backbufferTex_RGBA16F;	
	}
}





float4 Shader3(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target
{
	float4 color = tex2D(RFX_backbufferColor_RGBA16F, texcoord);	
	return color;
}
technique Tech3 
{
	pass Pass3
	{
		VertexShader = RFX_VS_PostProcess;
		PixelShader = Shader3;
	}
}
The administrator has disabled public write access.

Get bit depth of backbuffer? 1 month 4 weeks ago #17

You cannot read from and write to the same texture in a pass. The only exception is the backbuffer because ReShade automatically manages a mirror texture there for you. If you use custom textures you need to ping/pong between two different ones (read from the first and write to the second, then read from the second and write to the first etc.).
Cheers, crosire =)
The administrator has disabled public write access.
The following user(s) said Thank You: pneumatic

Get bit depth of backbuffer? 1 month 4 weeks ago #18

Any color processing stuff is being computed in float format usually, so when still inside a pixel shader, the data isn't quantized (at least not visibly).
To actually apply whatever is being computed, the shader renders to the backbuffer, which means quantization to 8 or 10 bit per channel, depending on backbuffer format, and that causes banding.
Vignette is bound to create banding, it creates wide gradients with only a few colors between start and end and many more pixels between start and end. The only real way to add dithering is add it right before the shader outputs to the backbuffer, where it would get quantized. So basically inside each shader, at the end.

CeeJay's dither shader is inside the same pixel shader as the vignette on ReShade 2.0, so that's exactly how it's supposed to be used. On current version with Vignette being an independent filter and rendering to backbuffer before any dither can do anything, dither does nothing to help banding form the vignette.
The administrator has disabled public write access.

Get bit depth of backbuffer? 1 month 4 weeks ago #19

Well unless it's inside the vignette function as you said. The current TriDither shader is apparently useless because of this, and I'm going to do a pull request to make it a callable function instead of a shader as it is now. Once that's done, we can add the dither function call to problematic effects, then we can (in theory if crosire is in favor) optionally toggle "dithering" globally via preprocessor definition.
The administrator has disabled public write access.

Get bit depth of backbuffer? 1 month 4 weeks ago #20

crosire wrote:
You cannot read from and write to the same texture in a pass. The only exception is the backbuffer because ReShade automatically manages a mirror texture there for you. If you use custom textures you need to ping/pong between two different ones (read from the first and write to the second, then read from the second and write to the first etc.).

I'm not sure if this is possible for the entire pipeline, as the user could enable any random order of effects, so each effect needs to update a global var to keep track of the last used texture, and we need to check that value with an if statement inside the technique's pass, which appears to be invalid syntax. Is there some way around this like dereferencing a string like RenderTarget = %GlobalStringContainingNameOfTextureVariable%
Last Edit: 1 month 4 weeks ago by pneumatic.
The administrator has disabled public write access.
  • Page:
  • 1
  • 2