Skip to content

[HLSL][RootSignature] Add fdx-rootsignature-version option to specify root signature version #144813

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 24, 2025

Conversation

inbelic
Copy link
Contributor

@inbelic inbelic commented Jun 18, 2025

This pr provides the ability to specify the root signature version as a compiler option and to retain this in the root signature decl.

It also updates the methods to serialize the version when dumping the declaration and to output the version when generating the metadata.

  • Update DXContainer.hI to define the root signature versions
  • Update Options.td and LangOpts.h to define the fdx-rootsignature-version compiler option
  • Update Options.td to provide an alias force-rootsig-ver in clang-dxc
  • Update Decl.[h|cpp] and SeamHLSL.cpp so that RootSignatureDecl will retain its version type
  • Updates CGHLSLRuntime.cpp to generate the extra metadata field
  • Add tests to illustrate

Resolves #126557.

Note: this does not implement validation based on versioning. #129940 is required to retrieve the version and use it for validations.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. backend:DirectX HLSL HLSL Language Support llvm:support labels Jun 18, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 18, 2025

@llvm/pr-subscribers-llvm-binary-utilities
@llvm/pr-subscribers-hlsl
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-driver
@llvm/pr-subscribers-llvm-support

@llvm/pr-subscribers-clang-codegen

Author: Finn Plummer (inbelic)

Changes

This pr provides the ability to specify the root signature version as a compiler option and to retain this in the root signature decl.

It also updates the methods to serialize the version when dumping the declaration and to output the version when generating the metadata.

  • Update DXILABI to define the root signature versions
  • Update Options.td and LangOpts.h to define the hlsl-rootsig-ver compiler option
  • Update Decl.[h|cpp] and SeamHLSL.cpp so that RootSignatureDecl will retain its version type
  • Updates CGHLSLRuntime.cpp to generate the extra metadata field
  • Add tests to illustrate

Resolves #126557.

Note: this does not implement validation based on versioning. #129940 is required to retrieve the version and use it for validations.


Full diff: https://github.com/llvm/llvm-project/pull/144813.diff

13 Files Affected:

  • (modified) clang/include/clang/AST/Decl.h (+6)
  • (modified) clang/include/clang/Basic/LangOptions.h (+5)
  • (modified) clang/include/clang/Driver/Options.td (+9)
  • (modified) clang/lib/AST/Decl.cpp (+10-8)
  • (modified) clang/lib/AST/TextNodeDumper.cpp (+10)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+17-7)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+2-1)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (+4)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+1-1)
  • (modified) clang/test/AST/HLSL/RootSignatures-AST.hlsl (+8)
  • (modified) clang/test/CodeGenHLSL/RootSignature.hlsl (+6-6)
  • (added) clang/test/Driver/dxc_hlsl-rootsig-ver.hlsl (+15)
  • (modified) llvm/include/llvm/Support/DXILABI.h (+6)
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<llvm::hlsl::rootsig::RootElement> RootElements);
 
   static HLSLRootSignatureDecl *CreateDeserialized(ASTContext &C,
                                                    GlobalDeclID ID);
 
+  llvm::dxil::RootSignatureVersion getVersion() const { return RootSigVer; }
+
   ArrayRef<llvm::hlsl::rootsig::RootElement> 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 <optional>
 #include <string>
