Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

As a DirectX noob i'm trying to wrap my head around depth buffers and specifically how pixel shaders are called for obscured pixels.

From what i understand, the rasterizer calls the pixel shader for each pixel that is covering the primitive beeing drawn, then later in the output merger stage, the output merger checks the depth buffer and either discards, writes or blends the pixel in the back buffer.

This seems wasteful though if i'm rendering a simple opaque object in front of a very complex one, so it seems it would be useful to have the rasterizer check the depthmap Before even calling the pixel shaders for the complex object.

Doing research i've found references to early Z test / conservative Z testing and so on, but there also seems to be very little documentation about it. i looked for a way to configure that on the rasterizer state desc object, but i only found anything like that on the OM state desc.

It also seems like this was possible to set with SetRenderState in DX9 (i have no experience with DX9 either though)

From my research it seems like this is something some hardware just does if i render objects front to back, is that correct? How can i even tell? With all the Control DirectX gives you it seems weird that there is no control over this, as it seems to be a good optimization :)

Any info or references on this is appriciated

share|improve this question

1 Answer 1

up vote 2 down vote accepted

It's completely automatic, so long as you don't do anything that might implicitly disable it.

Early Z and such are hardware optimizations, meaning that they're things hardware might do and are allowed to do or not to do as the result of early Z has no effect on the rendered image other than speed. It's similar to how a compiler or even CPU is allowed to transform or reorder your code so long as it doesn't change the actual output (assuming you don't rely on some specific result from undefined behaviour). This is the so called "as-if" rule, which is a formal part of some language specifications and just an informal/implicit rule of most other languages and APIs. Your role as an API users is simply to avoid doing things that might stop the hardware from using its optimizations rather than explicitly opting in or opting out.

For each pixel (fragment), the rasterizer will have already computed a "default" depth. This depth value is tested before the pixel shader is run. If the depth test fails (the pixel is obscured) then the pixel shader is not run. All automatic.

This is disabled if you do things like modify the depth output semantic in the pixel shader. In this case, the rasterizer doesn't know what depth to use until after it runs the pixel shader, so it can't do early Z culling.

A related topic is hierarchical Z. With this feature, the GPU takes advantage of the fact that most pixels drawn are part of a larger primitive and all other pixels nearby will be part of that same primitive and be at a relatively similar depth. Also, the primitive being drawn typically either fully obscures other primitives drawn or is itself fully obscured. Hierarchical Z breaks the scene into sub-regision, recursively, in an approach reminiscent of mipmaps (might even be the same thing on some hardware). In each lower layer of this hierarchy, the Z buffer stores only the furthest depth value (assuming you're using the standard depth scheme). Before testing a specific pixel's depth, the hierarchy is traversed downward. If any part of the hierarchy fails, the GPU knows that any pixel in that entire chunk would obscure the pixel being processed so it is culled. The hierarchy allows less depth value updates, tighter memory access, and so on, which account for sometimes significant drawing advantages. This feature is again free so long as you don't use weird depth setups or draw in crazy ways that would subvert the assumptions the algorithm is based on.

share|improve this answer
    
Great awnser, thanks :) –  aL3891 Jul 27 '13 at 17:53
    
So using the depth semantic is how Dx knows i modify the depth? i wonderd how that worked :) –  aL3891 Jul 27 '13 at 17:58
1  
Using it as an output parameter, yeahy. Again, it's a driver/hardware "hidden" optimization, so it's not really defined, but that's the most obvious and direct way for them to detect it. In OpenGL, the driver generally just checks during shader compilation if you assign to gl_Depth, which is OpenGL's equivalent to using semantics. –  Sean Middleditch Jul 27 '13 at 18:05
1  
@SeanMiddleditch: That sounds more like conservative depth, rather than an enforced depth test. It's a hint you use so that early depth can still happen even if you change the depth, because you promise not to make it smaller or larger than the original. –  Nicol Bolas Jul 27 '13 at 20:54
2  
[earlydepthstencil] - see msdn.microsoft.com/en-us/library/windows/desktop/… –  Darth Satan Jul 27 '13 at 21:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.