diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 05aac15b30cd6..43f710e2090e8 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -41,6 +41,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" @@ -5179,6 +5180,8 @@ class HLSLRootSignatureDecl final llvm::hlsl::rootsig::RootElement> { friend TrailingObjects; + llvm::dxbc::RootSignatureVersion Version; + unsigned NumElems; llvm::hlsl::rootsig::RootElement *getElems() { return getTrailingObjects(); } @@ -5188,16 +5191,20 @@ class HLSLRootSignatureDecl final } HLSLRootSignatureDecl(DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, + llvm::dxbc::RootSignatureVersion Version, unsigned NumElems); public: static HLSLRootSignatureDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, + llvm::dxbc::RootSignatureVersion Version, ArrayRef RootElements); static HLSLRootSignatureDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); + llvm::dxbc::RootSignatureVersion getVersion() const { return Version; } + ArrayRef getRootElements() const { return {getElems(), NumElems}; } diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 491e8bee9fd5c..b7c5ed994c992 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/BinaryFormat/DXContainer.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::dxbc::RootSignatureVersion HLSLRootSigVer = + llvm::dxbc::RootSignatureVersion::V1_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..181c937c2709f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -9288,6 +9288,20 @@ 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 fdx_rootsignature_version : + Joined<["-"], "fdx-rootsignature-version=">, + Group, + Visibility<[ClangOption, CC1Option]>, + HelpText<"Root Signature Version">, + Values<"rootsig_1_0,rootsig_1_1">, + NormalizedValuesScope<"llvm::dxbc::RootSignatureVersion">, + NormalizedValues<["V1_0", "V1_1"]>, + MarshallingInfoEnum, "V1_1">; +def dxc_rootsig_ver : + Separate<["/", "-"], "force-rootsig-ver">, + Alias, + Group, + Visibility<[DXCOption]>; 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 c4376aab480cd..a63e1ce37cb23 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::dxbc::RootSignatureVersion Version, unsigned NumElems) : NamedDecl(Decl::Kind::HLSLRootSignature, DC, Loc, DeclarationName(ID)), - NumElems(NumElems) {} + Version(Version), NumElems(NumElems) {} HLSLRootSignatureDecl *HLSLRootSignatureDecl::Create( ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID, + llvm::dxbc::RootSignatureVersion Version, ArrayRef RootElements) { HLSLRootSignatureDecl *RSDecl = new (C, DC, additionalSizeToAlloc( RootElements.size())) - HLSLRootSignatureDecl(DC, Loc, ID, RootElements.size()); + HLSLRootSignatureDecl(DC, Loc, ID, Version, RootElements.size()); auto *StoredElems = RSDecl->getElems(); std::uninitialized_copy(RootElements.begin(), RootElements.end(), StoredElems); @@ -5877,7 +5877,9 @@ HLSLRootSignatureDecl *HLSLRootSignatureDecl::Create( HLSLRootSignatureDecl * HLSLRootSignatureDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { HLSLRootSignatureDecl *Result = new (C, ID) - HLSLRootSignatureDecl(nullptr, SourceLocation(), nullptr, /*NumElems=*/0); + HLSLRootSignatureDecl(nullptr, SourceLocation(), nullptr, + /*Version*/ llvm::dxbc::RootSignatureVersion::V1_1, + /*NumElems=*/0); return Result; } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 1b84b8824047b..bb860a8f76742 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::dxbc::RootSignatureVersion::V1_0: + OS << "1.0"; + break; + case llvm::dxbc::RootSignatureVersion::V1_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 3103f1798e14e..f2e992fb7fa69 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -66,17 +66,16 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) { DXILValMD->addOperand(Val); } -void addRootSignature(ArrayRef Elements, +void addRootSignature(llvm::dxbc::RootSignatureVersion RootSigVer, + ArrayRef Elements, llvm::Function *Fn, llvm::Module &M) { auto &Ctx = M.getContext(); - llvm::hlsl::rootsig::MetadataBuilder Builder(Ctx, Elements); - MDNode *RootSignature = Builder.BuildRootSignature(); + llvm::hlsl::rootsig::MetadataBuilder RSBuilder(Ctx, Elements); + MDNode *RootSignature = RSBuilder.BuildRootSignature(); - // TODO: We need to wire the root signature version up through the frontend - // rather than hardcoding it. - ConstantAsMetadata *Version = - ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 2)); + ConstantAsMetadata *Version = ConstantAsMetadata::get(ConstantInt::get( + llvm::Type::getInt32Ty(Ctx), llvm::to_underlying(RootSigVer))); MDNode *MDVals = MDNode::get(Ctx, {ValueAsMetadata::get(Fn), RootSignature, Version}); @@ -471,9 +470,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 2bb42a319eccf..6ec7b89558571 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3825,16 +3825,18 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs, static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs, types::ID InputType) { - const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version, - options::OPT_res_may_alias, - options::OPT_D, - options::OPT_I, - options::OPT_O, - options::OPT_emit_llvm, - options::OPT_emit_obj, - options::OPT_disable_llvm_passes, - options::OPT_fnative_half_type, - options::OPT_hlsl_entrypoint}; + const unsigned ForwardedArguments[] = { + options::OPT_dxil_validator_version, + options::OPT_res_may_alias, + options::OPT_D, + options::OPT_I, + options::OPT_O, + options::OPT_emit_llvm, + options::OPT_emit_obj, + options::OPT_disable_llvm_passes, + options::OPT_fnative_half_type, + options::OPT_hlsl_entrypoint, + options::OPT_fdx_rootsignature_version}; if (!types::isHLSL(InputType)) return; for (const auto &Arg : ForwardedArguments) diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index dcc51e182924c..92c1e2f62a17b 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -295,6 +295,13 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, A->claim(); continue; } + if (A->getOption().getID() == options::OPT_dxc_rootsig_ver) { + DAL->AddJoinedArg(nullptr, + Opts.getOption(options::OPT_fdx_rootsignature_version), + A->getValue()); + A->claim(); + continue; + } if (A->getOption().getID() == options::OPT__SLASH_O) { StringRef OStr = A->getValue(); if (OStr == "d") { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 5c52dc33ddf6c..9e269ab244d4c 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_fdx_rootsignature_version) && !LangOpts.HLSL) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << "-fdx-rootsignature-version" << 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 d003967a522a1..b4b5aeef9b629 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1067,7 +1067,7 @@ void SemaHLSL::ActOnFinishRootSignatureDecl( auto *SignatureDecl = HLSLRootSignatureDecl::Create( SemaRef.getASTContext(), /*DeclContext=*/SemaRef.CurContext, Loc, - DeclIdent, Elements); + DeclIdent, SemaRef.getLangOpts().HLSLRootSigVer, Elements); if (handleRootSignatureDecl(SignatureDecl, Loc)) return; diff --git a/clang/test/AST/HLSL/RootSignatures-AST.hlsl b/clang/test/AST/HLSL/RootSignatures-AST.hlsl index c700174da764d..87bfa1cb2df34 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: -fdx-rootsignature-version=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: -fdx-rootsignature-version=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/Driver/dxc_hlsl-rootsig-ver.hlsl b/clang/test/Driver/dxc_hlsl-rootsig-ver.hlsl new file mode 100644 index 0000000000000..c6aa1e94096c8 --- /dev/null +++ b/clang/test/Driver/dxc_hlsl-rootsig-ver.hlsl @@ -0,0 +1,16 @@ +// RUN: %clang_dxc -T cs_6_0 -fcgl %s | FileCheck %s --check-prefix=CHECK-V1_1 + +// RUN: %clang_dxc -T cs_6_0 -fcgl -force-rootsig-ver rootsig_1_0 %s | FileCheck %s --check-prefix=CHECK-V1_0 +// RUN: %clang_dxc -T cs_6_0 -fcgl -force-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/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index 56c9e53308674..4edb2d5d57cef 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -750,6 +750,12 @@ struct DescriptorRange : public v1::DescriptorRange { } // namespace v2 } // namespace RTS0 +// D3D_ROOT_SIGNATURE_VERSION +enum class RootSignatureVersion { + V1_0 = 0x1, + V1_1 = 0x2, +}; + } // namespace dxbc } // namespace llvm