KhronosGroup / Vulkan-Docs

The Vulkan API Specification and related tools
Other
2.7k stars 452 forks source link

[Roadmap Feedback] Discarding fragments before early depth testing #2334

Closed ntsh-oni closed 3 months ago

ntsh-oni commented 3 months ago

Problem statement:

Some materials use textures with texels that must not be rendered and an alpha cutoff value (see: for example: glTF™ 2.0 Specification - 3.9.4. Alpha Coverage). One way to manage these textures is to read the texel in a fragment shader, use this alpha cutoff value, and if the alpha value of the texel is inferior to the alpha cutoff value, the fragment gets discarded.

The main issue with this method is that the discard statement in GLSL, or OpTerminateInvocation in SPIR-V, may deactivate early depth testing:

Similarly, if the fragment shader discards the fragment with the discard keyword, this will almost always turn off early depth tests on some hardware. Note that even conditional use of discard will mean that the FS will turn off early depth tests.

This lack of depth testing due to the presence of discard in a fragment shader can have a great impact on performance.

Use Case Example(s):

Using discard to discard fragments when rendering any object that may use a material that uses alpha cutoff is quite common, for example : billboards (quads facing the camera), tree leaves, bushes, flowers, ...

It also impacts shadow mapping, as the depth value of the fragments that should be discarded should not appear on the shadow map.

(Optional) Suggested Solution(s) (via opening an MR on vulkan-docs repo and creating a Proposal Document) :

Being able to specify an opacity image (R8/R16/R32), a alpha cutoff value and a way to access uv values would allow the device to not emit fragments during the rasterization step if the texel's value is inferior to the alpha cutoff value, removing the use of the OpTerminateInvocation statement and the performance loss of missing early depth testing.

ntsh-oni commented 3 months ago

After profiling today, I didn't see any performance hit with or without discard (test consisted of 50 planes one behind each other), the issue is closed. The issue appeared clearly on my Nvidia GTX 1060 a few months ago but I can't see anything telling that having discard in a shader is enough to turn off early depth testing completely, at least on my Nvidia RTX 4070.