@@ -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<emit_pristine_llvm>;
 def enable_16bit_types : DXCFlag<"enable-16bit-types">, Alias<fnative_half_type>,
   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<dxc_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<LangOpts<"HLSLRootSigVer">, "rootsig_1_1">;
 def hlsl_entrypoint : Option<["-"], "hlsl-entry", KIND_SEPARATE>,
                       Group<dxc_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<llvm::hlsl::rootsig::RootElement> RootElements) {
   HLSLRootSignatureDecl *RSDecl =
       new (C, DC,
            additionalSizeToAlloc<llvm::hlsl::rootsig::RootElement>(
                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<llvm::hlsl::rootsig::RootElement> Elements,
+void addRootSignature(llvm::dxil::RootSignatureVersion RootSigVer,
+                      ArrayRef<llvm::hlsl::rootsig::RootElement> 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<RootSignatureAttr>(Attr))
-      addRootSignature(RSAttr->getSignatureDecl()->getRootElements(), EntryFn,
+    if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(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
 

@llvmbot
Copy link
Member

llvmbot commented Jun 18, 2025

@llvm/pr-subscribers-backend-directx

Author: Finn Plummer (inbelic)

Changes

This pr provides the ability to specify the root signature version as a compiler option and to retain this in the root signature decl.

It also updates the methods to serialize the version when dumping the declaration and to output the version when generating the metadata.

  • Update DXILABI to define the root signature versions
  • Update Options.td and LangOpts.h to define the hlsl-rootsig-ver compiler option
  • Update Decl.[h|cpp] and SeamHLSL.cpp so that RootSignatureDecl will retain its version type
  • Updates CGHLSLRuntime.cpp to generate the extra metadata field
  • Add tests to illustrate

Resolves #126557.

Note: this does not implement validation based on versioning. #129940 is required to retrieve the version and use it for validations.


Full diff: https://github.com/llvm/llvm-project/pull/144813.diff

13 Files Affected:

  • (modified) clang/include/clang/AST/Decl.h (+6)
  • (modified) clang/include/clang/Basic/LangOptions.h (+5)
  • (modified) clang/include/clang/Driver/Options.td (+9)
  • (modified) clang/lib/AST/Decl.cpp (+10-8)
  • (modified) clang/lib/AST/TextNodeDumper.cpp (+10)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+17-7)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+2-1)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (+4)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+1-1)
  • (modified) clang/test/AST/HLSL/RootSignatures-AST.hlsl (+8)
  • (modified) clang/test/CodeGenHLSL/RootSignature.hlsl (+6-6)
  • (added) clang/test/Driver/dxc_hlsl-rootsig-ver.hlsl (+15)
  • (modified) llvm/include/llvm/Support/DXILABI.h (+6)
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<llvm::hlsl::rootsig::RootElement> RootElements);
 
   static HLSLRootSignatureDecl *CreateDeserialized(ASTContext &C,
                                                    GlobalDeclID ID);
 
+  llvm::dxil::RootSignatureVersion getVersion() const { return RootSigVer; }
+
   ArrayRef<llvm::hlsl::rootsig::RootElement> 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 <optional>
 #include <string>
@@ -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<emit_pristine_llvm>;
 def enable_16bit_types : DXCFlag<"enable-16bit-types">, Alias<fnative_half_type>,
   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<dxc_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<LangOpts<"HLSLRootSigVer">, "rootsig_1_1">;
 def hlsl_entrypoint : Option<["-"], "hlsl-entry", KIND_SEPARATE>,
                       Group<dxc_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<llvm::hlsl::rootsig::RootElement> RootElements) {
   HLSLRootSignatureDecl *RSDecl =
       new (C, DC,
            additionalSizeToAlloc<llvm::hlsl::rootsig::RootElement>(
                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<llvm::hlsl::rootsig::RootElement> Elements,
+void addRootSignature(llvm::dxil::RootSignatureVersion RootSigVer,
+                      ArrayRef<llvm::hlsl::rootsig::RootElement> 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<RootSignatureAttr>(Attr))
-      addRootSignature(RSAttr->getSignatureDecl()->getRootElements(), EntryFn,
+    if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(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
 

Copy link
Contributor

@bogner bogner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation all looks fairly straightforward here, but shouldn't we be naming the clang-dxc flag to match dxc's flag that does this? That is, -force-rootsig-ver.

bogner added a commit to bogner/llvm-project that referenced this pull request Jun 20, 2025
In llvm#144957 the backend was updated to expect a version in the metadata, but
since the frontend wasn't updated this breaks compilation. This is a somewhat
temporary fix to that until llvm#144813 lands.
Copy link

github-actions bot commented Jun 20, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Comment on lines 9291 to 9307
def hlsl_rootsig_ver :
Option<["-"], "hlsl-rootsig-ver", KIND_SEPARATE>,
Group<dxc_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<LangOpts<"HLSLRootSigVer">, "V1_1">;
def dxc_rootsig_ver :
Option<["-"], "force-rootsig-ver", KIND_SEPARATE>,
Group<dxc_Group>,
Visibility<[ClangOption, CC1Option, DXCOption]>,
HelpText<"Root Signature Version">,
Values<"rootsig_1_0,rootsig_1_1">,
NormalizedValuesScope<"llvm::dxbc::RootSignatureVersion">,
NormalizedValues<["V1_0", "V1_1"]>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should think a bit about the ergonomics here.

  • I don't think we want -force-rootsig-ver to be available in the clang driver mode or -cc1
  • The -hlsl-rootsig-ver naming is a bit funny, since this is really DirectX related moreso than HLSL
  • Clang driver options should generally follow the gcc-style conventions, so this should probably be a -f option (maybe -fhlsl- if we deem it language-wide?) or even -m if it's specific to the DirectX backend

I think the -force-rootsig-ver could potentially just be an alias for the other spelling that's only exposed in the dxc mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I had intended to only let -force-rootsig-ver to be an alias and have corrected that.

As for the naming of the clang driver options, I see. I will look into that and resolve a name for it next week.

bogner added a commit that referenced this pull request Jun 20, 2025
In #144957 the backend was updated to expect a version in the metadata,
but since the frontend wasn't updated this breaks compilation. This is a
somewhat temporary fix to that until #144813 lands.
Jaddyen pushed a commit to Jaddyen/llvm-project that referenced this pull request Jun 23, 2025
In llvm#144957 the backend was updated to expect a version in the metadata,
but since the frontend wasn't updated this breaks compilation. This is a
somewhat temporary fix to that until llvm#144813 lands.
This pr provides the ability to specify the root signature version as a
compiler option and to retain this in the root signature decl.

It also updates the methods to serialize the version when dumping the
declaration and to output the version when generating the metadata.

- Update `DXILABI` to define the root signature versions
- Update `Options.td` and `LangOpts.h` to define the `fdx-rootsig-ver`
Clang/CC1 compiler option
- Update `Options.td` to specify DXC compatible aliases
`force-rootsig-ver` and `force_rootsig-ver`
- Update `Decl.[h|cpp]` and `SeamHLSL.cpp` so that `RootSignatureDecl`
will retain its version type
- Updates `CGHLSLRuntime.cpp` to generate the extra metadata field
- Add tests to illustrate
Copy link
Contributor

@bogner bogner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. A few minor comments below.

options::OPT_disable_llvm_passes,
options::OPT_fnative_half_type,
options::OPT_hlsl_entrypoint,
options::OPT_fdx_rootsignature_version};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary? Since the -fdx-rootsignature-version spelling isn't exposed in the dxc driver mode I don't think this ever comes up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required. The naming is quite confusing, this is what will forward the argument to be used in cc1. The changes in HLSL.cpp just construct this arg but without this it wouldn't be used later.

@inbelic inbelic changed the title [HLSL][RootSignature] Add hlsl-rootsig-ver option to specify root signature version [HLSL][RootSignature] Add fdx-rootsignature-version option to specify root signature version Jun 24, 2025
@inbelic inbelic merged commit e93a0d0 into llvm:main Jun 24, 2025
8 checks passed
@inbelic inbelic deleted the inbelic/rs-add-version branch June 25, 2025 17:46
@inbelic
Copy link
Contributor Author

inbelic commented Jun 26, 2025

I realize now that I forgot to update setDefaultFlags here, to set the default values of RootDescriptorFlags and DescriptorRangeFlags dependent on the version.

This requires an update to HLSLRootSignatureParser to be given the version and initialize accordingly.

An issue tracking this is created here: #145820

anthonyhatran pushed a commit to anthonyhatran/llvm-project that referenced this pull request Jun 26, 2025
…fy root signature version (llvm#144813)

This pr provides the ability to specify the root signature version as a
compiler option and to retain this in the root signature decl.

It also updates the methods to serialize the version when dumping the
declaration and to output the version when generating the metadata.

- Update `DXContainer.hI` to define the root signature versions
- Update `Options.td` and `LangOpts.h` to define the
`fdx-rootsignature-version` compiler option
- Update `Options.td` to provide an alias `force-rootsig-ver` in
clang-dxc
- Update `Decl.[h|cpp]` and `SeamHLSL.cpp` so that `RootSignatureDecl`
will retain its version type
- Updates `CGHLSLRuntime.cpp` to generate the extra metadata field
- Add tests to illustrate

Resolves llvm#126557.

Note: this does not implement validation based on versioning.
llvm#129940 is required to
retrieve the version and use it for validations.
rlavaee pushed a commit to rlavaee/llvm-project that referenced this pull request Jul 1, 2025
…fy root signature version (llvm#144813)

This pr provides the ability to specify the root signature version as a
compiler option and to retain this in the root signature decl.

It also updates the methods to serialize the version when dumping the
declaration and to output the version when generating the metadata.

- Update `DXContainer.hI` to define the root signature versions
- Update `Options.td` and `LangOpts.h` to define the
`fdx-rootsignature-version` compiler option
- Update `Options.td` to provide an alias `force-rootsig-ver` in
clang-dxc
- Update `Decl.[h|cpp]` and `SeamHLSL.cpp` so that `RootSignatureDecl`
will retain its version type
- Updates `CGHLSLRuntime.cpp` to generate the extra metadata field
- Add tests to illustrate

Resolves llvm#126557.

Note: this does not implement validation based on versioning.
llvm#129940 is required to
retrieve the version and use it for validations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:DirectX clang:codegen IR generation bugs: mangling, exceptions, etc. clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category HLSL HLSL Language Support llvm:binary-utilities llvm:support
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[HLSL] Add support for Root Signature versions
4 participants