Jump to content
  • Advertisement
Sign in to follow this  
51mon

DXGI_USAGE_UNORDERED_ACCESS and RWTexture2D in pixel shader?

This topic is 1312 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

Hello

I'm trying to do some dynamic blending in a pixel shader. This is on DX 11. I created the swap chain with DXGI_USAGE_UNORDERED_ACCESS and DXGI_FORMAT_R8G8B8A8_UNORM format. The idea is to have a pixel shader with no declared output but instead read read/write to a RWTexture2D inside the shader.

 

However I'm having a bit of a problem to declare the RWTexture2D. What type should it be, uint doesn't work? I get the error message:

The resource return type for component 0 declared in the shader code (UINT) is not compatible with the resource type bound to Unordered Access View slot 0 of the Pixel Shader unit (UNORM). This mismatch is invalid if the shader actually uses the view (e.g. it is not skipped due to shader code branching). [ EXECUTION ERROR #2097372: DEVICE_UNORDEREDACCESSVIEW_RETURN_TYPE_MISMATCH]

 

And if I try to create the UAV with a different format I get errors like this:

The Format (0x1e, R8G8B8A8_UINT) is invalid, when creating a View; the Resource was already created with a fully qualified Format, which is not castable (0x1c, R8G8B8A8_UNORM). [ STATE_CREATION ERROR #2097343: CREATEUNORDEREDACCESSVIEW_INVALIDFORMAT]

 

So how can I resolve this? Is there a correct way to declare the texture in the shader or should handle the setup on the CPU in a different way?

 

Thanks!

 

Share this post


Link to post
Share on other sites
Advertisement

If you have a format with the "UNORM" suffix, this basically means "the raw data is stored as unsigned integers, but the hardware will interpret it as a [0.0, 1.0] floating point value". So if you have a Texture2D or RWTexture2D, you should use the "float4" type with UNORM formats.

 

As an example of how it works, let's say a single texel of your texture has the integer values (255, 127, 63, 0). To perform the UNORM conversion, the hardware will divide all of those by 255.0. This produces a float4 with the values (1.0, 0.5, 0.25, 0.0). SNORM works in a very similar way, except that it interprets that data as a signed integer and converts to floating point values of the range [-1.0, 1.0].

 

If you're interested, the relevent documentation on how the format conversions work can be found here.

Thanks! That worked fine but I now have a different issue.

 

First I want to read the back buffer do some computations on the data and then write back to the RWTexture resource. So I declared the texture as float4 to be able to write to it but then when I try to read from it, it fails to compile with the following error:

 

error X3676: typed UAV loads are only allowed for single-component 32-bit element types

 

How can I get around this? Is there a way to declare it so it's both valid for read and write in the pixel shader?

Share this post


Link to post
Share on other sites

Yeah, that's a really annoying limitation of RWTexture2D: they can only read from R32_FLOAT, R32_UINT, and R32_INT formats. It comes from early D3D11 hardware that had bad support for UAV's.

For the case of an R8B8G8A8_UNORM texture, you can work around this by aliasing the texture as R32_UINT and then manually performing the UNORM conversion in the shader. There's documentation on how to do this here.

Share this post


Link to post
Share on other sites

Yeah, that's a really annoying limitation of RWTexture2D: they can only read from R32_FLOAT, R32_UINT, and R32_INT formats. It comes from early D3D11 hardware that had bad support for UAV's.

For the case of an R8B8G8A8_UNORM texture, you can work around this by aliasing the texture as R32_UINT and then manually performing the UNORM conversion in the shader. There's documentation on how to do this here.

I was thinking about that but how do I alias the texture? The swap chain is created as a typed format by default.

 

Thanks!

Share this post


Link to post
Share on other sites

You can (sometimes) alias if you create the resource/texture with the _TYPELESS suffix. The views (SRV, RTV, UAV) then explicitly define a type. You probably have to experiment a bit to find out what combination works. E.g. I don't know if you can alias R32 and RGBA8. I also wonder if the swap-chain texture can be typeless.

If this doesn't work the alternative is rendering to an off-screen texture and later draw it with a full-screen quad reading from said texture.

Share this post


Link to post
Share on other sites

 

unbird, on 28 Oct 2014 - 10:48 AM, said:

You can (sometimes) alias if you create the resource/texture with the _TYPELESS suffix. The views (SRV, RTV, UAV) then explicitly define a type. You probably have to experiment a bit to find out what combination works. E.g. I don't know if you can alias R32 and RGBA8. I also wonder if the swap-chain texture can be typeless.

If this doesn't work the alternative is rendering to an off-screen texture and later draw it with a full-screen quad reading from said texture.

According to this document it's not possible to use a typeless swap chain, http://msdn.microsoft.com/en-us/library/windows/desktop/bb173064(v=vs.85).aspx.

 

Would it be possible to manage the resource as RWByteAddressBuffer in the shader somehow without copying into a whole new resource?

Edited by 51mon

Share this post


Link to post
Share on other sites

I believe that for UAV's that allow for a special case, where you can create the UAV with DXGI_FORMAT_R32_UINT even though that does not match the original format that the texture was created with. 

Share this post


Link to post
Share on other sites

I believe that for UAV's that allow for a special case, where you can create the UAV with DXGI_FORMAT_R32_UINT even though that does not match the original format that the texture was created with. 

I tried that but I'll get:

 

D3D11 ERROR: ID3D11Device::CreateUnorderedAccessView: The Format (0x2a, R32_UINT) is invalid, when creating a View; the Resource was already created with a fully qualified Format, which is not castable (0x1c, R8G8B8A8_UNORM). [ STATE_CREATION ERROR #2097343: CREATEUNORDEREDACCESSVIEW_INVALIDFORMAT]

Share this post


Link to post
Share on other sites

Would it be possible to manage the resource as RWByteAddressBuffer in the shader somehow without copying into a whole new resource?


To my knowledge you can't alias a texture as a buffer (or vice versa). If so, you'd need the D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS flag. I doubt you can do this with textures, and the swap chain description doesn't have such a flag anyway. Looks you need to go for the indirect approach.sad.png 

Hmmmm, now I remember: Humus has an example of GPU texture compression where he copies from a R32G32_UInt to BC4 with CopyResource. Maybe you can do something similar. Still indirect, but doesn't involve another draw call.

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!