VK_EXT_shader_demote_to_helper_invocation support
This extension adds Vulkan support for the
SPV_EXT_demote_to_helper_invocation SPIR-V extension. That
SPIR-V extension provides a new instruction
OpDemoteToHelperInvocationEXT allowing shaders to “demote”
a fragment shader invocation to behave like a helper
invocation for its duration. The demoted invocation will
have no further side effects and will not output to the
framebuffer, but remains active and can participate in
computing derivatives and in group operations. This is a
better match for the “discard” instruction in HLSL.
Tests: dEQP-VK.rasterization.frag_side_effects.*.demote
Tests: dEQP-VK.glsl.demote.*
Tests: dEQP-VK.glsl.discard.*
Bug: b/204502919
Change-Id: I2a1d5ab2cda5a4f57ef9798861e3ea915c39c20c
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/64408
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index d6b5546..24bc4c6 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -257,6 +257,10 @@
}
break;
+ case spv::OpDemoteToHelperInvocation:
+ analysis.ContainsKill = true;
+ break;
+
case spv::OpLoopMerge:
case spv::OpSelectionMerge:
break; // Nothing to do in analysis pass.
@@ -441,6 +445,7 @@
case spv::CapabilityGroupNonUniformShuffleRelative: capabilities.GroupNonUniformShuffleRelative = true; break;
case spv::CapabilityDeviceGroup: capabilities.DeviceGroup = true; break;
case spv::CapabilityMultiView: capabilities.MultiView = true; break;
+ case spv::CapabilityDemoteToHelperInvocation: capabilities.DemoteToHelperInvocation = true; break;
case spv::CapabilityStencilExportEXT: capabilities.StencilExportEXT = true; break;
case spv::CapabilityVulkanMemoryModel: capabilities.VulkanMemoryModel = true; break;
case spv::CapabilityVulkanMemoryModelDeviceScope: capabilities.VulkanMemoryModelDeviceScope = true; break;
@@ -748,6 +753,7 @@
case spv::OpCopyObject:
case spv::OpCopyLogical:
case spv::OpArrayLength:
+ case spv::OpIsHelperInvocationEXT:
// Instructions that yield an intermediate value or divergent pointer
DefineResult(insn);
break;
@@ -795,6 +801,7 @@
if(!strcmp(ext, "SPV_KHR_variable_pointers")) break;
if(!strcmp(ext, "SPV_KHR_device_group")) break;
if(!strcmp(ext, "SPV_KHR_multiview")) break;
+ if(!strcmp(ext, "SPV_EXT_demote_to_helper_invocation")) break;
if(!strcmp(ext, "SPV_EXT_shader_stencil_export")) break;
if(!strcmp(ext, "SPV_KHR_float_controls")) break;
if(!strcmp(ext, "SPV_KHR_integer_dot_product")) break;
@@ -2087,6 +2094,12 @@
case spv::OpKill:
return EmitKill(insn, state);
+ case spv::OpDemoteToHelperInvocation:
+ return EmitDemoteToHelperInvocation(insn, state);
+
+ case spv::OpIsHelperInvocationEXT:
+ return EmitIsHelperInvocation(insn, state);
+
case spv::OpImageSampleImplicitLod:
case spv::OpImageSampleExplicitLod:
case spv::OpImageSampleDrefImplicitLod: