diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 05aac15b30cd6..3e2d39e3a2784 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -5179,6 +5179,8 @@ class HLSLRootSignatureDecl final llvm::hlsl::rootsig::RootElement> { friend TrailingObjects; + llvm::dxil::RootSignatureVersion RootSigVer; + unsigned NumElems; llvm::hlsl::rootsig::RootElement *getElems() { return getTrailingObjects(); } @@ -5188,16 +5190,20 @@ class HLSLRootSignatureDecl final } HLSLRootSignatureDecl(DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, + llvm::dxil::RootSignatureVersion RootSigVer, unsigned NumElems); public: static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, + llvm::dxil::RootSignatureVersion RootSigVer, ArrayRef RootElements); static HLSLRootSignatureDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); + llvm::dxil::RootSignatureVersion getVersion() const { return RootSigVer; } + ArrayRef getRootElements() const { return {getElems(), NumElems}; } diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 491e8bee9fd5c..6442492d104b9 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -24,6 +24,7 @@ #include "clang/Basic/Visibility.h" #include "llvm/ADT/FloatingPointMode.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DXILABI.h" #include "llvm/TargetParser/Triple.h" #include #include @@ -623,6 +624,10 @@ class LangOptions : public LangOptionsBase { // implementation on real-world examples. std::string OpenACCMacroOverride; + /// The HLSL root signature version for dxil. + llvm::dxil::RootSignatureVersion HLSLRootSigVer = + llvm::dxil::RootSignatureVersion::rootsig_1_1; + // Indicates if the wasm-opt binary must be ignored in the case of a // WebAssembly target. bool NoWasmOpt = false; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 0ffd8c40da7da..141d80e786a0c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -9288,6 +9288,15 @@ def fcgl : DXCFlag<"fcgl">, Alias; def enable_16bit_types : DXCFlag<"enable-16bit-types">, Alias, HelpText<"Enable 16-bit types and disable min precision types." "Available in HLSL 2018 and shader model 6.2.">; +def hlsl_rootsig_ver : + Option<["-"], "hlsl-rootsig-ver", KIND_SEPARATE>, + Group, + Visibility<[ClangOption, CC1Option, DXCOption]>, + HelpText<"Root Signature Version">, + Values<"rootsig_1_0,rootsig_1_1">, + NormalizedValuesScope<"llvm::dxil::RootSignatureVersion">, + NormalizedValues<["rootsig_1_0", "rootsig_1_1"]>, + MarshallingInfoEnum, "rootsig_1_1">; def hlsl_entrypoint : Option<["-"], "hlsl-entry", KIND_SEPARATE>, Group, Visibility<[ClangOption, CC1Option]>, diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 860968939b4ae..87cd7bc331b22 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -5853,21 +5853,21 @@ bool HLSLBufferDecl::buffer_decls_empty() { // HLSLRootSignatureDecl Implementation //===----------------------------------------------------------------------===// -HLSLRootSignatureDecl::HLSLRootSignatureDecl(DeclContext *DC, - SourceLocation Loc, - IdentifierInfo *ID, - unsigned NumElems) +HLSLRootSignatureDecl::HLSLRootSignatureDecl( + DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, + llvm::dxil::RootSignatureVersion RootSigVer, unsigned NumElems) : NamedDecl(Decl::Kind::HLSLRootSignature, DC, Loc, DeclarationName(ID)), - NumElems(NumElems) {} + RootSigVer(RootSigVer), NumElems(NumElems) {} HLSLRootSignatureDecl *HLSLRootSignatureDecl::Create( ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, + llvm::dxil::RootSignatureVersion RootSigVer, ArrayRef RootElements) { HLSLRootSignatureDecl *RSDecl = new (C, DC, additionalSizeToAlloc( RootElements.size())) - HLSLRootSignatureDecl(DC, Loc, ID, RootElements.size()); + HLSLRootSignatureDecl(DC, Loc, ID, RootSigVer, RootElements.size()); auto *StoredElems = RSDecl->getElems(); std::uninitialized_copy(RootElements.begin(), RootElements.end(), StoredElems); @@ -5876,8 +5876,10 @@ HLSLRootSignatureDecl *HLSLRootSignatureDecl::Create( HLSLRootSignatureDecl * HLSLRootSignatureDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { - HLSLRootSignatureDecl *Result = new (C, ID) - HLSLRootSignatureDecl(nullptr, SourceLocation(), nullptr, /*NumElems=*/0); + HLSLRootSignatureDecl *Result = new (C, ID) HLSLRootSignatureDecl( + nullptr, SourceLocation(), nullptr, + /*RootSigVer*/ llvm::dxil::RootSignatureVersion::rootsig_1_0, + /*NumElems=*/0); return Result; } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 1b84b8824047b..cdb6f7b88777d 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -3041,6 +3041,16 @@ void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) { void TextNodeDumper::VisitHLSLRootSignatureDecl( const HLSLRootSignatureDecl *D) { dumpName(D); + OS << " version: "; + switch (D->getVersion()) { + case llvm::dxil::RootSignatureVersion::rootsig_1_0: + OS << "1.0"; + break; + case llvm::dxil::RootSignatureVersion::rootsig_1_1: + OS << "1.1"; + break; + } + OS << ", "; llvm::hlsl::rootsig::dumpRootElements(OS, D->getRootElements()); } diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 585411bc59e16..55f4e7fd4e0ec 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -66,14 +66,22 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) { DXILValMD->addOperand(Val); } -void addRootSignature(ArrayRef Elements, +void addRootSignature(llvm::dxil::RootSignatureVersion RootSigVer, + ArrayRef Elements, llvm::Function *Fn, llvm::Module &M) { auto &Ctx = M.getContext(); + IRBuilder<> Builder(Ctx); - llvm::hlsl::rootsig::MetadataBuilder Builder(Ctx, Elements); - MDNode *RootSignature = Builder.BuildRootSignature(); - MDNode *FnPairing = - MDNode::get(Ctx, {ValueAsMetadata::get(Fn), RootSignature}); + llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements); + MDNode *RootSignature = RSBuilder.BuildRootSignature(); + + Metadata *Operands[] = { + ValueAsMetadata::get(Fn), + RootSignature, + ConstantAsMetadata::get( + Builder.getInt32(llvm::to_underlying(RootSigVer))), + }; + MDNode *FnPairing = MDNode::get(Ctx, Operands); StringRef RootSignatureValKey = "dx.rootsignatures"; auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey); @@ -465,9 +473,11 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, // Add and identify root signature to function, if applicable for (const Attr *Attr : FD->getAttrs()) { - if (const auto *RSAttr = dyn_cast(Attr)) - addRootSignature(RSAttr->getSignatureDecl()->getRootElements(), EntryFn, + if (const auto *RSAttr = dyn_cast(Attr)) { + auto *RSDecl = RSAttr->getSignatureDecl(); + addRootSignature(RSDecl->getVersion(), RSDecl->getRootElements(), EntryFn, M); + } } } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a78a1c8978183..b779d5be12941 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3834,7 +3834,8 @@ static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs, options::OPT_emit_obj, options::OPT_disable_llvm_passes, options::OPT_fnative_half_type, - options::OPT_hlsl_entrypoint}; + options::OPT_hlsl_entrypoint, + options::OPT_hlsl_rootsig_ver}; if (!types::isHLSL(InputType)) return; for (const auto &Arg : ForwardedArguments) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 5c52dc33ddf6c..a53a7347be481 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -636,6 +636,10 @@ static bool FixupInvocation(CompilerInvocation &Invocation, Diags.Report(diag::err_drv_argument_not_allowed_with) << "-hlsl-entry" << GetInputKindName(IK); + if (Args.hasArg(OPT_hlsl_rootsig_ver) && !LangOpts.HLSL) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << "-hlsl-rootsig-ver" << GetInputKindName(IK); + if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP) Diags.Report(diag::warn_ignored_hip_only_option) << Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args); diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index b55f4fd786b58..03431f3944c4b 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -997,7 +997,7 @@ void SemaHLSL::ActOnFinishRootSignatureDecl( auto *SignatureDecl = HLSLRootSignatureDecl::Create( SemaRef.getASTContext(), /*DeclContext=*/SemaRef.CurContext, Loc, - DeclIdent, Elements); + DeclIdent, SemaRef.getLangOpts().HLSLRootSigVer, Elements); SignatureDecl->setImplicit(); SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope()); diff --git a/clang/test/AST/HLSL/RootSignatures-AST.hlsl b/clang/test/AST/HLSL/RootSignatures-AST.hlsl index c700174da764d..4b78c24683801 100644 --- a/clang/test/AST/HLSL/RootSignatures-AST.hlsl +++ b/clang/test/AST/HLSL/RootSignatures-AST.hlsl @@ -1,5 +1,11 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \ // RUN: -disable-llvm-passes -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \ +// RUN: -hlsl-rootsig-ver rootsig_1_0 \ +// RUN: -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-V1_0 +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \ +// RUN: -hlsl-rootsig-ver rootsig_1_1 \ +// RUN: -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-V1_1 // This test ensures that the sample root signature is parsed without error and // the Attr AST Node is created succesfully. If an invalid root signature was @@ -16,6 +22,8 @@ "DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))" // CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[SAMPLE_RS_DECL:__hlsl_rootsig_decl_\d*]] +// CHECK-V1_0: version: 1.0, +// CHECK-V1_1: version: 1.1, // CHECK-SAME: RootElements{ // CHECK-SAME: CBV(b1, numDescriptors = 1, space = 0, // CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = DataStaticWhileSetAtExecute), diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index ca843ffbb1ced..6618ca741aa9d 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -3,14 +3,14 @@ // CHECK: !dx.rootsignatures = !{![[#EMPTY_ENTRY:]], ![[#DT_ENTRY:]], // CHECK-SAME: ![[#RF_ENTRY:]], ![[#RC_ENTRY:]], ![[#RD_ENTRY:]], ![[#SS_ENTRY:]]} -// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]]} +// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]], i32 2} // CHECK: ![[#EMPTY]] = !{} [shader("compute"), RootSignature("")] [numthreads(1,1,1)] void EmptyEntry() {} -// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]]} +// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]], i32 2} // CHECK: ![[#DT_RS]] = !{![[#TABLE:]]} // CHECK: ![[#TABLE]] = !{!"DescriptorTable", i32 0, ![[#CBV:]], ![[#SRV:]]} // CHECK: ![[#CBV]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4} @@ -25,7 +25,7 @@ void EmptyEntry() {} [numthreads(1,1,1)] void DescriptorTableEntry() {} -// CHECK: ![[#RF_ENTRY]] = !{ptr @RootFlagsEntry, ![[#RF_RS:]]} +// CHECK: ![[#RF_ENTRY]] = !{ptr @RootFlagsEntry, ![[#RF_RS:]], i32 2} // CHECK: ![[#RF_RS]] = !{![[#ROOT_FLAGS:]]} // CHECK: ![[#ROOT_FLAGS]] = !{!"RootFlags", i32 2114} @@ -38,7 +38,7 @@ void DescriptorTableEntry() {} [numthreads(1,1,1)] void RootFlagsEntry() {} -// CHECK: ![[#RC_ENTRY]] = !{ptr @RootConstantsEntry, ![[#RC_RS:]]} +// CHECK: ![[#RC_ENTRY]] = !{ptr @RootConstantsEntry, ![[#RC_RS:]], i32 2} // CHECK: ![[#RC_RS]] = !{![[#ROOT_CONSTANTS:]]} // CHECK: ![[#ROOT_CONSTANTS]] = !{!"RootConstants", i32 5, i32 1, i32 2, i32 1} @@ -52,7 +52,7 @@ void RootFlagsEntry() {} [numthreads(1,1,1)] void RootConstantsEntry() {} -// CHECK: ![[#RD_ENTRY]] = !{ptr @RootDescriptorsEntry, ![[#RD_RS:]]} +// CHECK: ![[#RD_ENTRY]] = !{ptr @RootDescriptorsEntry, ![[#RD_RS:]], i32 2} // CHECK: ![[#RD_RS]] = !{![[#ROOT_CBV:]], ![[#ROOT_UAV:]], ![[#ROOT_SRV:]]} // CHECK: ![[#ROOT_CBV]] = !{!"RootCBV", i32 0, i32 0, i32 0, i32 4} // CHECK: ![[#ROOT_UAV]] = !{!"RootUAV", i32 0, i32 42, i32 3, i32 2} @@ -66,7 +66,7 @@ void RootConstantsEntry() {} [numthreads(1,1,1)] void RootDescriptorsEntry() {} -// CHECK: ![[#SS_ENTRY]] = !{ptr @StaticSamplerEntry, ![[#SS_RS:]]} +// CHECK: ![[#SS_ENTRY]] = !{ptr @StaticSamplerEntry, ![[#SS_RS:]], i32 2} // CHECK: ![[#SS_RS]] = !{![[#STATIC_SAMPLER:]]} // checking filter = 0x4 diff --git a/clang/test/Driver/dxc_hlsl-rootsig-ver.hlsl b/clang/test/Driver/dxc_hlsl-rootsig-ver.hlsl new file mode 100644 index 0000000000000..5e65b43c15b51 --- /dev/null +++ b/clang/test/Driver/dxc_hlsl-rootsig-ver.hlsl @@ -0,0 +1,15 @@ +// RUN: %clang_dxc -T cs_6_0 -fcgl %s | FileCheck %s --check-prefix=CHECK-V1_1 +// RUN: %clang_dxc -T cs_6_0 -fcgl -hlsl-rootsig-ver rootsig_1_0 %s | FileCheck %s --check-prefix=CHECK-V1_0 +// RUN: %clang_dxc -T cs_6_0 -fcgl -hlsl-rootsig-ver rootsig_1_1 %s | FileCheck %s --check-prefix=CHECK-V1_1 + +// Test to demonstrate that we can specify the root-signature versions + +// CHECK: !dx.rootsignatures = !{![[#EMPTY_ENTRY:]]} +// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]], +// CHECK-V1_0: i32 1} +// CHECK-V1_1: i32 2} +// CHECK: ![[#EMPTY]] = !{} + +[shader("compute"), RootSignature("")] +[numthreads(1,1,1)] +void EmptyEntry() {} diff --git a/llvm/include/llvm/Support/DXILABI.h b/llvm/include/llvm/Support/DXILABI.h index b479f7c73eba3..89bf707c205f3 100644 --- a/llvm/include/llvm/Support/DXILABI.h +++ b/llvm/include/llvm/Support/DXILABI.h @@ -99,6 +99,12 @@ enum class SamplerFeedbackType : uint32_t { const unsigned MinWaveSize = 4; const unsigned MaxWaveSize = 128; +// D3D_ROOT_SIGNATURE_VERSION +enum class RootSignatureVersion { + rootsig_1_0 = 0x1, + rootsig_1_1 = 0x2, +}; + } // namespace dxil } // namespace llvm