[D3D12] Avoid waiting on a Fence for depth prepass

Started by
3 comments, last by Funkymunky 8 years, 8 months ago

I've got a decent setup going. I track N frames (currently 2); I generate all my draw calls on a thread, then submit them to a CommandQueue and signal that frame's fence. Then I switch to the next frame and do the same procedure, so that I'm constantly generating draw calls and never waiting for any substantial time on the GPU to finish.

Now I want to do a depth prepass, and I'm struggling to figure out how to do so without waiting. First I'd submit my drawcalls for the depth prepass, but then I'd have to wait until it completed before submitting my drawcalls that use the results. Since the signalling the fence sets a point in the queue that you can wait for, I'd essentially by lockstepping each frame.

Should I make a separate CommandQueue that's only responsible for the depth prepass? Or is there some other aspect that I'm missing?

Advertisement

There's no need to insert any sort of wait after submitting the commands for your depth prepass before submitting the commands for your "main pass", at least from a GPU synchronisation perspective.

When you say you'd have to wait until it completed "before submitting my drawcalls that use the results"; what exactly do you mean by "use the results"? If you mean you want your depth prepass to act as a means by which the GPU's overdraw is near 1, then you need to do nothing with fences or barriers whatsoever. However if you mean you want to read back the GPU's depth prepass to the CPU for some means (like CPU occlusion culling?) then that's a different matter.

Could you explain if your requirements are anything more complicated than the standard behaviour of "draw everything to depth only then draw everything with proper pixel shaders"?

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

I guess I misspoke, I'm really intending to render depth/normals for use in a tiled rendering setup. Or, in a similar way, if I wanted to render deferred and needed to generate my G-Buffer before assembling my final scene. So I would have to render to a texture, and then I thought I'd have to wait until I knew that had completed before I could read that data in another shader.

Nope, fortunately things are a little easier than that. Take a look at the ID3D12GraphicsCommandList::ResourceBarrier. You simply need to transition the resources (in this case, Render Targets) from being in the state D3D12_RESOURCE_STATE_RENDER_TARGET to D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE (D3D12_RESOURCE_STATE_GENERIC_READ will probably work too).

This way any flushes that need to be inserted by the driver to allow safe reading of these resources as shader resource views after being used as render targets can be inserted.

You probably have similar code to transition the buffers on a swap chain in and out of the "PRESENT" state, you merely need to do the same for any other resource you render to.

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

Oh damn, of course. Thanks!

This topic is closed to new replies.

Advertisement