• Advertisement
Sign in to follow this  

D3d12 : d24_x8 format to rgba8?

This topic is 723 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a very very specific use case that sample depth texture (stored as d24 and 8 bits stencil) as an rgba8 components. There is no conversion involved, the texture is just reinterpreted and the depth value is obtained by a dot product of texel rgb with a constant vector (2^16,2^8,1).

Is this kind of operation supported with d3d? My testing shows that debug layer doesn't complain (d24x8 and rgba8 have same size but on the other hand the format are not straightforward) however with my Intel igpu the result is wrong. With an Nvidia card the result *looks* right but maybe it's just by luck.

Share this post


Link to post
Share on other sites
Advertisement

IIRC AMD GCN always stores the stencil and depth separately, so this hack won't work there.

Yes they mentionned it on some twitter account, but then does GCN store 24 bits depth value as 32 bits if a 24 bits depth texture is requested ?

Since there is no performance bandwidth advantage since 24 bits needs to be stored in a 32 bits location and 8 bits are wasted the driver might as well promote d24x8 to d32 + r8 ?

 

[EDIT] Is it possible to copy depth component to a RGBA8 (possibly typeless) texture or do I have to use a shader to manually convert the float depth to int, do some bit shift operations and store component separatly ?

Edited by vlj

Share this post


Link to post
Share on other sites

I think the correct way to access depth-stencil surface as texture (SRV) is to

 

1. create the resource as:

DXGI_FORMAT_R24G8_TYPELESS     

 

2. create depth stencil surface as:

DXGI_FORMAT_D24_UNORM_S8_UINT

 

3. Create *two* separate SRVs for accessing depth and stencil parts of the surface of formats:

DXGI_FORMAT_R24_UNORM_X8_TYPELESS

DXGI_FORMAT_X24_TYPELESS_G8_UINT

 

You can only access depth from the first SRV (by reading red/x component of the texture as normalized float value) and only access stencil component from the second SRV (reading as unsigned integer).

 

This should work on all IHVs.

Share this post


Link to post
Share on other sites

Yes but with DXGI_FORMAT_R24_UNORM_X8_TYPELESS format I can only access the 24 bits depth value, it's not splitted in 3x8 bits values.

Share this post


Link to post
Share on other sites

Yes they mentionned it on some twitter account, but then does GCN store 24 bits depth value as 32 bits if a 24 bits depth texture is requested ?
Since there is no performance bandwidth advantage since 24 bits needs to be stored in a 32 bits location and 8 bits are wasted the driver might as well promote d24x8 to d32 + r8 ?


No, they store it as 24-bit fixed point with 8 bits unused. It only uses 32 bits if you request a floating point depth buffer, and they can't promote from fixed point -> floating point since the distribution of precision is different.
 

[EDIT] Is it possible to copy depth component to a RGBA8 (possibly typeless) texture or do I have to use a shader to manually convert the float depth to int, do some bit shift operations and store component separatly ?


You can only copy between textures that have the same format family.

Share this post


Link to post
Share on other sites

Yes but with DXGI_FORMAT_R24_UNORM_X8_TYPELESS format I can only access the 24 bits depth value, it's not splitted in 3x8 bits values.

If you're using this format, you presumably have access to integer operations in your shaders -- are you just hoping to see a performance increase by not doing any bit shifting? I'm almost positive bit shifting three values isn't going to bog you down.

Share this post


Link to post
Share on other sites

Yes they mentionned it on some twitter account, but then does GCN store 24 bits depth value as 32 bits if a 24 bits depth texture is requested ?
Since there is no performance bandwidth advantage since 24 bits needs to be stored in a 32 bits location and 8 bits are wasted the driver might as well promote d24x8 to d32 + r8 ?


No, they store it as 24-bit fixed point with 8 bits unused. It only uses 32 bits if you request a floating point depth buffer, and they can't promote from fixed point -> floating point since the distribution of precision is different.

Pretty much this. They cannot promote it for you since the behavior is very different. They must honour 24-bit integer precision.

As for the bandwidth, this is why AMD recommends that if you never use the stencil, don't ask for a depth buffer with stencil capabilities.

Share this post


Link to post
Share on other sites

Thanks for the answers. I found an working (but not optimal) way of doing, I'm copying depth buffer with R32_TYPELESS format to a vram buffer and then I'm copying to an RGBA8 texture in an heap.

Doing the conversion with shader arithmetic is likely the best way of doing but I'm afraid of some compatibility issues in my (very specific) case.

 

For what it worths I investigated further and actually Intel igpu are supporting d24s8 -> rgba8 cast without any special manipulation. However Nvidia gpu (or driver) seem to silently ignore the srv format for ds texture and use a d24s8 and output depth to red/green component. That's why I though it worked before, the dot operator was applied to (depth, depth, 0) and was returning "almost" the correct depth value since the first component has the highest weight.

 

Now with the buffer copy solution it works the same accross hardware vendor and some compatibility bug disappeared.

However I think debug layer should emit a warning or an error if there is ds/srv format incompatibility instead of having the driver trying to correct it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement