From daeba0cfb65ac1c126c9d89dad4056d497508752 Mon Sep 17 00:00:00 2001 From: Jeremy Hayes Date: Mon, 14 Aug 2023 11:17:00 -0600 Subject: [PATCH] [SPIRV] Add SM6.6 IsHelperLane (#5488) Fix #5427 --- .../include/clang/SPIRV/FeatureManager.h | 2 +- tools/clang/lib/SPIRV/DeclResultIdMapper.cpp | 1 + tools/clang/lib/SPIRV/SpirvEmitter.cpp | 29 +++++++++++++++++++ tools/clang/lib/SPIRV/SpirvEmitter.h | 4 +++ .../intrinsics.sm6_6.ishelperlane.hlsl | 13 +++++++++ .../intrinsics.sm6_6.ishelperlane.vk1p3.hlsl | 18 ++++++++++++ .../unittests/SPIRV/CodeGenSpirvTest.cpp | 6 ++++ 7 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 tools/clang/test/CodeGenSPIRV/intrinsics.sm6_6.ishelperlane.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/intrinsics.sm6_6.ishelperlane.vk1p3.hlsl diff --git a/tools/clang/include/clang/SPIRV/FeatureManager.h b/tools/clang/include/clang/SPIRV/FeatureManager.h index eb30682c63..c84c658da6 100644 --- a/tools/clang/include/clang/SPIRV/FeatureManager.h +++ b/tools/clang/include/clang/SPIRV/FeatureManager.h @@ -89,7 +89,7 @@ class FeatureManager { std::string getKnownExtensions(const char *delimiter, const char *prefix = "", const char *postfix = ""); - /// Rqeusts the given target environment for translating the given feature at + /// Request the given target environment for translating the given feature at /// the given source location. Emits an error if the requested target /// environment does not match user's target environemnt. bool requestTargetEnv(spv_target_env, llvm::StringRef target, SourceLocation); diff --git a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp index 5a2b9b3a3e..5194ae3e6d 100644 --- a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp +++ b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp @@ -3312,6 +3312,7 @@ SpirvVariable *DeclResultIdMapper::getBuiltinVar(spv::BuiltIn builtIn, spv::StorageClass sc = spv::StorageClass::Max; // Valid builtins supported switch (builtIn) { + case spv::BuiltIn::HelperInvocation: case spv::BuiltIn::SubgroupSize: case spv::BuiltIn::SubgroupLocalInvocationId: needsLegalization = true; diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index fa9549cbb5..feee58564d 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -8504,6 +8504,9 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) { retVal = spvBuilder.createLoad(retType, var, srcLoc, srcRange); needsLegalization = true; } break; + case hlsl::IntrinsicOp::IOP_IsHelperLane: + retVal = processIsHelperLane(callExpr, srcLoc, srcRange); + break; case hlsl::IntrinsicOp::IOP_WaveIsFirstLane: retVal = processWaveQuery(callExpr, spv::Op::OpGroupNonUniformElect); break; @@ -9161,6 +9164,32 @@ SpirvInstruction *SpirvEmitter::processWaveQuery(const CallExpr *callExpr, opcode, retType, spv::Scope::Subgroup, callExpr->getExprLoc()); } +SpirvInstruction *SpirvEmitter::processIsHelperLane(const CallExpr *callExpr, + SourceLocation loc, + SourceRange range) { + assert(callExpr->getNumArgs() == 0); + + if(!featureManager.isTargetEnvVulkan1p3OrAbove()) { + // If IsHelperlane is used for Vulkan 1.2 or less, we enable + // SPV_EXT_demote_to_helper_invocation extension to use + // OpIsHelperInvocationEXT instruction. + featureManager.allowExtension("SPV_EXT_demote_to_helper_invocation"); + + const QualType retType = callExpr->getCallReturnType(astContext); + return spvBuilder.createIsHelperInvocationEXT(retType, callExpr->getExprLoc()); + } + + // The SpreadVolatileSemanticsPass legalization pass will decorate the + // load with Volatile. + const QualType retType = callExpr->getCallReturnType(astContext); + auto *var = + declIdMapper.getBuiltinVar(spv::BuiltIn::HelperInvocation, retType, loc); + auto retVal = spvBuilder.createLoad(retType, var, loc, range); + needsLegalization = true; + + return retVal; +} + SpirvInstruction *SpirvEmitter::processWaveVote(const CallExpr *callExpr, spv::Op opcode) { // Signatures: diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.h b/tools/clang/lib/SPIRV/SpirvEmitter.h index b0a831305b..3cb0a9b3c7 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.h +++ b/tools/clang/lib/SPIRV/SpirvEmitter.h @@ -590,6 +590,10 @@ class SpirvEmitter : public ASTConsumer { /// Processes SM6.0 wave query intrinsic calls. SpirvInstruction *processWaveQuery(const CallExpr *, spv::Op opcode); + /// Processes SM6.6 IsHelperLane intrisic calls. + SpirvInstruction *processIsHelperLane(const CallExpr *, SourceLocation loc, + SourceRange range); + /// Processes SM6.0 wave vote intrinsic calls. SpirvInstruction *processWaveVote(const CallExpr *, spv::Op opcode); diff --git a/tools/clang/test/CodeGenSPIRV/intrinsics.sm6_6.ishelperlane.hlsl b/tools/clang/test/CodeGenSPIRV/intrinsics.sm6_6.ishelperlane.hlsl new file mode 100644 index 0000000000..aa7bb97c1f --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/intrinsics.sm6_6.ishelperlane.hlsl @@ -0,0 +1,13 @@ +// RUN: %dxc -T ps_6_0 -E main + +// CHECK-NOT: OpDecorate {{%\w+}} BuiltIn HelperInvocation + +float4 main() : SV_Target { + float ret = 1.0; + + if (IsHelperLane()) ret = 2.0; + + return ret; +} +// CHECK: [[HelperInvocation:%\d+]] = OpIsHelperInvocationEXT %bool +// CHECK: OpBranchConditional [[HelperInvocation]] diff --git a/tools/clang/test/CodeGenSPIRV/intrinsics.sm6_6.ishelperlane.vk1p3.hlsl b/tools/clang/test/CodeGenSPIRV/intrinsics.sm6_6.ishelperlane.vk1p3.hlsl new file mode 100644 index 0000000000..d293f5ac09 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/intrinsics.sm6_6.ishelperlane.vk1p3.hlsl @@ -0,0 +1,18 @@ +// RUN: %dxc -T ps_6_0 -E main -fspv-target-env=vulkan1.3 + +// CHECK: OpEntryPoint Fragment +// CHECK-SAME: %gl_HelperInvocation + +// CHECK: OpDecorate %gl_HelperInvocation BuiltIn HelperInvocation + +// CHECK: %gl_HelperInvocation = OpVariable %_ptr_Input_bool Input + +float4 main() : SV_Target { +// CHECK: [[val:%\d+]] = OpLoad %bool %gl_HelperInvocation +// CHECK: OpBranchConditional [[val]] + float ret = 1.0; + + if (IsHelperLane()) ret = 2.0; + + return ret; +} diff --git a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp index 9bd41a90a1..4188e17c89 100644 --- a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp +++ b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp @@ -1493,6 +1493,12 @@ TEST_F(FileTest, IntrinsicsSM66PackClampU8S8) { TEST_F(FileTest, IntrinsicsSM66Unpack) { runFileTest("intrinsics.sm6_6.unpack.hlsl"); } +TEST_F(FileTest, IntrinsicsSM66IsHelperLane) { + runFileTest("intrinsics.sm6_6.ishelperlane.hlsl"); +} +TEST_F(FileTest, IntrinsicsSM66IsHelperLaneVk1p3) { + runFileTest("intrinsics.sm6_6.ishelperlane.vk1p3.hlsl"); +} // For attributes TEST_F(FileTest, AttributeEarlyDepthStencil) {