Jump to content
  • Advertisement
Sign in to follow this  
Akenre

How to access UAVs from any shader stage

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

Hi,

i am trying to find concrete info about the Directx 11.1 feature:

Unordered access views can be accessed from any shader stage

 

 

https://msdn.microsoft.com/en-us/library/windows/hardware/dn653328(v=vs.85).aspx

 

The name of the feature seems to imply that it is not necessary to bind uavs from C++ side for

additional shaders once it is bound to one shader, but i cannot verify if i misunderstood this.

In that case what register(s) would be used for that sharing of the uav?

 

What i am trying to do is to use a uav/RWByteAddressBuffer written to in a compute shader directly in a vertex shader for vertex, color, texture data without mapping the results and unnecessarily transferring the data between GPU and CPU.

However, even if that would have to be done from C++, there would be no directx device method available such as:

 

dc->VSSetUnorderedAccessViews()

 

I also cannot use a constant buffer slot because the bind-flags uav and constant buffer together are not allowed.

 

Has anyone succesfuly done this and could enlighten me on how to do this?

Thank you

Edited by Akenre

Share this post


Link to post
Share on other sites
Advertisement

IIRC the only way to bind UAV's in D3D11 is to the OM stage. With this feature, I assume every shader stage gets its UAV bindings from the OM stage. If my assumption is right, you'd bind them for your VS the same way that you'd usually bind them for a PS in vanilla D3D11.

 

However, yeah as mentioned by Syntac_, if your vertex shader does not need to write to the resource, then it should use a SRV (or IA-stage vertex buffer binding if the buffer contains per-vertex or per-instance data) instead of a UAV.

 

Note that D3D's **V's are just "views" of a particular resource - they are not the resource. One resource can have several views -- such as a UAV that's used by a compute shader, and an SRV used by a vertex shader.

Edited by Hodgman

Share this post


Link to post
Share on other sites

IIRC the only way to bind UAV's in D3D11 is to the OM stage. With this feature, I assume every shader stage gets its UAV bindings from the OM stage. If my assumption is right, you'd bind them for your VS the same way that you'd usually bind them for a CS in vanilla D3D11.

 

However, yeah as mentioned by Syntac_, if your vertex shader does not need to write to the resource, then it should use a SRV (or IA-stage vertex buffer binding if the buffer contains per-vertex or per-instance data) instead of a UAV.

 

Note that D3D's **V's are just "views" of a particular resource - they are not the resource. One resource can have several views -- such as a UAV that's used by a compute shader, and an SRV used by a vertex shader.

 

This is correct, UAVs bound at the OM stage are visible to the entire graphics pipeline. But do also be aware that you can't bind the same resource for input and output at the same time, so if your PS needs to use it as a UAV, then your VS can't bind it as an SRV - but it can access the same UAV slot.

Share this post


Link to post
Share on other sites

Thanks for the many answers.

 

I am trying Syntac's suggestion.

 

After the dispatch of the compute shader i "unbind" the buffer from the uav by passing a nullptr array to the view:

 

ID3D11UnorderedAccessView* ppUAViewnullptr[2] = { nullptr, nullptr };
dc->CSSetUnorderedAccessViews(0, 2, ppUAViewnullptr, nullptr);

 

 

Then this code is used:

 

D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc2;
ZeroMemory(&srvDesc2, sizeof(srvDesc2));
srvDesc2.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
srvDesc2.BufferEx.FirstElement = 0;
srvDesc2.Format = DXGI_FORMAT_R32_TYPELESS;
srvDesc2.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
srvDesc2.BufferEx.NumElements = NUM_ELEMENTS * 36 / 4; // 36 bytes Stride for raw buffer
ID3D11ShaderResourceView *ppSRVOut;
ZeroMemory(&ppSRVOut, sizeof(ppSRVOut));
 

m_device->CreateShaderResourceView(g_pBufResult, &srvDesc2, &ppSRVOut);

dc->VSSetShaderResources(0, 1, &SRView);

to bind the buffer to the shader resource view.

 

In the vertex shader i declare:

RWByteAddressBuffer patchInput : register(u1);

 

 

using u0 or t0 creates an exception:

 

 

D3D11 ERROR: ID3D11DeviceContext::DrawIndexed: The Vertex Shader unit expects an Unordered Access View at Slot 0, but the first 1 slots are currently used for Render Target Views. [ EXECUTION ERROR #2097374: DEVICE_DRAW_UNORDEREDACCESSVIEW_RENDERTARGETVIEW_OVERLAP]

 

 

 

The compiler output of  HLSL Shader Compiler in the Visual Studio Graphics Analyzer reads:

 

Resource Bindings:
//
// Name                                 Type  Format         Dim      HLSL Bind  Count
// ------------------------------ ---------- ------- ----------- -------------- ------
// patchInput                            UAV    byte         r/w             u1      1 
// cbPerFrame                        cbuffer      NA          NA            cb0      1 
 
However in the debugger of the vertex shader, i get
 

 

patchInput = Not set

 

when hovering over the raw buffer name.

 

And trying to read data from that raw buffer like so:

 

float p1 = asfloat(patchInput.Load(vertexId));

 

 

yields always:

 

p1 = 0.000000000

 

 

So it look like the buffer is not ending up in the correct slot due to the overlap issue for slot0.

Also the srv view desc might be incorrect.

Edited by Akenre

Share this post


Link to post
Share on other sites

You're using an RW buffer, which is a UAV. If you're following the SRV suggestion, then just remove the "RW" from the buffer declaration in the shader, and declare it in the 't' namespace.

Share this post


Link to post
Share on other sites

You're using an RW buffer, which is a UAV. If you're following the SRV suggestion, then just remove the "RW" from the buffer declaration in the shader, and declare it in the 't' namespace.

 

Jesse, thanks to your suggestion, i can now bind to t0 without exception using:

 

 

ByteAddressBuffer patchInput : register(t0);

 

Turns out that i used a wrong shader resource view reference, where it should have been

 

dc->VSSetShaderResources(0, 1, &ppSRVOut);

 

 

Thanks a lot for the help. I am able to use the buffer now in the vs.

Edited by Akenre

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!