GLSL discard behavior
Hello,
Since 93231001597dad1149a5d035af30eda50b9e6b6c (merged in 15.4.0), GLSL's discard now maps to OpDemoteToHelperInvocation instead of OpTerminateInvocation when targeting SPIR-V >= 1.6.
This change has already been discussed in #3954, but I would like to add a few more elements.
From the GLSL 4.60 specification, section 6.4. Jumps, about the discard keyword:
Control flow exits the shader, and subsequent implicit or explicit derivatives are undefined when this control flow is non-uniform
This sentence seems to describe the behavior of OpTerminateInvocation, as opposed to OpDemoteToHelperInvocation.
Also, from the specification of VK_KHR_shader_terminate_invocation:
OpTerminateInvocation provides the behavior required by the GLSL discard statement, and should be used when available by GLSL compilers and applications that need the GLSL discard behavior.
So from what I understand, mapping discard to OpTerminateInvocation was indeed the expected behavior, at least according to the specification.
I understand that the ambiguity of discard may cause bugs in applications, but isn't that why GLSL_EXT_demote_to_helper_invocation and GL_EXT_terminate_invocation were introduced ? The latter states:
It is recommended that programmers use demote [...] or terminateInvocation instead of discard.
Is it reasonable for glslang to deviate from the GLSL, VK and EXTs specifications on this point? Am I missing something?
While that is indeed what the spec says, in practice every Mesa driver sets discard_is_demote so the options for glslang were to continue emitting OpKill which then gets translated into a demote, or else actually emit TerminateInvocation which changes the behavior of existing shader code and results in brokenness.
Thank you for your answer.
I understand the issue with MESA drivers, and the necessity to be able to match the behavior they introduced in https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27617/commits
But what about drivers from other vendors?
In my experience, OpenGL drivers from major vendors always treat discard as a "terminate" operation.
So when porting OpenGL applications to Vulkan and using glslang for shader code compatibility, there will also be a change of behavior.
What about adding an option in glslang similar to MESA's discard_is_demote, so that applications can choose which behavior they want? (keeping the default to "demote" for compatibility with MESA)
I can do the PR.
I think it would be a reasonable thing to add as a command-line option (and you would also have to expose it via the C and C++ API).