diff --git a/include/dxc/HlslIntrinsicOp.h b/include/dxc/HlslIntrinsicOp.h index 7541cdac8f..e342255f2d 100644 --- a/include/dxc/HlslIntrinsicOp.h +++ b/include/dxc/HlslIntrinsicOp.h @@ -226,6 +226,9 @@ enum class IntrinsicOp { IOP_AcceptHitAndEndSearch, #endif // ENABLE_SPIRV_CODEGEN #ifdef ENABLE_SPIRV_CODEGEN IOP_VkReadClock, +#endif // ENABLE_SPIRV_CODEGEN +#ifdef ENABLE_SPIRV_CODEGEN + IOP_Vkext_execution_mode, #endif // ENABLE_SPIRV_CODEGEN MOP_Append, MOP_RestartStrip, diff --git a/lib/HLSL/HLOperationLower.cpp b/lib/HLSL/HLOperationLower.cpp index e3948cd6b9..7c4d2217f1 100644 --- a/lib/HLSL/HLOperationLower.cpp +++ b/lib/HLSL/HLOperationLower.cpp @@ -5662,6 +5662,7 @@ IntrinsicLower gLowerTable[] = { #ifdef ENABLE_SPIRV_CODEGEN { IntrinsicOp::IOP_VkReadClock, UnsupportedVulkanIntrinsic, DXIL::OpCode::NumOpCodes }, { IntrinsicOp::IOP_VkRawBufferLoad, UnsupportedVulkanIntrinsic, DXIL::OpCode::NumOpCodes }, + { IntrinsicOp::IOP_Vkext_execution_mode, UnsupportedVulkanIntrinsic, DXIL::OpCode::NumOpCodes }, #endif // ENABLE_SPIRV_CODEGEN {IntrinsicOp::MOP_Append, StreamOutputLower, DXIL::OpCode::EmitStream}, {IntrinsicOp::MOP_RestartStrip, StreamOutputLower, DXIL::OpCode::CutStream}, diff --git a/tools/clang/include/clang/Basic/Attr.td b/tools/clang/include/clang/Basic/Attr.td index 8a61731fc2..9a0e89a32c 100644 --- a/tools/clang/include/clang/Basic/Attr.td +++ b/tools/clang/include/clang/Basic/Attr.td @@ -1050,6 +1050,14 @@ def VKExtensionExt : InheritableAttr { let Documentation = [Undocumented]; } +def VKStorageClassExt : InheritableAttr { + let Spellings = [CXX11<"vk", "ext_storage_class">]; + let Subjects = SubjectList<[Var, ParmVar], ErrorDiag>; + let Args = [UnsignedArgument<"stclass">]; + let LangOpts = [SPIRV]; + let Documentation = [Undocumented]; +} + // Global variables that are of struct type def StructGlobalVar : SubsetSubjecthasGlobalStorage() && S->getType()->isStructureType()}]>; diff --git a/tools/clang/include/clang/SPIRV/SpirvBuilder.h b/tools/clang/include/clang/SPIRV/SpirvBuilder.h index 263d900374..3b68ee00ca 100644 --- a/tools/clang/include/clang/SPIRV/SpirvBuilder.h +++ b/tools/clang/include/clang/SPIRV/SpirvBuilder.h @@ -554,8 +554,10 @@ class SpirvBuilder { llvm::StringRef content = ""); /// \brief Adds an execution mode to the module under construction. - inline void addExecutionMode(SpirvFunction *entryPoint, spv::ExecutionMode em, - llvm::ArrayRef params, SourceLocation); + inline SpirvInstruction *addExecutionMode(SpirvFunction *entryPoint, + spv::ExecutionMode em, + llvm::ArrayRef params, + SourceLocation); /// \brief Adds an OpModuleProcessed instruction to the module under /// construction. @@ -854,12 +856,15 @@ SpirvBuilder::setDebugSource(uint32_t major, uint32_t minor, return mainSource->getFile(); } -void SpirvBuilder::addExecutionMode(SpirvFunction *entryPoint, - spv::ExecutionMode em, - llvm::ArrayRef params, - SourceLocation loc) { - mod->addExecutionMode( - new (context) SpirvExecutionMode(loc, entryPoint, em, params, false)); +SpirvInstruction * +SpirvBuilder::addExecutionMode(SpirvFunction *entryPoint, spv::ExecutionMode em, + llvm::ArrayRef params, + SourceLocation loc) { + auto mode = + new (context) SpirvExecutionMode(loc, entryPoint, em, params, false); + mod->addExecutionMode(mode); + + return mode; } } // end namespace spirv diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.cpp b/tools/clang/lib/SPIRV/SpirvEmitter.cpp index 1aaf18f158..fad9ef5cda 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.cpp +++ b/tools/clang/lib/SPIRV/SpirvEmitter.cpp @@ -1659,8 +1659,11 @@ void SpirvEmitter::doVarDecl(const VarDecl *decl) { needsLegalization = true; } - if (var != nullptr) { + if (var != nullptr && decl->hasAttrs()) { declIdMapper.decorateVariableWithIntrinsicAttrs(decl, var); + if (auto attr = decl->getAttr()) { + var->setStorageClass(static_cast(attr->getStclass())); + } } // All variables that are of opaque struct types should request legalization. @@ -7634,8 +7637,13 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) { case hlsl::IntrinsicOp::IOP_VkReadClock: retVal = processIntrinsicReadClock(callExpr); break; +<<<<<<< HEAD case hlsl::IntrinsicOp::IOP_VkRawBufferLoad: retVal = processRawBufferLoad(callExpr); +======= + case hlsl::IntrinsicOp::IOP_Vkext_execution_mode: + retVal = processIntrinsicExecutionMode(callExpr); +>>>>>>> daae8b9c0 ([SPIRV] Add support vk::ext_execution_mode) break; case hlsl::IntrinsicOp::IOP_saturate: retVal = processIntrinsicSaturate(callExpr); @@ -12567,6 +12575,27 @@ SpirvInstruction *SpirvEmitter::processRawBufferLoad(const CallExpr *callExpr) { loadInst->setAlignment(4); return loadInst; +SpirvInstruction * +SpirvEmitter::processIntrinsicExecutionMode(const CallExpr *expr) { + llvm::SmallVector execModesParams; + uint32_t exeMode = 0; + const auto args = expr->getArgs(); + for (uint32_t i = 0; i < expr->getNumArgs(); ++i) { + SpirvConstantInteger *argInst = + dyn_cast(doExpr(args[i])); + assert(argInst != nullptr); + unsigned argInteger = argInst->getValue().getZExtValue(); + if (i > 0) + execModesParams.push_back(argInteger); + else + exeMode = argInteger; + } + assert(entryFunction != nullptr); + assert(exeMode != 0); + + return spvBuilder.addExecutionMode(entryFunction, + static_cast(exeMode), + execModesParams, expr->getExprLoc()); } bool SpirvEmitter::spirvToolsValidate(std::vector *mod, diff --git a/tools/clang/lib/SPIRV/SpirvEmitter.h b/tools/clang/lib/SPIRV/SpirvEmitter.h index b0e6f23893..900c63da82 100644 --- a/tools/clang/lib/SPIRV/SpirvEmitter.h +++ b/tools/clang/lib/SPIRV/SpirvEmitter.h @@ -599,6 +599,8 @@ class SpirvEmitter : public ASTConsumer { /// Custom intrinsic to support basic buffer_reference use case SpirvInstruction *processRawBufferLoad(const CallExpr *callExpr); + /// Process vk::ext_execution_mode intrinsic + SpirvInstruction *processIntrinsicExecutionMode(const CallExpr *expr); private: /// Returns the for constant value 0 of the given type. diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 6f33e3cf51..bf240bb27a 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -12090,6 +12090,11 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A, ValidateAttributeStringArg(S, A, nullptr, 1), A.getAttributeSpellingListIndex()); break; + case AttributeList::AT_VKStorageClassExt: + declAttr = ::new (S.Context) VKStorageClassExtAttr( + A.getRange(), S.Context, unsigned(ValidateAttributeIntArg(S, A)), + A.getAttributeSpellingListIndex()); + break; default: Handled = false; return; diff --git a/tools/clang/test/CodeGenSPIRV/spv.intrinsicExecutionMode.hlsl b/tools/clang/test/CodeGenSPIRV/spv.intrinsicExecutionMode.hlsl new file mode 100644 index 0000000000..9a410b9e65 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/spv.intrinsicExecutionMode.hlsl @@ -0,0 +1,14 @@ +// RUN: %dxc -T ps_6_0 -E main -spirv + + +// CHECK: OpExecutionMode {{%\w+}} StencilRefReplacingEXT +// CHECK: OpExecutionMode {{%\w+}} SubgroupSize 32 +// CHECK: OpDecorate {{%\w+}} BuiltIn FragStencilRefEXT + +[[vk::ext_decorate(11, 5014)]] +int main() : SV_Target0 { + + vk::ext_execution_mode(/*StencilRefReplacingEXT*/5027); + vk::ext_execution_mode(/*SubgroupSize*/35, 32); + return 3; +} diff --git a/tools/clang/test/CodeGenSPIRV/spv.intrinsicStorageClass.hlsl b/tools/clang/test/CodeGenSPIRV/spv.intrinsicStorageClass.hlsl new file mode 100644 index 0000000000..cab1f4720d --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/spv.intrinsicStorageClass.hlsl @@ -0,0 +1,13 @@ +// RUN: %dxc -T ps_6_0 -E main -spirv -Vd + +//CHECK: {{%\w+}} = OpVariable {{%\w+}} RayPayloadNV +//CHECK: {{%\w+}} = OpVariable {{%\w+}} CrossWorkgroup + +[[vk::ext_storage_class(/*RayPayloadNV*/5338)]] +float4 payload; + +int main() : SV_Target0 { + + [[vk::ext_storage_class(/* CrossWorkgroup */ 5)]] int foo = 3; + return foo; +} diff --git a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp index 2056300c0b..fbf27c0355 100644 --- a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp +++ b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp @@ -1346,6 +1346,8 @@ TEST_F(FileTest, IntrinsicsSpirv) { runFileTest("spv.intrinsicInstruction.hlsl"); runFileTest("spv.intrinsicLiteral.hlsl"); runFileTest("spv.intrinsicDecorate.hlsl", Expect::Success, false); + runFileTest("spv.intrinsicExecutionMode.hlsl", Expect::Success, false); + runFileTest("spv.intrinsicStorageClass.hlsl", Expect::Success, false); runFileTest("spv.intrinsic.reference.error.hlsl", Expect::Failure); } TEST_F(FileTest, IntrinsicsVkReadClock) { diff --git a/utils/hct/gen_intrin_main.txt b/utils/hct/gen_intrin_main.txt index 6d81fe3d86..c80a3f8aa9 100644 --- a/utils/hct/gen_intrin_main.txt +++ b/utils/hct/gen_intrin_main.txt @@ -379,6 +379,7 @@ namespace VkIntrinsics { u64 [[]] ReadClock(in uint scope); uint [[ro]] RawBufferLoad(in u64 addr); +void [[]] ext_execution_mode(...); } namespace // SPIRV Change Ends