Jump to content
  • Advertisement
pcmaster

DX12 Unbind UAV, then write to it - DX 11 vs 12

Recommended Posts

Hello!

I can see that when there's a write to UAVs in CS or PS, and I bind a null ID3D11UnorderedAccessView into a used UAV slot, the GPU won't hang and the writes are silently dropped. I hope I amn't dreaming.

With DX12, I can't seem to emulate this. I reckon it's impossible. The shader just reads the descriptor of the UAV (from a register/offset based on the root signature layout) and does an "image_store" at some offset from the base address. If it's unmapped, bang, we're dead. I tried zeroing out that GPU visible UAV's range in the table, same result. Such an all-zero UAV descriptor doesn't seem very legit. That's expected.

Am I right? How does DX11 do it that it survives this? Does it silently patch the shader or what? Thanks, .P

Edited by pcmaster

Share this post


Link to post
Share on other sites
Advertisement

How did you zero it out? Did you call ZeroMemory (or similar) on the CPU descriptor handle? That's... not the right way to do it. What you're looking for is a null view. You can call CreateUnorderedAccessView with a null resource, but you must pass a valid view desc. That'll set up the descriptor such that reads return 0 (or last-written data, depending on architecture) and writes are dropped.

Share this post


Link to post
Share on other sites

Hi, SoL! I was looking exactly for this, is it actually documented anywhere? :) I'm on an unnamed architecture where I could do a memset... as I say it didn't seem very legit. I'm just trying what you propose.

Share this post


Link to post
Share on other sites

It does work!

D3D12_UNORDERED_ACCESS_VIEW_DESC dummyUavDesc = {};
dummyUavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
dummyUavDesc.Texture3D.FirstWSlice = 0;
dummyUavDesc.Texture3D.MipSlice = 0;
dummyUavDesc.Texture3D.WSize = 2048;
dummyUavDesc.Format = DXGI_FORMAT_R8G8B8A8_SNORM;
pD3D12Device->CreateUnorderedAccessView(nullptr, nullptr, &dummyUavDesc, cpuHandle);

CreateUnorderedAccessView writes all zeroes to the cpuHandle designated memory. CopyDescriptors() copies the zeroes correctly to the contiguous GPU visible descriptor table and the GPU recognises this. All cool. Thank you SoL!

 

Edited by pcmaster

Share this post


Link to post
Share on other sites
On 11/28/2017 at 8:02 AM, pcmaster said:

Hi, SoL! I was looking exactly for this, is it actually documented anywhere? I'm on an unnamed architecture where I could do a memset... as I say it didn't seem very legit. I'm just trying what you propose.

It's mentioned in the docs for CreateUnorderedAccessView:

At least one of pResource or pDesc must be provided. A null pResource is used to initialize a null descriptor, which guarantees D3D11-like null binding behavior (reading 0s, writes are discarded), but must have a valid pDesc in order to determine the descriptor type.

It's also mentioned here in the programming guide.

One thing to watch out for is there's no way to have a NULL descriptor for a UAV or SRV  that's bound as a root SRV/UAV parameter. In this case there's really no descriptor (you're just passing a GPU pointer to the buffer data), so you forego any bounds checking on reads or writes. Just like raw pointer access on the CPU, reading or writing out-of-bounds will result in undefined behavior.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • 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!