Forums - Vulkan: discard/OpKill does not prevent early fragment tests

1 post / 0 new
Vulkan: discard/OpKill does not prevent early fragment tests
Join Date: 1 Jun 13
Posts: 1
Posted: Mon, 2018-06-18 11:53

This issue has been seen on Adreno 530 with latest drivers from Android 8.1.0 on a Pixel and ZTEE Axon 7.

When a fragment shader uses discard, it's not preventing stencil REPLACE operations.

Normally, fragment tests (depth/stencil, etc.) are optimized to be run early when possible.  Per Vulkan - 8.9.2 and Vulkan - 25.4, this should technically only happen when EarlyFragmentTests in in the shader (e.g. "layout(early_fragment_tests) in;")  This is true in Vulkan 1.0 and 1.1.

According to the Vulkan Programming Guide, it's acceptable for an implementation to enable it anyway, provided the shader doesn't write to depth, doesn't have side effects like image writes, and doesn't include OpKill.  However, OpKill at least is not properly being detected.

The scenario in which this happened was (possibly may occur in more scenarios):

  1. Depth test and depth bounds test disabled.
  2. Stencil test enabled.
  3. Stencil write mask, compare mask, and reference as dynamic state.
  4. Compare op ALWAYS.
  5. Depth fail, stencil fail, and stencil pass ops set to REPLACE.
  6. No attributes passed to vertex shader - using gl_VertexIndex to generate positions.
  7. Fragment shader conditionally or unconditionally calling discard / OpKill.

This bug does not occur on other implementations and appears Adreno specific.  A workaround has been applied to statically write to gl_FragDepth, which has fixed the issue.

For those curious as to why one would perform the above, it's basically used to upload stencil values (using 8 passes, one per bit.)  However, I suspect the issue would occur even in more general usage when stencil and discard are used together.  The same basic strategy works well through GLES on Adreno, where the discard is detected properly.

More details can be seen here:
(ignore the GLES issue - that was a bug in the code due to a recent refactor and was not Adreno specific.)


  • Up0
  • Down0

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries (“Qualcomm”). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.