My program behaves differently with and without layout(early_fragment_tests) in my fragment shader.
My fragment shader either writes out a pixel or discards, but I’m not writing to gl_FragDepth, I never use this variable in the code.
How can the result be different with and without early_fragment_tests enabled?
If you use atomic counters, image variables or shader storage buffers then early_fragment_tests has an effect:
a. If early_fragment_tests is used then no fragment shader invocations will be executed for those fragments that fail the depth or stencil test, thus atomic counter operations, image operations and shader storage buffer writes will not be performed for those fragments.
b. If early_fragment_tests is not used then there will be fragment shader invocations even for fragments that will eventually get discarded by the depth or stencil test, thus atomic counter operations, image operations and shader storage buffer writes will be performed for all fragments.
Other than that, there should be no difference. E.g. writes to framebuffer attachments will be identically performed in both cases.
I am not using atomics or image stores or loads in this shader, it is just a plain raster-or-discard routine.
I see that the problem happens only when discard has been called. Fragments that are behind a fragment that called discard are also discarded - I even see the background. It seems discarding the fragment still writes to the Z-buffer? Using 311.06 drivers. Weird
Same result with the latest 320.18 drivers.
I’m using FBO attachments, COLOR0 + DEPTH. Surely early_fragment_tests works correctly with these in place, I don’t see any reason why it wouldn’t?
early_fragment_tests doesn’t work with discard, period.
With early_fragment_tests disabled:
And now with early_fragment_tests enabled:
To perform my test, I did the following:
- Downloaded the following tutorial (Windows): http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php
- Modified vertexShader.txt:
#version 420 compatibility
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
// Add this line below
gl_TexCoord.st = gl_MultiTexCoord0.st;
- Modified fragmentShader.txt:
#version 420 compatibility
//Uncomment this line to see the effect of discard with this layout:
void main (void)
if (gl_TexCoord.y > 0.5)
gl_FragColor = vec4(gl_TexCoord.st, 0, 1);
Okay, now I know what’s your problem. You use discard to cull fragments, which actually works just fine, but you forget about that because you forced early tests depth test, and as a result the depth writes happen as well. that’s why your depth buffer will reflect the data as if no fragments were culled using discard.
This is actually the correct behavior. If you want discard to also prevent depth writes, not just color writes, you cannot use early_fragment_tests.
Very weird spec…
Also, in the code above with the teapot, does it mean the driver doesn’t do any form of Early-Z test when I’m not using layout(early_fragment_tests)?
What about Early-Z/Hyper-Z technologies that have been around in the last few years, much before early_fragment_tests was made available?
Even if you’re not using early_fragment_tests you still likely to get your early depth and stencil test (including Hi-Z) if you don’t modify depth in your fragment shader, just in that case depth and stencil writes might still get postponed after the fragment shader if e.g. the shader uses discard. Also, even when you modify depth in your fragment shader, if you use ARB_conservative depth, you still might get some early tests, but once again, writes happen only after the fragment shader.
To sum it up, unless you want to force depth-stencil tests and writes to be early (e.g. because you don’t want side effects to happen, like atomic counter, image or shader storage buffer operations, or want to write depth, but want to have the option to avoid color writes with discard) then you should not use early_fragment_tests, you should just rely on the driver/hardware to handle the potential of early test usage.
This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.