diff options
| author | Darren Wihandi <65404740+fairywreath@users.noreply.github.com> | 2025-03-21 10:31:07 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-21 22:31:07 +0800 |
| commit | 16ac0efa3e1e834e3b12af8ac34cf47a6418bb34 (patch) | |
| tree | 1761fd5fa7186a3e9881be79b5ef9df6527f3a45 | |
| parent | 32a5bd2f43d55453bb5ea15c888c7a90730bbcff (diff) | |
Apply pixel interlock execution mode to entry-point functions only (#6661)
Co-authored-by: Ellie Hermaszewska <ellieh@nvidia.com>
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 64 | ||||
| -rw-r--r-- | tests/pipeline/rasterization/fragment-shader-interlock-child-function.slang | 31 |
2 files changed, 67 insertions, 28 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 266f3b7e9..8ecbe1bc7 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -3640,35 +3640,20 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex } case kIROp_RequireMaximallyReconverges: - if (auto entryPointsUsingInst = - getReferencingEntryPoints(m_referencingEntryPoints, getParentFunc(inst))) - { - ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_maximal_reconvergence")); - for (IRFunc* entryPoint : *entryPointsUsingInst) - { - requireSPIRVExecutionMode( - nullptr, - getIRInstSpvID(entryPoint), - SpvExecutionModeMaximallyReconvergesKHR); - } - } + ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_maximal_reconvergence")); + requireSPIRVExecutionModeOnReferencingEntryPoints( + nullptr, + getParentFunc(inst), + SpvExecutionModeMaximallyReconvergesKHR); break; case kIROp_RequireQuadDerivatives: - if (auto entryPointsUsingInst = - getReferencingEntryPoints(m_referencingEntryPoints, getParentFunc(inst))) - { - ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_quad_control")); - requireSPIRVCapability(SpvCapabilityQuadControlKHR); - for (IRFunc* entryPoint : *entryPointsUsingInst) - { - requireSPIRVExecutionMode( - nullptr, - getIRInstSpvID(entryPoint), - SpvExecutionModeQuadDerivativesKHR); - } - } + ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_quad_control")); + requireSPIRVCapability(SpvCapabilityQuadControlKHR); + requireSPIRVExecutionModeOnReferencingEntryPoints( + nullptr, + getParentFunc(inst), + SpvExecutionModeQuadDerivativesKHR); break; - case kIROp_Return: if (as<IRReturn>(inst)->getVal()->getOp() == kIROp_VoidLit) result = emitOpReturn(parent, inst); @@ -3691,9 +3676,9 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex case kIROp_BeginFragmentShaderInterlock: ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_fragment_shader_interlock")); requireSPIRVCapability(SpvCapabilityFragmentShaderPixelInterlockEXT); - requireSPIRVExecutionMode( + requireSPIRVExecutionModeOnReferencingEntryPoints( nullptr, - getIRInstSpvID(getParentFunc(inst)), + getParentFunc(inst), SpvExecutionModePixelInterlockOrderedEXT); result = emitOpBeginInvocationInterlockEXT(parent, inst); break; @@ -8280,6 +8265,29 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex } } + // Applies execution mode to entry points that reference `childFunc`. + template<typename... Operands> + void requireSPIRVExecutionModeOnReferencingEntryPoints( + IRInst* parentInst, + IRFunc* childFunc, + SpvExecutionMode executionMode, + const Operands&... ops) + { + + if (auto entryPointsUsingInst = + getReferencingEntryPoints(m_referencingEntryPoints, childFunc)) + { + for (IRFunc* entryPoint : *entryPointsUsingInst) + { + requireSPIRVExecutionMode( + parentInst, + getIRInstSpvID(entryPoint), + executionMode, + ops...); + } + } + } + SPIRVEmitContext(IRModule* module, TargetProgram* program, DiagnosticSink* sink) : SPIRVEmitSharedContext(module, program, sink), m_irModule(module), m_memoryArena(2048) { diff --git a/tests/pipeline/rasterization/fragment-shader-interlock-child-function.slang b/tests/pipeline/rasterization/fragment-shader-interlock-child-function.slang new file mode 100644 index 000000000..65dc39bdc --- /dev/null +++ b/tests/pipeline/rasterization/fragment-shader-interlock-child-function.slang @@ -0,0 +1,31 @@ +//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry main -stage fragment + +RasterizerOrderedTexture2D<float4> texture; + +// +// Tests that an interlock region place at a non-entry point function will properly apply the SPIRV execution mode +// to the entry point function and not the child function. +// + +// CHECK: OpEntryPoint +// CHECK: OpExecutionMode %main PixelInterlockOrderedEXT + +float4 foo(float4 coords) +{ + float4 result; + + beginInvocationInterlock(); + { + result = texture[uint2(coords.xy)]; + texture[uint2(coords.xy)] = result + coords; + } + endInvocationInterlock(); + + return result; +} + +[shader("fragment")] +float4 main(float4 coords : COORDS) : SV_Target +{ + return foo(coords); +} |
