Shouldn't the depth-test stop occluded pixels from being shaded?

Started by
6 comments, last by mind in a box 10 years, 4 months ago

Hi!

From what I know, the GPU shouldn't run a pixel shader for a pixel which already failed the depth-test, right?

We're developing a mobile game for WindowsPhone8 at the moment, using Direct3D11. To save some performance we created some geometry which we render behind the planes of our HUD, to not waste shading power to the pixels which will get occluded by our hud at the end anyways.

So what we are basically doing is the following:

  • Render HUD-Masks
  • Render World
  • Render HUD

When disabling the HUD we can see indeed that the pixels would not get into our backbuffer, but even when I let the Masks occlude the whole screen, we do not see any improvement of performance, which should be the case because reducing the resolution drastically improves it. So since we are pixelshader-bound like it seems, why isn't there any improvement? Did we maybe just miss some flag which disables depth-culling?

Or is this just unsupported on mobile GPUs?

Thanks in advance.

Advertisement

The most likely cause of this is that you don't have depth-writing enabled when drawing your HUD masks. If that's the case, the depth buffer will still contain the clear value after drawing them, so the depth test for the scene will be as if they hadn't been drawn.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Alphatest and texkill/discard instructions in the pixel shader will disable early-z. Are you using either of those features?

I think alphatest could be enabled when rendering those, I've seen something like this in my code but thought since the vaules are written into the depth-buffer the early-z test will be used anyways. I'll check that later :)

Early-Z optimizations are hardware-specific, and aren't actually part of the D3D pipeline. The spec basically says that the depth test only has to prevent the pixel values from being written to the current render target, not that the pixel shader shouldn't be run. The drivers will therefore only enable early-z optimizations for cases where using it would produce the same render target results as if the optimization weren't used. The conditions that allow the driver to enable early-z are dependent on the exact GPU being used, so you should consult vendor-specific programming guides to know for sure.

In your case you're running on mobile hardware, which typically uses some variant of TBDR. These GPU's will usually always have use early-z, unless you use alpha test or exporting depth from the pixel shader.

I don't know, I disabled alphablending now, but it doesn't help. Maybe I'll just go with the stencil-buffer, even though I've never used it before, but I think this is what it is for?

I'm assuming you HUD is not fully opaque, if the HUD is being blended in as an overlay ( this indicates some for of transparency ), then there will be no pixels that are fully occluded. Depending on the blend mode, the actually framebuffer content at the currently fragment location will be needed for the blend operation. Unless the HUD is fully opaque, in which case setting the depth value of the HUD fragments to the near clip plane value and rendering the HUD first will cause the occluded fragments to fail the depth test. All this is nought if like several other posted above if hi-z or early-z is disabled for whatever reason.

We created some meshes which roughly cover the area of our HUD-Elements (Because they have a small fade at the sides) which we are rendering instead of the actual HUD-Elements.

These are the first Objects to render in the whole frame, so what could disable my early-z in such a case?

This topic is closed to new replies.

Advertisement