Downsampling a depth stencil buffer

Started by
5 comments, last by Reitano 7 years, 1 month ago

Is it possible in DirectX 11 to downsample a depth stencil buffer, and then re-bind it again as a read-only depth stencil buffer ? I only managed to bind it as a shader resource view but I would like, if possible, to take advantage of early depth culling and the stencil buffer. The use case is volumetric effects, rendered at half resolution, although the question is relevant to lower res rendering in general.

Advertisement

Writing to a depth buffer is as easy as writing to "SV_DEPTH" in a pixel shader rather than "SV_TARGETx". Bind the high resolution depth buffer as an SRV, bind a lower resolution one as your depth buffer, and then perform whatever operation you feel appropriate for downsampling (e.g. Max, Min, Average etc).

Downsampling Stencil is a little bit more tricky. Until recently the only way to write a specific Stencil value was to set the Stencil Ref value in the Depth Stencil State and then draw a full-screen quad to the depth buffer and kill any pixels where you didn't want that value written. You could do that 256 times, once per possible stencil ref value, but it's quicker to do it in only 8 passes by writing a single bit at a time. By setting the StencilWriteMask, each pass can write a different bit. Of course if you know you don't use high values in the stencil buffer you can stop after as many bits as you use.

In DX11.3 and DX12 there's optional GPU support for SV_STENCILREF in the pixel shader. With this you can issue just a single full screen quad, use OP_REPLACE and set the stencil reference value in the pixel shader the same way you would with SV_DEPTH. Whether you go this route or not depends on whether you want to limit yourself to Windows 10 and if your GPU supports it.

https://msdn.microsoft.com/de-de/library/windows/desktop/dn879499(v=vs.85).aspx

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

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

But on the early depth testing thing, you are probably driver doomed. Only on consoles we have the control to redo the early depth data after things like depth downscale. On PC, usually, driver just can't figure the case.

You shouldn't have any problem getting "EarlyZ", even on PC. What you're unlikely to be able to take advantage of is HiZ (Hierarchical Z) since that's generated on the fly as the triangles pass through the GPU. Writing to SV_DEPTH defeats that process.

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

You shouldn't have any problem getting "EarlyZ", even on PC. What you're unlikely to be able to take advantage of is HiZ (Hierarchical Z) since that's generated on the fly as the triangles pass through the GPU. Writing to SV_DEPTH defeats that process.

HiZ IS EarlyZ, at least on AMD, nVidia system is called zCull. It is possible to ReZ the HiZ on AMD by doing a fullscreen pass with custom states ( on console, not PC unless they detect a case and do it in the driver for you), and this give you a farZ value for early reject ( sacrificing the early accept but it is less important ).

HiZ and EarlyZ are two separate concepts on AMD cards. You can have EarlyZ without HiZ.

HiZ is a coarse, tiled-based acceptance/rejection of 8x8 tiles of pixels using the HTile metadata surface. HTile stores Min/Max per tile as well as compression related data. If an entire tile is > Max, then it can be rejected without performing a fine-rate depth test. If an entire incoming tile is < Min, the entire tile can be accepted without performing a fine-rate depth test.

EarlyZ is the ability to cull pixels before the pixel shader and is not reliant on HTile/HiZ being used or allocated.

LateZ is depth testing after the pixel shader and is again unrelated to HiZ.

"ReZ the HiZ" doesn't make sense. ReZ is a combination of Early Test and Late Test+Write. You're talking about resummarising the HiZ, which is what you can't do on PC.

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

Thank you for the information. I will profile the use of SV_Depth and see what overhead and performance savings brings to my scenes. Manually rejecting pixels in the pixel shader with dynamic branching might be good enough but we'll see.

Related: what is the granularity of depth and stencil rejection on recent GPUs ? And would it be more efficient to use both in cases where one suffices ? For example, draw the sky on pixels whose depth == 1 AND stencil == skyRef instead of only depth == 1.

This topic is closed to new replies.

Advertisement