spirv: optionally emit nir_demote instead of nir_discard for OpKill
This MR is an attempt to start cleaning up the mess that we call discard.
The semantics of discard differ between GLSL and HLSL and their various implementations.
Subsequently, numerous of application bugs occurred and SPV_EXT_demote_to_helper_invocation
was written in order to clarify the behavior. In NIR, we now have 3 different intrinsics for 2 things,
and while demote
and terminate
have clear semantics, discard
still doesn't.
Therefore, I'd like to entirely remove nir_intrinsic_discard:
- For Vulkan, the spec states that the behavior of OpKill is implementation defined:
The OpTerminateInvocation instruction, along with the OpDemoteToHelperInvocation instruction from the VK_EXT_shader_demote_to_helper_invocation extension, together replace the OpKill instruction, which could behave like either of these instructions.
I think, because of game bugs, the default behavior should be demote. - For GLSL, I think the situation is comparable as radeonSI lowers discard to demote by default. For this MR, I left it unchanged.
I also added a patch to make gl_HelperInvocation
always volatile. Although this is the replacement for OpIsHelperInvocationEXT
, currently, there is no GLSL support and application bugs are likely.
These changes should be pretty much in line with what Nvidia and AMD do in their proprietary drivers.
v2: Make it optional instead of unconditional.