HLSL - "typed UAV loads" error, how to fix it?

Started by
2 comments, last by upstream99 4 years, 10 months ago

Visual Studio output:

Quote

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

Any idea how to fix it? I have got a C# project and can not build it. I am a web developer myself so not very good with HLSL nuances :)

AlphaPremultiplier.cs.hlsl


RWTexture2D<unorm float4> tex : register(u0);

[numthreads(16, 16, 1)]
void main(uint3 dispatchThreadId : SV_DispatchThreadID) {
    uint2 pixelId = dispatchThreadId.xy;

    float4 c = tex[pixelId]; // <--- error 
    c.rgb *= c.a;
    tex[pixelId] = c;
}

 

Advertisement

Whether it can be 'fixed' or not all depends on what version of DX11 you're using and whether you're willing to limit the hardware on which you want to be able to run the shader.

DX11.3 and DX12 expanded on the list of formats that could be loaded from UAVs from just 3 (R32_FLOAT, R32_UINT, R32_SINT) to a list containing about 15, with most of the rest of them as 'optional'.

Hardware that is D3D_FEATURE_LEVEL_12_0 or 12_1 will be able to do a typed UAV load from R8G8B8A8_UNORM but only optionally R16G16B16A16_UNORM.

If you aren't willing to require D3D_FEATURE_LEVEL_12 hardware or 11_0/11_1 hardware that confirms it supports Typed UAV loads from the format you're interesting in (see CheckFeatureSupport / D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD) then you'll have to jump through some extra hoops...

If the underlying format of your UAV is R8G8B8A8_UNORM then you can create the resource in the R32_TYPELESS format and create a UAV in the format R32_UINT. From there you load a single 32-bit 'uint' in the shader, unpack 8-bit R,G,B and A separately, do your premultiply operation and pack it back into a uint again before writing it back to the UAV.

The two functions you're looking for in D3DX_DXGIFormatConvert.inl (seen here: https://github.com/apitrace/dxsdk/blob/master/Include/d3dx_dxgiformatconvert.inl) are:

XMFLOAT4 D3DX_R8G8B8A8_UNORM_to_FLOAT4(UINT packedInput)
UINT D3DX_FLOAT4_to_R8G8B8A8_UNORM(hlsl_precise XMFLOAT4 unpackedInput)

Include that header in your shader, unpack the uint to float4, do your operation and then repack it into a uint again and write it to the UAV.

If, later in your frame you want to read your R8G8B8A8_UNORM texture using an SRV (not a UAV) then you can create an SRV in the R8G8B8A8_UNORM format on top of the R32_TYPELESS texture you created earlier. This allows for useful things like sampling / filtering and avoiding the cost of unpacking a uint.

Resource Format: R32_TYPELESS
UAV Format: R32_UINT
SRV Format (optional): R8G8B8A8_UNORM

A similar explanation to the one I gave above is seen at the top of the d3dx_dxgiformatconvert.inl file.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

Thank you very much Adam Miles!

This topic is closed to new replies.

Advertisement