https://github.com/joaosaffran updated 
https://github.com/llvm/llvm-project/pull/160616

>From 787c77638092b06e7648f03660a4429dc602aac6 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Thu, 18 Sep 2025 14:16:25 -0700
Subject: [PATCH 01/19] adding yaml representation and updating write logic

---
 llvm/include/llvm/BinaryFormat/DXContainer.h  | 24 ++++++++
 .../BinaryFormat/DXContainerConstants.def     | 10 +++
 .../llvm/MC/DXContainerRootSignature.h        |  1 +
 .../include/llvm/ObjectYAML/DXContainerYAML.h |  5 ++
 llvm/lib/BinaryFormat/DXContainer.cpp         |  9 +++
 .../HLSL/RootSignatureValidations.cpp         |  4 +-
 llvm/lib/MC/DXContainerRootSignature.cpp      |  7 ++-
 llvm/lib/ObjectYAML/DXContainerEmitter.cpp    |  3 +
 llvm/lib/ObjectYAML/DXContainerYAML.cpp       | 12 ++++
 .../ObjectYAML/DXContainerYAMLTest.cpp        | 61 +++++++++++++++++++
 10 files changed, 134 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h 
b/llvm/include/llvm/BinaryFormat/DXContainer.h
index c04380667a640..a08cfff4b4974 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainer.h
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -185,6 +185,15 @@ enum class DescriptorRangeFlags : uint32_t {
 
 LLVM_ABI ArrayRef<EnumEntry<DescriptorRangeFlags>> getDescriptorRangeFlags();
 
+#define STATIC_SAMPLER_FLAG(Num, Enum, Flag) Enum = Num,
+enum class StaticSamplerFlags : uint32_t {
+#include "DXContainerConstants.def"
+
+  LLVM_MARK_AS_BITMASK_ENUM(NonNormalizedCoordinates)
+};
+
+LLVM_ABI ArrayRef<EnumEntry<StaticSamplerFlags>> getStaticSamplerFlags();
+
 #define ROOT_PARAMETER(Val, Enum) Enum = Val,
 enum class RootParameterType : uint32_t {
 #include "DXContainerConstants.def"
@@ -813,6 +822,21 @@ struct DescriptorRange {
   }
 };
 } // namespace v2
+namespace v3 {
+struct StaticSampler : public v1::StaticSampler {
+  uint32_t Flags;
+
+  StaticSampler() = default;
+  explicit StaticSampler(v1::StaticSampler &Base)
+      : v1::StaticSampler(Base), Flags(0U) {}
+
+  void swapBytes() {
+    v1::StaticSampler::swapBytes();
+    sys::swapByteOrder(Flags);
+  }
+};
+
+} // namespace v3
 } // namespace RTS0
 
 // D3D_ROOT_SIGNATURE_VERSION
diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def 
b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
index 889653611d79a..f576d958037cd 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
+++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
@@ -104,6 +104,16 @@ DESCRIPTOR_RANGE_FLAG(0x10000, 
DescriptorsStaticKeepingBufferBoundsChecks, DESCR
 #undef DESCRIPTOR_RANGE_FLAG
 #endif // DESCRIPTOR_RANGE_FLAG
 
+// STATIC_SAMPLER_FLAG(flag value, name, flag).
+#ifdef STATIC_SAMPLER_FLAG
+
+STATIC_SAMPLER_FLAG(0x0, None, SAMPLER_FLAG_NONE)
+STATIC_SAMPLER_FLAG(0x1, UintBorderColor, SAMPLER_FLAG_UINT_BORDER_COLOR)
+STATIC_SAMPLER_FLAG(0x2, NonNormalizedCoordinates, 
SAMPLER_FLAG_NON_NORMALIZED_COORDINATES)
+
+#undef STATIC_SAMPLER_FLAG
+#endif // STATIC_SAMPLER_FLAG
+
 #ifdef ROOT_PARAMETER
 
 ROOT_PARAMETER(0, DescriptorTable)
diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h 
b/llvm/include/llvm/MC/DXContainerRootSignature.h
index 54677ef70244f..2a76e81fefc5f 100644
--- a/llvm/include/llvm/MC/DXContainerRootSignature.h
+++ b/llvm/include/llvm/MC/DXContainerRootSignature.h
@@ -74,6 +74,7 @@ struct StaticSampler {
   uint32_t ShaderRegister;
   uint32_t RegisterSpace;
   dxbc::ShaderVisibility ShaderVisibility;
+  uint32_t Flags;
 };
 
 struct RootParametersContainer {
diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h 
b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index 62bfee7693db1..b5b110d0f59a1 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -178,6 +178,11 @@ struct StaticSamplerYamlDesc {
   uint32_t ShaderRegister;
   uint32_t RegisterSpace;
   dxbc::ShaderVisibility ShaderVisibility;
+
+  LLVM_ABI uint32_t getEncodedFlags() const;
+
+#define STATIC_SAMPLER_FLAG(Num, Enum, Flag) bool Enum = false;
+#include "llvm/BinaryFormat/DXContainerConstants.def"
 };
 
 struct RootSignatureYamlDesc {
diff --git a/llvm/lib/BinaryFormat/DXContainer.cpp 
b/llvm/lib/BinaryFormat/DXContainer.cpp
index 36d10d0b63078..c06a3e34653f0 100644
--- a/llvm/lib/BinaryFormat/DXContainer.cpp
+++ b/llvm/lib/BinaryFormat/DXContainer.cpp
@@ -89,6 +89,15 @@ ArrayRef<EnumEntry<DescriptorRangeFlags>> 
dxbc::getDescriptorRangeFlags() {
   return ArrayRef(DescriptorRangeFlagNames);
 }
 
+static const EnumEntry<StaticSamplerFlags> StaticSamplerFlagNames[] = {
+#define STATIC_SAMPLER_FLAG(Val, Enum, Flag) {#Enum, StaticSamplerFlags::Enum},
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+};
+
+ArrayRef<EnumEntry<StaticSamplerFlags>> dxbc::getStaticSamplerFlags() {
+  return ArrayRef(StaticSamplerFlagNames);
+}
+
 #define SHADER_VISIBILITY(Val, Enum) {#Enum, ShaderVisibility::Enum},
 
 static const EnumEntry<ShaderVisibility> ShaderVisibilityValues[] = {
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp 
b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
index 0970977b5064f..8c298f0685286 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
@@ -20,7 +20,9 @@ namespace rootsig {
 
 bool verifyRootFlag(uint32_t Flags) { return (Flags & ~0xfff) == 0; }
 
-bool verifyVersion(uint32_t Version) { return (Version == 1 || Version == 2); }
+bool verifyVersion(uint32_t Version) {
+  return (Version == 1 || Version == 2 || Version == 3);
+}
 
 bool verifyRegisterValue(uint32_t RegisterValue) {
   return RegisterValue != ~0U;
diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp 
b/llvm/lib/MC/DXContainerRootSignature.cpp
index b9ebb7a9e789c..13784e7c86684 100644
--- a/llvm/lib/MC/DXContainerRootSignature.cpp
+++ b/llvm/lib/MC/DXContainerRootSignature.cpp
@@ -33,7 +33,9 @@ static uint32_t 
rewriteOffsetToCurrentByte(raw_svector_ostream &Stream,
 size_t RootSignatureDesc::getSize() const {
   uint32_t StaticSamplersOffset = computeStaticSamplersOffset();
   size_t StaticSamplersSize =
-      StaticSamplers.size() * sizeof(dxbc::RTS0::v1::StaticSampler);
+      (Version > 2 ? sizeof(dxbc::RTS0::v3::StaticSampler)
+                   : sizeof(dxbc::RTS0::v1::StaticSampler)) *
+      StaticSamplers.size();
 
   return size_t(StaticSamplersOffset) + StaticSamplersSize;
 }
@@ -171,6 +173,9 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
     support::endian::write(BOS, S.ShaderRegister, llvm::endianness::little);
     support::endian::write(BOS, S.RegisterSpace, llvm::endianness::little);
     support::endian::write(BOS, S.ShaderVisibility, llvm::endianness::little);
+
+    if (Version > 2)
+      support::endian::write(BOS, S.Flags, llvm::endianness::little);
   }
   assert(Storage.size() == getSize());
   OS.write(Storage.data(), Storage.size());
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp 
b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index 910383816f43b..b00e45d912be1 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -343,6 +343,9 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) {
         NewSampler.RegisterSpace = Param.RegisterSpace;
         NewSampler.ShaderVisibility = Param.ShaderVisibility;
 
+        if (RS.Version > 2)
+          NewSampler.Flags = Param.getEncodedFlags();
+
         RS.StaticSamplers.push_back(NewSampler);
       }
 
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp 
b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 22674b1ceb734..39f42fb4dc839 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -245,6 +245,15 @@ uint32_t 
DXContainerYAML::DescriptorRangeYaml::getEncodedFlags() const {
   return Flags;
 }
 
+uint32_t DXContainerYAML::StaticSamplerYamlDesc::getEncodedFlags() const {
+  uint64_t Flags = 0;
+#define STATIC_SAMPLER_FLAG(Num, Enum, Flag)                                   
\
+  if (Enum)                                                                    
\
+    Flags |= (uint32_t)dxbc::StaticSamplerFlags::Enum;
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+  return Flags;
+}
+
 uint64_t DXContainerYAML::ShaderFeatureFlags::getEncodedFlags() {
   uint64_t Flag = 0;
 #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str)                      
\
@@ -512,6 +521,9 @@ void 
MappingTraits<llvm::DXContainerYAML::StaticSamplerYamlDesc>::mapping(
   IO.mapRequired("ShaderRegister", S.ShaderRegister);
   IO.mapRequired("RegisterSpace", S.RegisterSpace);
   IO.mapRequired("ShaderVisibility", S.ShaderVisibility);
+
+#define STATIC_SAMPLER_FLAG_FLAG(Num, Val) IO.mapOptional(#Val, S.Val, false);
+#include "llvm/BinaryFormat/DXContainerConstants.def"
 }
 
 void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
diff --git a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp 
b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
index b0ad208625436..eee0b64e4b866 100644
--- a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
+++ b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
@@ -526,3 +526,64 @@ TEST(RootSignature, ParseStaticSamplers) {
   EXPECT_EQ(Storage.size(), 144u);
   EXPECT_TRUE(memcmp(Buffer, Storage.data(), 144u) == 0);
 }
+
+TEST(RootSignature, ParseStaticSamplersV13) {
+  SmallString<128> Storage;
+
+  // First read a fully explicit yaml with all sizes and offsets provided
+  ASSERT_TRUE(convert(Storage, R"(--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  PartCount:       1
+  PartOffsets:     [ 60 ]
+Parts:
+  - Name:            RTS0
+    Size:            76
+    RootSignature:
+      Version: 3
+      NumRootParameters: 0
+      RootParametersOffset: 24
+      NumStaticSamplers: 1
+      StaticSamplersOffset: 24
+      Parameters: []
+      Samplers: 
+        - Filter: MinLinearMagMipPoint 
+          AddressU: Wrap
+          AddressV: Mirror
+          AddressW: MirrorOnce
+          MipLODBias: 1.23
+          MaxAnisotropy: 20
+          ComparisonFunc: LessEqual
+          BorderColor: TransparentBlack
+          MinLOD: 4.56
+          MaxLOD: 8.90
+          ShaderRegister: 31 
+          RegisterSpace: 32
+          ShaderVisibility:  Mesh
+          SAMPLER_FLAG_UINT_BORDER_COLOR: true
+      AllowInputAssemblerInputLayout: true
+      DenyGeometryShaderRootAccess: true
+    )"));
+
+  uint8_t Buffer[] = {
+      0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+      0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+      0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41,
+      0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+      0x01};
+
+  EXPECT_EQ(Storage.size(), 148U);
+  EXPECT_TRUE(memcmp(Buffer, Storage.data(), 148U) == 0);
+}

>From 57fd710107c459b53e2f9fe2c3f0de3f24d6b064 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Thu, 18 Sep 2025 16:54:27 -0700
Subject: [PATCH 02/19] fix test

---
 llvm/lib/ObjectYAML/DXContainerYAML.cpp           | 4 ++--
 llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp 
b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 39f42fb4dc839..42074731c4e16 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -521,8 +521,8 @@ void 
MappingTraits<llvm::DXContainerYAML::StaticSamplerYamlDesc>::mapping(
   IO.mapRequired("ShaderRegister", S.ShaderRegister);
   IO.mapRequired("RegisterSpace", S.RegisterSpace);
   IO.mapRequired("ShaderVisibility", S.ShaderVisibility);
-
-#define STATIC_SAMPLER_FLAG_FLAG(Num, Val) IO.mapOptional(#Val, S.Val, false);
+#define STATIC_SAMPLER_FLAG(Num, Enum, Flag)                                   
\
+  IO.mapOptional(#Flag, S.Enum, false);
 #include "llvm/BinaryFormat/DXContainerConstants.def"
 }
 
diff --git a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp 
b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
index eee0b64e4b866..db9861f0149a4 100644
--- a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
+++ b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
@@ -528,7 +528,7 @@ TEST(RootSignature, ParseStaticSamplers) {
 }
 
 TEST(RootSignature, ParseStaticSamplersV13) {
-  SmallString<128> Storage;
+  SmallString<160> Storage;
 
   // First read a fully explicit yaml with all sizes and offsets provided
   ASSERT_TRUE(convert(Storage, R"(--- !dxcontainer
@@ -575,14 +575,14 @@ TEST(RootSignature, ParseStaticSamplersV13) {
       0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+      0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
       0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
       0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
       0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41,
       0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-      0x01};
+      0x01, 0x00, 0x00, 0x00};
 
   EXPECT_EQ(Storage.size(), 148U);
   EXPECT_TRUE(memcmp(Buffer, Storage.data(), 148U) == 0);

>From d72adfe11a56a57e970f28b7ff0725c316ec8900 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Fri, 19 Sep 2025 10:46:53 -0700
Subject: [PATCH 03/19] adding missing test

---
 .../RootSignature-Invalid-Version.ll          | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 
llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Invalid-Version.ll

diff --git 
a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Invalid-Version.ll 
b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Invalid-Version.ll
new file mode 100644
index 0000000000000..26867e6d7ec25
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Invalid-Version.ll
@@ -0,0 +1,20 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | 
FileCheck %s
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+
+; CHECK: error: Invalid value for Version: 4
+; CHECK-NOT: Root Signature Definitions
+define void @main() #0 {
+entry:
+  ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2, !3, !4, !5} ; list of function/root signature pairs
+!2 = !{ ptr @main, !6, i32 1 } ; function, root signature
+!3 = !{ ptr @main, !6, i32 4 } ; function, root signature
+!4 = !{ ptr @main, !6, i32 2 } ; function, root signature
+!5 = !{ ptr @main, !6, i32 3 } ; function, root signature
+!6 = !{ } ; list of root signature elements

>From fefd58c2ab1044ac51c546b6bc6df968eb5edaa8 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Fri, 19 Sep 2025 12:48:11 -0700
Subject: [PATCH 04/19] fix test

---
 llvm/include/llvm/Object/DXContainer.h    | 57 ++++++++++++++++-------
 llvm/lib/ObjectYAML/DXContainerYAML.cpp   | 16 ++++++-
 llvm/unittests/Object/DXContainerTest.cpp | 16 ++++---
 3 files changed, 63 insertions(+), 26 deletions(-)

diff --git a/llvm/include/llvm/Object/DXContainer.h 
b/llvm/include/llvm/Object/DXContainer.h
index 9bc1918852335..e3e532f6635a4 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -123,25 +123,26 @@ template <typename T> struct ViewArray {
 };
 
 namespace DirectX {
+
+template <typename T> Expected<T> readParameter(StringRef Data) {
+  T Struct;
+  if (sizeof(T) != Data.size())
+    return make_error<GenericBinaryError>(
+        "Reading structure out of file bounds", object_error::parse_failed);
+
+  memcpy(&Struct, Data.data(), sizeof(T));
+  // DXContainer is always little endian
+  if (sys::IsBigEndianHost)
+    Struct.swapBytes();
+  return Struct;
+}
+
 struct RootParameterView {
   const dxbc::RTS0::v1::RootParameterHeader &Header;
   StringRef ParamData;
 
   RootParameterView(const dxbc::RTS0::v1::RootParameterHeader &H, StringRef P)
       : Header(H), ParamData(P) {}
-
-  template <typename T> Expected<T> readParameter() {
-    T Struct;
-    if (sizeof(T) != ParamData.size())
-      return make_error<GenericBinaryError>(
-          "Reading structure out of file bounds", object_error::parse_failed);
-
-    memcpy(&Struct, ParamData.data(), sizeof(T));
-    // DXContainer is always little endian
-    if (sys::IsBigEndianHost)
-      Struct.swapBytes();
-    return Struct;
-  }
 };
 
 struct RootConstantView : RootParameterView {
@@ -151,7 +152,7 @@ struct RootConstantView : RootParameterView {
   }
 
   llvm::Expected<dxbc::RTS0::v1::RootConstants> read() {
-    return readParameter<dxbc::RTS0::v1::RootConstants>();
+    return readParameter<dxbc::RTS0::v1::RootConstants>(ParamData);
   }
 };
 
@@ -167,7 +168,8 @@ struct RootDescriptorView : RootParameterView {
 
   llvm::Expected<dxbc::RTS0::v2::RootDescriptor> read(uint32_t Version) {
     if (Version == 1) {
-      auto Descriptor = readParameter<dxbc::RTS0::v1::RootDescriptor>();
+      auto Descriptor =
+          readParameter<dxbc::RTS0::v1::RootDescriptor>(ParamData);
       if (Error E = Descriptor.takeError())
         return E;
       return dxbc::RTS0::v2::RootDescriptor(*Descriptor);
@@ -176,9 +178,10 @@ struct RootDescriptorView : RootParameterView {
       return make_error<GenericBinaryError>("Invalid Root Signature version: " 
+
                                                 Twine(Version),
                                             object_error::parse_failed);
-    return readParameter<dxbc::RTS0::v2::RootDescriptor>();
+    return readParameter<dxbc::RTS0::v2::RootDescriptor>(ParamData);
   }
 };
+
 template <typename T> struct DescriptorTable {
   uint32_t NumRanges;
   uint32_t RangesOffset;
@@ -247,8 +250,26 @@ class RootSignature {
   llvm::iterator_range<param_header_iterator> param_headers() const {
     return llvm::make_range(ParametersHeaders.begin(), 
ParametersHeaders.end());
   }
-  llvm::iterator_range<samplers_iterator> samplers() const {
-    return llvm::make_range(StaticSamplers.begin(), StaticSamplers.end());
+  llvm::Expected<dxbc::RTS0::v3::StaticSampler> getSampler(uint32_t Loc) const 
{
+    if (Loc >= getNumStaticSamplers())
+      return parseFailed("Static sampler index out of range");
+
+    auto SamplerSize = (Version <= 2) ? sizeof(dxbc::RTS0::v1::StaticSampler)
+                                     : sizeof(dxbc::RTS0::v3::StaticSampler);
+
+    StringRef Buff = PartData.substr(StaticSamplersOffset + (Loc * 
SamplerSize),
+                                     SamplerSize);
+    if (Version < 3) {
+      auto Sampler = readParameter<dxbc::RTS0::v1::StaticSampler>(Buff);
+      if (Error E = Sampler.takeError())
+        return E;
+      return dxbc::RTS0::v3::StaticSampler(*Sampler);
+    }
+    if (Version != 3)
+      return make_error<GenericBinaryError>("Invalid Root Signature version: " 
+
+                                                Twine(Version),
+                                            object_error::parse_failed);
+    return readParameter<dxbc::RTS0::v3::StaticSampler>(Buff);
   }
   uint32_t getFlags() const { return Flags; }
 
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp 
b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 42074731c4e16..6f24b7d2573ec 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -163,7 +163,13 @@ DXContainerYAML::RootSignatureYamlDesc::create(
     }
   }
 
-  for (const auto &S : Data.samplers()) {
+  for (uint32_t Loc = 0; Loc < Data.getNumStaticSamplers(); ++Loc) {
+    llvm::Expected<dxbc::RTS0::v3::StaticSampler> MaybeSampler =
+        Data.getSampler(Loc);
+    if (Error E = MaybeSampler.takeError())
+      return std::move(E);
+    const llvm::dxbc::RTS0::v3::StaticSampler &S = *MaybeSampler;
+
     if (!dxbc::isValidSamplerFilter(S.Filter))
       return createStringError(std::errc::invalid_argument,
                                "Invalid value for static sampler filter");
@@ -209,6 +215,14 @@ DXContainerYAML::RootSignatureYamlDesc::create(
     NewS.RegisterSpace = S.RegisterSpace;
     NewS.ShaderVisibility = dxbc::ShaderVisibility(S.ShaderVisibility);
 
+    if (Version > 2) {
+      if (Version > 1) {
+#define STATIC_SAMPLER_FLAG(Num, Enum, Flag)                                   
\
+  NewS.Enum =                                                                  
\
+      (S.Flags & llvm::to_underlying(dxbc::StaticSamplerFlags::Enum)) > 0;
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+      }
+    }
     RootSigDesc.StaticSamplers.push_back(NewS);
   }
 
diff --git a/llvm/unittests/Object/DXContainerTest.cpp 
b/llvm/unittests/Object/DXContainerTest.cpp
index 396d060a75bfd..f2a7bdfdcd75a 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -1165,11 +1165,11 @@ TEST(RootSignature, ParseStaticSamplers) {
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-        0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
-        0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-        0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41,
+        0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00,
+        0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+        0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x7f,
         0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 
0x00};
     DXContainer C =
         llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));
@@ -1179,12 +1179,14 @@ TEST(RootSignature, ParseStaticSamplers) {
     const auto &RS = MaybeRS.value();
     ASSERT_EQ(RS.getVersion(), 2u);
     ASSERT_EQ(RS.getNumParameters(), 0u);
-    ASSERT_EQ(RS.getRootParametersOffset(), 0u);
+    ASSERT_EQ(RS.getRootParametersOffset(), 24u);
     ASSERT_EQ(RS.getNumStaticSamplers(), 1u);
     ASSERT_EQ(RS.getStaticSamplersOffset(), 24u);
     ASSERT_EQ(RS.getFlags(), 17u);
 
-    auto Sampler = *RS.samplers().begin();
+    auto MaybeSamplerView = RS.getSampler(0);
+    ASSERT_THAT_ERROR(MaybeSamplerView.takeError(), Succeeded());
+    const auto &Sampler = *MaybeSamplerView;
 
     ASSERT_EQ(Sampler.Filter, 10u);
     ASSERT_EQ(Sampler.AddressU, 1u);

>From 1d0cbd39875a84c983106678c8b857d8157bfa51 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Mon, 22 Sep 2025 10:28:12 -0700
Subject: [PATCH 05/19] adding samplers_iterator

---
 llvm/include/llvm/Object/DXContainer.h    | 70 +++++++++++++++++------
 llvm/lib/ObjectYAML/DXContainerYAML.cpp   |  5 +-
 llvm/unittests/Object/DXContainerTest.cpp |  2 +-
 3 files changed, 56 insertions(+), 21 deletions(-)

diff --git a/llvm/include/llvm/Object/DXContainer.h 
b/llvm/include/llvm/Object/DXContainer.h
index e3e532f6635a4..e3913ece842bc 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -223,6 +223,28 @@ static Error parseFailed(const Twine &Msg) {
 
 class RootSignature {
 private:
+  struct samplers_iterator {
+    const RootSignature *Parent = nullptr;
+    uint32_t Index = 0;
+
+    llvm::Expected<dxbc::RTS0::v3::StaticSampler> operator*() const {
+      return Parent->getSampler(Index);
+    }
+
+    samplers_iterator &operator++() {
+      ++Index;
+      return *this;
+    }
+
+    bool operator==(const samplers_iterator &Other) const {
+      return Parent == Other.Parent && Index == Other.Index;
+    }
+
+    bool operator!=(const samplers_iterator &Other) const {
+      return !(*this == Other);
+    }
+  };
+
   uint32_t Version;
   uint32_t NumParameters;
   uint32_t RootParametersOffset;
@@ -233,23 +255,6 @@ class RootSignature {
   StringRef PartData;
   ViewArray<dxbc::RTS0::v1::StaticSampler> StaticSamplers;
 
-  using param_header_iterator =
-      ViewArray<dxbc::RTS0::v1::RootParameterHeader>::iterator;
-  using samplers_iterator = ViewArray<dxbc::RTS0::v1::StaticSampler>::iterator;
-
-public:
-  RootSignature(StringRef PD) : PartData(PD) {}
-
-  LLVM_ABI Error parse();
-  uint32_t getVersion() const { return Version; }
-  uint32_t getNumParameters() const { return NumParameters; }
-  uint32_t getRootParametersOffset() const { return RootParametersOffset; }
-  uint32_t getNumStaticSamplers() const { return NumStaticSamplers; }
-  uint32_t getStaticSamplersOffset() const { return StaticSamplersOffset; }
-  uint32_t getNumRootParameters() const { return ParametersHeaders.size(); }
-  llvm::iterator_range<param_header_iterator> param_headers() const {
-    return llvm::make_range(ParametersHeaders.begin(), 
ParametersHeaders.end());
-  }
   llvm::Expected<dxbc::RTS0::v3::StaticSampler> getSampler(uint32_t Loc) const 
{
     if (Loc >= getNumStaticSamplers())
       return parseFailed("Static sampler index out of range");
@@ -271,6 +276,37 @@ class RootSignature {
                                             object_error::parse_failed);
     return readParameter<dxbc::RTS0::v3::StaticSampler>(Buff);
   }
+
+  using param_header_iterator =
+      ViewArray<dxbc::RTS0::v1::RootParameterHeader>::iterator;
+
+public:
+  RootSignature(StringRef PD) : PartData(PD) {}
+
+  LLVM_ABI Error parse();
+  uint32_t getVersion() const { return Version; }
+  uint32_t getNumParameters() const { return NumParameters; }
+  uint32_t getRootParametersOffset() const { return RootParametersOffset; }
+  uint32_t getNumStaticSamplers() const { return NumStaticSamplers; }
+  uint32_t getStaticSamplersOffset() const { return StaticSamplersOffset; }
+  uint32_t getNumRootParameters() const { return ParametersHeaders.size(); }
+
+  samplers_iterator samplers_begin() const {
+    return samplers_iterator{this, 0};
+  }
+
+  samplers_iterator samplers_end() const {
+    return samplers_iterator{this, getNumStaticSamplers()};
+  }
+
+  llvm::iterator_range<samplers_iterator> samplers() const {
+    return llvm::make_range(samplers_begin(), samplers_end());
+  }
+
+  llvm::iterator_range<param_header_iterator> param_headers() const {
+    return llvm::make_range(ParametersHeaders.begin(), 
ParametersHeaders.end());
+  }
+
   uint32_t getFlags() const { return Flags; }
 
   llvm::Expected<RootParameterView>
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp 
b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 6f24b7d2573ec..91f86caaa4005 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -163,9 +163,8 @@ DXContainerYAML::RootSignatureYamlDesc::create(
     }
   }
 
-  for (uint32_t Loc = 0; Loc < Data.getNumStaticSamplers(); ++Loc) {
-    llvm::Expected<dxbc::RTS0::v3::StaticSampler> MaybeSampler =
-        Data.getSampler(Loc);
+  for (llvm::Expected<dxbc::RTS0::v3::StaticSampler> MaybeSampler :
+       Data.samplers()) {
     if (Error E = MaybeSampler.takeError())
       return std::move(E);
     const llvm::dxbc::RTS0::v3::StaticSampler &S = *MaybeSampler;
diff --git a/llvm/unittests/Object/DXContainerTest.cpp 
b/llvm/unittests/Object/DXContainerTest.cpp
index 923df70f44194..fe898c430b8a3 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -1184,7 +1184,7 @@ TEST(RootSignature, ParseStaticSamplers) {
     ASSERT_EQ(RS.getStaticSamplersOffset(), 24u);
     ASSERT_EQ(RS.getFlags(), 17u);
 
-    auto MaybeSamplerView = RS.getSampler(0);
+    auto MaybeSamplerView = *RS.samplers().begin();
     ASSERT_THAT_ERROR(MaybeSamplerView.takeError(), Succeeded());
     const auto &Sampler = *MaybeSamplerView;
 

>From e530bcc1b81b300a12ada139c54553b84ab89a03 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Mon, 22 Sep 2025 11:29:55 -0700
Subject: [PATCH 06/19] this was easier than I thought

---
 llvm/include/llvm/Object/DXContainer.h    | 62 ++---------------------
 llvm/lib/Object/DXContainer.cpp           | 13 +++--
 llvm/lib/ObjectYAML/DXContainerYAML.cpp   |  6 +--
 llvm/unittests/Object/DXContainerTest.cpp | 49 ++++++++++++++++--
 4 files changed, 61 insertions(+), 69 deletions(-)

diff --git a/llvm/include/llvm/Object/DXContainer.h 
b/llvm/include/llvm/Object/DXContainer.h
index e3913ece842bc..0bfc5cec48da4 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -223,28 +223,6 @@ static Error parseFailed(const Twine &Msg) {
 
 class RootSignature {
 private:
-  struct samplers_iterator {
-    const RootSignature *Parent = nullptr;
-    uint32_t Index = 0;
-
-    llvm::Expected<dxbc::RTS0::v3::StaticSampler> operator*() const {
-      return Parent->getSampler(Index);
-    }
-
-    samplers_iterator &operator++() {
-      ++Index;
-      return *this;
-    }
-
-    bool operator==(const samplers_iterator &Other) const {
-      return Parent == Other.Parent && Index == Other.Index;
-    }
-
-    bool operator!=(const samplers_iterator &Other) const {
-      return !(*this == Other);
-    }
-  };
-
   uint32_t Version;
   uint32_t NumParameters;
   uint32_t RootParametersOffset;
@@ -253,32 +231,11 @@ class RootSignature {
   uint32_t Flags;
   ViewArray<dxbc::RTS0::v1::RootParameterHeader> ParametersHeaders;
   StringRef PartData;
-  ViewArray<dxbc::RTS0::v1::StaticSampler> StaticSamplers;
-
-  llvm::Expected<dxbc::RTS0::v3::StaticSampler> getSampler(uint32_t Loc) const 
{
-    if (Loc >= getNumStaticSamplers())
-      return parseFailed("Static sampler index out of range");
-
-    auto SamplerSize = (Version <= 2) ? sizeof(dxbc::RTS0::v1::StaticSampler)
-                                     : sizeof(dxbc::RTS0::v3::StaticSampler);
-
-    StringRef Buff = PartData.substr(StaticSamplersOffset + (Loc * 
SamplerSize),
-                                     SamplerSize);
-    if (Version < 3) {
-      auto Sampler = readParameter<dxbc::RTS0::v1::StaticSampler>(Buff);
-      if (Error E = Sampler.takeError())
-        return E;
-      return dxbc::RTS0::v3::StaticSampler(*Sampler);
-    }
-    if (Version != 3)
-      return make_error<GenericBinaryError>("Invalid Root Signature version: " 
+
-                                                Twine(Version),
-                                            object_error::parse_failed);
-    return readParameter<dxbc::RTS0::v3::StaticSampler>(Buff);
-  }
+  ViewArray<dxbc::RTS0::v3::StaticSampler> StaticSamplers;
 
   using param_header_iterator =
       ViewArray<dxbc::RTS0::v1::RootParameterHeader>::iterator;
+  using samplers_iterator = ViewArray<dxbc::RTS0::v3::StaticSampler>::iterator;
 
 public:
   RootSignature(StringRef PD) : PartData(PD) {}
@@ -290,21 +247,12 @@ class RootSignature {
   uint32_t getNumStaticSamplers() const { return NumStaticSamplers; }
   uint32_t getStaticSamplersOffset() const { return StaticSamplersOffset; }
   uint32_t getNumRootParameters() const { return ParametersHeaders.size(); }
-
-  samplers_iterator samplers_begin() const {
-    return samplers_iterator{this, 0};
-  }
-
-  samplers_iterator samplers_end() const {
-    return samplers_iterator{this, getNumStaticSamplers()};
+  llvm::iterator_range<param_header_iterator> param_headers() const {
+    return llvm::make_range(ParametersHeaders.begin(), 
ParametersHeaders.end());
   }
 
   llvm::iterator_range<samplers_iterator> samplers() const {
-    return llvm::make_range(samplers_begin(), samplers_end());
-  }
-
-  llvm::iterator_range<param_header_iterator> param_headers() const {
-    return llvm::make_range(ParametersHeaders.begin(), 
ParametersHeaders.end());
+    return llvm::make_range(StaticSamplers.begin(), StaticSamplers.end());
   }
 
   uint32_t getFlags() const { return Flags; }
diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
index 031b9414f4c1a..b7da8316840f0 100644
--- a/llvm/lib/Object/DXContainer.cpp
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -6,6 +6,8 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include <cstddef>
+
 #include "llvm/Object/DXContainer.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Object/Error.h"
@@ -276,10 +278,13 @@ Error DirectX::RootSignature::parse() {
       RootParametersOffset,
       NumParameters * sizeof(dxbc::RTS0::v1::RootParameterHeader));
 
-  StaticSamplers.Stride = sizeof(dxbc::RTS0::v1::StaticSampler);
-  StaticSamplers.Data = PartData.substr(
-      StaticSamplersOffset,
-      NumStaticSamplers * sizeof(dxbc::RTS0::v1::StaticSampler));
+  StaticSamplers.Stride = (Version <= 2)
+                              ? sizeof(dxbc::RTS0::v1::StaticSampler)
+                              : sizeof(dxbc::RTS0::v3::StaticSampler);
+
+  StaticSamplers.Data = PartData.substr(StaticSamplersOffset,
+                                        static_cast<size_t>(NumStaticSamplers) 
*
+                                            StaticSamplers.Stride);
 
   return Error::success();
 }
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp 
b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 91f86caaa4005..2fde1b86247f8 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -163,11 +163,7 @@ DXContainerYAML::RootSignatureYamlDesc::create(
     }
   }
 
-  for (llvm::Expected<dxbc::RTS0::v3::StaticSampler> MaybeSampler :
-       Data.samplers()) {
-    if (Error E = MaybeSampler.takeError())
-      return std::move(E);
-    const llvm::dxbc::RTS0::v3::StaticSampler &S = *MaybeSampler;
+  for (const auto &S : Data.samplers()) {
 
     if (!dxbc::isValidSamplerFilter(S.Filter))
       return createStringError(std::errc::invalid_argument,
diff --git a/llvm/unittests/Object/DXContainerTest.cpp 
b/llvm/unittests/Object/DXContainerTest.cpp
index fe898c430b8a3..76b2aed5bb591 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -1184,9 +1184,7 @@ TEST(RootSignature, ParseStaticSamplers) {
     ASSERT_EQ(RS.getStaticSamplersOffset(), 24u);
     ASSERT_EQ(RS.getFlags(), 17u);
 
-    auto MaybeSamplerView = *RS.samplers().begin();
-    ASSERT_THAT_ERROR(MaybeSamplerView.takeError(), Succeeded());
-    const auto &Sampler = *MaybeSamplerView;
+    auto Sampler = *RS.samplers().begin();
 
     ASSERT_EQ(Sampler.Filter, 10u);
     ASSERT_EQ(Sampler.AddressU, 1u);
@@ -1202,4 +1200,49 @@ TEST(RootSignature, ParseStaticSamplers) {
     ASSERT_EQ(Sampler.RegisterSpace, 32u);
     ASSERT_EQ(Sampler.ShaderVisibility, 7u);
   }
+  {
+    uint8_t Buffer[] = {
+        0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+        0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+        0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41,
+        0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+        0x01, 0x00, 0x00, 0x00};
+    DXContainer C =
+        llvm::cantFail(DXContainer::create(getMemoryBuffer<148>(Buffer)));
+
+    auto MaybeRS = C.getRootSignature();
+    ASSERT_TRUE(MaybeRS.has_value());
+    const auto &RS = MaybeRS.value();
+    ASSERT_EQ(RS.getVersion(), 3U);
+    ASSERT_EQ(RS.getNumParameters(), 0U);
+    ASSERT_EQ(RS.getRootParametersOffset(), 0U);
+    ASSERT_EQ(RS.getNumStaticSamplers(), 1U);
+    ASSERT_EQ(RS.getStaticSamplersOffset(), 24U);
+    ASSERT_EQ(RS.getFlags(), 17U);
+
+    auto Sampler = *RS.samplers().begin();
+
+    ASSERT_EQ(Sampler.Filter, 10U);
+    ASSERT_EQ(Sampler.AddressU, 1U);
+    ASSERT_EQ(Sampler.AddressV, 2U);
+    ASSERT_EQ(Sampler.AddressW, 5U);
+    ASSERT_FLOAT_EQ(Sampler.MipLODBias, 1.23F);
+    ASSERT_EQ(Sampler.MaxAnisotropy, 20U);
+    ASSERT_EQ(Sampler.ComparisonFunc, 4U);
+    ASSERT_EQ(Sampler.BorderColor, 0U);
+    ASSERT_FLOAT_EQ(Sampler.MinLOD, 4.56F);
+    ASSERT_FLOAT_EQ(Sampler.MaxLOD, 8.9F);
+    ASSERT_EQ(Sampler.ShaderRegister, 31U);
+    ASSERT_EQ(Sampler.RegisterSpace, 32U);
+    ASSERT_EQ(Sampler.ShaderVisibility, 7U);
+    ASSERT_EQ(Sampler.Flags, 1U);
+  }
 }

>From 79ea587527552aaf93110098b526a88edbce620b Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Mon, 22 Sep 2025 12:17:34 -0700
Subject: [PATCH 07/19] adding new test

---
 llvm/lib/ObjectYAML/DXContainerYAML.cpp       |  2 -
 .../RootSignature-StaticSamplers1.3.yaml      | 65 +++++++++++++++++++
 2 files changed, 65 insertions(+), 2 deletions(-)
 create mode 100644 
llvm/test/ObjectYAML/DXContainer/RootSignature-StaticSamplers1.3.yaml

diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp 
b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 2fde1b86247f8..806722be0813d 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -211,12 +211,10 @@ DXContainerYAML::RootSignatureYamlDesc::create(
     NewS.ShaderVisibility = dxbc::ShaderVisibility(S.ShaderVisibility);
 
     if (Version > 2) {
-      if (Version > 1) {
 #define STATIC_SAMPLER_FLAG(Num, Enum, Flag)                                   
\
   NewS.Enum =                                                                  
\
       (S.Flags & llvm::to_underlying(dxbc::StaticSamplerFlags::Enum)) > 0;
 #include "llvm/BinaryFormat/DXContainerConstants.def"
-      }
     }
     RootSigDesc.StaticSamplers.push_back(NewS);
   }
diff --git 
a/llvm/test/ObjectYAML/DXContainer/RootSignature-StaticSamplers1.3.yaml 
b/llvm/test/ObjectYAML/DXContainer/RootSignature-StaticSamplers1.3.yaml
new file mode 100644
index 0000000000000..1623b05def009
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-StaticSamplers1.3.yaml
@@ -0,0 +1,65 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  PartCount:       1
+  PartOffsets:     [ 60 ]
+Parts:
+  - Name:            RTS0
+    Size:            80
+    RootSignature:
+      Version: 3
+      NumRootParameters: 0
+      RootParametersOffset: 24
+      NumStaticSamplers: 1
+      StaticSamplersOffset: 24
+      Parameters: []
+      Samplers: 
+        - Filter: MinLinearMagMipPoint 
+          AddressU: Wrap
+          AddressV: Mirror
+          AddressW: MirrorOnce
+          MipLODBias: 1.23
+          MaxAnisotropy: 20
+          ComparisonFunc: LessEqual
+          BorderColor: TransparentBlack
+          MinLOD: 4.56
+          MaxLOD: 8.90
+          ShaderRegister: 31 
+          RegisterSpace: 32
+          ShaderVisibility:  Mesh
+          SAMPLER_FLAG_UINT_BORDER_COLOR: true
+      AllowInputAssemblerInputLayout: true
+      DenyGeometryShaderRootAccess: true
+
+#CHECK:  - Name:            RTS0
+#CHECK-NEXT:    Size:            80
+#CHECK-NEXT:    RootSignature:
+#CHECK-NEXT:      Version:         3
+#CHECK-NEXT:      NumRootParameters: 0
+#CHECK-NEXT:      RootParametersOffset: 24
+#CHECK-NEXT:      NumStaticSamplers: 1
+#CHECK-NEXT:      StaticSamplersOffset: 24
+#CHECK-NEXT:      Parameters:      []
+#CHECK-NEXT:      Samplers:
+#CHECK-NEXT:        - Filter:          MinLinearMagMipPoint
+#CHECK-NEXT:          AddressU:        Wrap
+#CHECK-NEXT:          AddressV:        Mirror
+#CHECK-NEXT:          AddressW:        MirrorOnce
+#CHECK-NEXT:          MipLODBias:      1.23
+#CHECK-NEXT:          MaxAnisotropy:   20
+#CHECK-NEXT:          ComparisonFunc:  LessEqual
+#CHECK-NEXT:          BorderColor:     TransparentBlack
+#CHECK-NEXT:          MinLOD:          4.56
+#CHECK-NEXT:          MaxLOD:          8.9
+#CHECK-NEXT:          ShaderRegister:  31
+#CHECK-NEXT:          RegisterSpace:   32
+#CHECK-NEXT:          ShaderVisibility: Mesh
+#CHECK-NEXT:          SAMPLER_FLAG_UINT_BORDER_COLOR: true
+#CHECK-NEXT:      AllowInputAssemblerInputLayout: true
+#CHECK-NEXT:      DenyGeometryShaderRootAccess: true

>From 905d5d39d93e35a512537bec76566abefc79ce27 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Mon, 22 Sep 2025 12:32:25 -0700
Subject: [PATCH 08/19] clean up

---
 llvm/include/llvm/Object/DXContainer.h    | 33 +++++++++++------------
 llvm/lib/Object/DXContainer.cpp           |  2 --
 llvm/lib/ObjectYAML/DXContainerYAML.cpp   |  1 -
 llvm/unittests/Object/DXContainerTest.cpp |  2 +-
 4 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/llvm/include/llvm/Object/DXContainer.h 
b/llvm/include/llvm/Object/DXContainer.h
index 0bfc5cec48da4..6f10401dd2ba2 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -124,25 +124,25 @@ template <typename T> struct ViewArray {
 
 namespace DirectX {
 
-template <typename T> Expected<T> readParameter(StringRef Data) {
-  T Struct;
-  if (sizeof(T) != Data.size())
-    return make_error<GenericBinaryError>(
-        "Reading structure out of file bounds", object_error::parse_failed);
-
-  memcpy(&Struct, Data.data(), sizeof(T));
-  // DXContainer is always little endian
-  if (sys::IsBigEndianHost)
-    Struct.swapBytes();
-  return Struct;
-}
-
 struct RootParameterView {
   const dxbc::RTS0::v1::RootParameterHeader &Header;
   StringRef ParamData;
 
   RootParameterView(const dxbc::RTS0::v1::RootParameterHeader &H, StringRef P)
       : Header(H), ParamData(P) {}
+
+  template <typename T> Expected<T> readParameter() {
+    T Struct;
+    if (sizeof(T) != ParamData.size())
+      return make_error<GenericBinaryError>(
+          "Reading structure out of file bounds", object_error::parse_failed);
+
+    memcpy(&Struct, ParamData.data(), sizeof(T));
+    // DXContainer is always little endian
+    if (sys::IsBigEndianHost)
+      Struct.swapBytes();
+    return Struct;
+  }
 };
 
 struct RootConstantView : RootParameterView {
@@ -152,7 +152,7 @@ struct RootConstantView : RootParameterView {
   }
 
   llvm::Expected<dxbc::RTS0::v1::RootConstants> read() {
-    return readParameter<dxbc::RTS0::v1::RootConstants>(ParamData);
+    return readParameter<dxbc::RTS0::v1::RootConstants>();
   }
 };
 
@@ -168,8 +168,7 @@ struct RootDescriptorView : RootParameterView {
 
   llvm::Expected<dxbc::RTS0::v2::RootDescriptor> read(uint32_t Version) {
     if (Version == 1) {
-      auto Descriptor =
-          readParameter<dxbc::RTS0::v1::RootDescriptor>(ParamData);
+      auto Descriptor = readParameter<dxbc::RTS0::v1::RootDescriptor>();
       if (Error E = Descriptor.takeError())
         return E;
       return dxbc::RTS0::v2::RootDescriptor(*Descriptor);
@@ -178,7 +177,7 @@ struct RootDescriptorView : RootParameterView {
       return make_error<GenericBinaryError>("Invalid Root Signature version: " 
+
                                                 Twine(Version),
                                             object_error::parse_failed);
-    return readParameter<dxbc::RTS0::v2::RootDescriptor>(ParamData);
+    return readParameter<dxbc::RTS0::v2::RootDescriptor>();
   }
 };
 
diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
index b7da8316840f0..7b7b8d88c63fc 100644
--- a/llvm/lib/Object/DXContainer.cpp
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -6,8 +6,6 @@
 //
 
//===----------------------------------------------------------------------===//
 
-#include <cstddef>
-
 #include "llvm/Object/DXContainer.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Object/Error.h"
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp 
b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 806722be0813d..bfb3837707f0a 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -164,7 +164,6 @@ DXContainerYAML::RootSignatureYamlDesc::create(
   }
 
   for (const auto &S : Data.samplers()) {
-
     if (!dxbc::isValidSamplerFilter(S.Filter))
       return createStringError(std::errc::invalid_argument,
                                "Invalid value for static sampler filter");
diff --git a/llvm/unittests/Object/DXContainerTest.cpp 
b/llvm/unittests/Object/DXContainerTest.cpp
index 76b2aed5bb591..7fec8addc8d52 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -1172,7 +1172,7 @@ TEST(RootSignature, ParseStaticSamplers) {
         0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41,
         0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 
0x00};
     DXContainer C =
-        llvm::cantFail(DXContainer::create(getMemoryBuffer<144>(Buffer)));
+        llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));
 
     auto MaybeRS = C.getRootSignature();
     ASSERT_TRUE(MaybeRS.has_value());

>From b73bf248c1225498e6372d25f8e75ce6a03d5489 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Mon, 22 Sep 2025 12:33:59 -0700
Subject: [PATCH 09/19] clean up

---
 llvm/include/llvm/Object/DXContainer.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/llvm/include/llvm/Object/DXContainer.h 
b/llvm/include/llvm/Object/DXContainer.h
index 6f10401dd2ba2..5a5a4dbaae2ad 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -123,7 +123,6 @@ template <typename T> struct ViewArray {
 };
 
 namespace DirectX {
-
 struct RootParameterView {
   const dxbc::RTS0::v1::RootParameterHeader &Header;
   StringRef ParamData;
@@ -180,7 +179,6 @@ struct RootDescriptorView : RootParameterView {
     return readParameter<dxbc::RTS0::v2::RootDescriptor>();
   }
 };
-
 template <typename T> struct DescriptorTable {
   uint32_t NumRanges;
   uint32_t RangesOffset;
@@ -249,11 +247,9 @@ class RootSignature {
   llvm::iterator_range<param_header_iterator> param_headers() const {
     return llvm::make_range(ParametersHeaders.begin(), 
ParametersHeaders.end());
   }
-
   llvm::iterator_range<samplers_iterator> samplers() const {
     return llvm::make_range(StaticSamplers.begin(), StaticSamplers.end());
   }
-
   uint32_t getFlags() const { return Flags; }
 
   llvm::Expected<RootParameterView>

>From bc393fda07547bbd8abc24701c8bfc3495db2e89 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Mon, 22 Sep 2025 16:49:12 -0700
Subject: [PATCH 10/19] adding flags to static sampler parser

---
 .../clang/Lex/HLSLRootSignatureTokenKinds.def |  8 +++
 .../clang/Parse/ParseHLSLRootSignature.h      |  3 +
 clang/lib/Parse/ParseHLSLRootSignature.cpp    | 61 +++++++++++++++++++
 .../Lex/LexHLSLRootSignatureTest.cpp          |  3 +
 .../llvm/Frontend/HLSL/HLSLRootSignature.h    |  1 +
 llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp  |  2 +-
 6 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def 
b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def
index a5cfeb34b2b51..1d7f7adbe076f 100644
--- a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def
+++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def
@@ -65,6 +65,9 @@
 #ifndef STATIC_BORDER_COLOR_ENUM
 #define STATIC_BORDER_COLOR_ENUM(NAME, LIT) ENUM(NAME, LIT)
 #endif
+#ifndef STATIC_SAMPLER_FLAG_ENUM
+#define STATIC_SAMPLER_FLAG_ENUM(NAME, LIT) ENUM(NAME, LIT)
+#endif
 
 // General Tokens:
 TOK(invalid, "invalid identifier")
@@ -228,6 +231,10 @@ STATIC_BORDER_COLOR_ENUM(OpaqueWhite, 
"STATIC_BORDER_COLOR_OPAQUE_WHITE")
 STATIC_BORDER_COLOR_ENUM(OpaqueBlackUint, 
"STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT")
 STATIC_BORDER_COLOR_ENUM(OpaqueWhiteUint, 
"STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT")
 
+// Root Descriptor Flag Enums:
+STATIC_SAMPLER_FLAG_ENUM(UintBorderColor, "UINT_BORDER_COLOR")
+STATIC_SAMPLER_FLAG_ENUM(NonNormalizedCoordinates, 
"NON_NORMALIZED_COORDINATES")
+
 #undef STATIC_BORDER_COLOR_ENUM
 #undef COMPARISON_FUNC_ENUM
 #undef TEXTURE_ADDRESS_MODE_ENUM
@@ -237,6 +244,7 @@ STATIC_BORDER_COLOR_ENUM(OpaqueWhiteUint, 
"STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT
 #undef DESCRIPTOR_RANGE_FLAG_ENUM_OFF
 #undef DESCRIPTOR_RANGE_FLAG_ENUM_ON
 #undef ROOT_DESCRIPTOR_FLAG_ENUM
+#undef STATIC_SAMPLER_FLAG_ENUM
 #undef ROOT_FLAG_ENUM
 #undef DESCRIPTOR_RANGE_OFFSET_ENUM
 #undef UNBOUNDED_ENUM
diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h 
b/clang/include/clang/Parse/ParseHLSLRootSignature.h
index b06846fd83c09..8f91d7cd7b031 100644
--- a/clang/include/clang/Parse/ParseHLSLRootSignature.h
+++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h
@@ -130,6 +130,7 @@ class RootSignatureParser {
     std::optional<float> MaxLOD;
     std::optional<uint32_t> Space;
     std::optional<llvm::dxbc::ShaderVisibility> Visibility;
+    std::optional<llvm::dxbc::StaticSamplerFlags> Flags;
   };
   std::optional<ParsedStaticSamplerParams> parseStaticSamplerParams();
 
@@ -153,6 +154,8 @@ class RootSignatureParser {
   parseRootDescriptorFlags(RootSignatureToken::Kind Context);
   std::optional<llvm::dxbc::DescriptorRangeFlags>
   parseDescriptorRangeFlags(RootSignatureToken::Kind Context);
+  std::optional<llvm::dxbc::StaticSamplerFlags>
+  parseStaticSamplerFlags(RootSignatureToken::Kind Context);
 
   /// Use NumericLiteralParser to convert CurToken.NumSpelling into a unsigned
   /// 32-bit integer
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp 
b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 3b16efb1f1199..5677365688413 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -485,6 +485,9 @@ std::optional<StaticSampler> 
RootSignatureParser::parseStaticSampler() {
   if (Params->Visibility.has_value())
     Sampler.Visibility = Params->Visibility.value();
 
+  if (Params->Flags.has_value())
+    Sampler.Flags = Params->Flags.value();
+
   return Sampler;
 }
 
@@ -926,6 +929,20 @@ RootSignatureParser::parseStaticSamplerParams() {
       if (!Visibility.has_value())
         return std::nullopt;
       Params.Visibility = Visibility;
+    } else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
+      // `flags` `=` UINT_BORDER_COLOR
+      if (Params.Flags.has_value()) {
+        reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
+        return std::nullopt;
+      }
+
+      if (consumeExpectedToken(TokenKind::pu_equal))
+        return std::nullopt;
+
+      auto Flags = parseStaticSamplerFlags(TokenKind::kw_flags);
+      if (!Flags.has_value())
+        return std::nullopt;
+      Params.Flags = Flags;
     } else {
       consumeNextToken(); // let diagnostic be at the start of invalid token
       reportDiag(diag::err_hlsl_invalid_token)
@@ -1255,6 +1272,50 @@ RootSignatureParser::parseDescriptorRangeFlags(TokenKind 
Context) {
   return Flags;
 }
 
+std::optional<llvm::dxbc::StaticSamplerFlags>
+RootSignatureParser::parseStaticSamplerFlags(TokenKind Context) {
+  assert(CurToken.TokKind == TokenKind::pu_equal &&
+         "Expects to only be invoked starting at given keyword");
+
+  // Handle the edge-case of '0' to specify no flags set
+  if (tryConsumeExpectedToken(TokenKind::int_literal)) {
+    if (!verifyZeroFlag()) {
+      reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
+      return std::nullopt;
+    }
+    return llvm::dxbc::StaticSamplerFlags::None;
+  }
+
+  TokenKind Expected[] = {
+#define STATIC_SAMPLER_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
+#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
+  };
+
+  std::optional<llvm::dxbc::StaticSamplerFlags> Flags;
+
+  do {
+    if (tryConsumeExpectedToken(Expected)) {
+      switch (CurToken.TokKind) {
+#define STATIC_SAMPLER_FLAG_ENUM(NAME, LIT)                                    
\
+  case TokenKind::en_##NAME:                                                   
\
+    Flags = maybeOrFlag<llvm::dxbc::StaticSamplerFlags>(                       
\
+        Flags, llvm::dxbc::StaticSamplerFlags::NAME);                          
\
+    break;
+#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
+      default:
+        llvm_unreachable("Switch for consumed enum token was not provided");
+      }
+    } else {
+      consumeNextToken(); // consume token to point at invalid token
+      reportDiag(diag::err_hlsl_invalid_token)
+          << /*value=*/1 << /*value of*/ Context;
+      return std::nullopt;
+    }
+  } while (tryConsumeExpectedToken(TokenKind::pu_or));
+
+  return Flags;
+}
+
 std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {
   // Parse the numeric value and do semantic checks on its specification
   clang::NumericLiteralParser Literal(
diff --git a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp 
b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp
index 01f8d4f97b092..82f19686167da 100644
--- a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp
@@ -226,6 +226,9 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) {
     STATIC_BORDER_COLOR_OPAQUE_WHITE
     STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT
     STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT
+
+    UINT_BORDER_COLOR
+    NON_NORMALIZED_COORDINATES
   )cc";
   hlsl::RootSignatureLexer Lexer(Source);
 
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h 
b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index 87777fddc9157..37224d8a94527 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -131,6 +131,7 @@ struct StaticSampler {
   float MaxLOD = std::numeric_limits<float>::max();
   uint32_t Space = 0;
   dxbc::ShaderVisibility Visibility = dxbc::ShaderVisibility::All;
+  dxbc::StaticSamplerFlags Flags = dxbc::StaticSamplerFlags::None;
 };
 
 /// Models RootElement : RootFlags | RootConstants | RootParam
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp 
b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
index 92c62b83fadb0..f9129adb4a4f9 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -172,7 +172,7 @@ raw_ostream &operator<<(raw_ostream &OS, const 
StaticSampler &Sampler) {
      << ", borderColor = " << Sampler.BorderColor
      << ", minLOD = " << Sampler.MinLOD << ", maxLOD = " << Sampler.MaxLOD
      << ", space = " << Sampler.Space << ", visibility = " << 
Sampler.Visibility
-     << ")";
+     << ", flags = " << Sampler.Flags << ")";
   return OS;
 }
 

>From e8f7b949d921c8d180d38a923fd307e70f55d711 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saff...@microsoft.com>
Date: Tue, 23 Sep 2025 18:34:39 +0000
Subject: [PATCH 11/19] add tests

---
 clang/test/CodeGenHLSL/RootSignature.hlsl     |  5 +--
 .../Parse/ParseHLSLRootSignatureTest.cpp      | 34 ++++++++++++++++++-
 .../Frontend/HLSL/RootSignatureMetadata.cpp   |  1 +
 3 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl 
b/clang/test/CodeGenHLSL/RootSignature.hlsl
index bc40bdd79ce59..eaff3a9e73305 100644
--- a/clang/test/CodeGenHLSL/RootSignature.hlsl
+++ b/clang/test/CodeGenHLSL/RootSignature.hlsl
@@ -82,8 +82,8 @@ void RootDescriptorsEntry() {}
 // checking minLOD, maxLOD
 // CHECK-SAME: float -1.280000e+02, float 1.280000e+02,
 
-// checking register, space and visibility
-// CHECK-SAME: i32 42, i32 0, i32 0}
+// checking register, space, visibility and flag
+// CHECK-SAME: i32 42, i32 0, i32 0, i32 1}
 
 #define SampleStaticSampler \
   "StaticSampler(s42, " \
@@ -96,6 +96,7 @@ void RootDescriptorsEntry() {}
   " borderColor = STATIC_BORDER_COLOR_OPAQUE_WHITE, " \
   " minLOD = -128.f, maxLOD = 128.f, " \
   " space = 0, visibility = SHADER_VISIBILITY_ALL, " \
+  " flags = UINT_BORDER_COLOR" \
   ")"
 [shader("compute"), RootSignature(SampleStaticSampler)]
 [numthreads(1,1,1)]
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp 
b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index 9b9f5dd8a63bb..f7e9d2d32c3f4 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -263,7 +263,8 @@ TEST_F(ParseHLSLRootSignatureTest, 
ValidParseStaticSamplerTest) {
       filter = FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT,
       maxLOD = 9000, addressU = TEXTURE_ADDRESS_MIRROR,
       comparisonFunc = COMPARISON_NOT_EQUAL,
-      borderColor = STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT
+      borderColor = STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT,
+      flags = 0
     )
   )cc";
 
@@ -336,6 +337,37 @@ TEST_F(ParseHLSLRootSignatureTest, 
ValidParseStaticSamplerTest) {
   ASSERT_TRUE(Consumer->isSatisfied());
 }
 
+TEST_F(ParseHLSLRootSignatureTest, ValidStaticSamplerFlagsTest) {
+  const llvm::StringLiteral Source = R"cc(
+    StaticSampler(s0, flags = UINT_BORDER_COLOR | NON_NORMALIZED_COORDINATES)
+  )cc";
+
+  auto Ctx = createMinimalASTContext();
+  StringLiteral *Signature = wrapSource(Ctx, Source);
+
+  TrivialModuleLoader ModLoader;
+  auto PP = createPP(Source, ModLoader);
+
+  hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
+
+  // Test no diagnostics produced
+  Consumer->setNoDiag();
+
+  ASSERT_FALSE(Parser.parse());
+
+  auto Elements = Parser.getElements();
+  ASSERT_EQ(Elements.size(), 1u);
+
+  RootElement Elem = Elements[0].getElement();
+  ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem));
+  auto ValidStaticSamplerFlags =
+      llvm::dxbc::StaticSamplerFlags::NonNormalizedCoordinates |
+      llvm::dxbc::StaticSamplerFlags::UintBorderColor;
+  ASSERT_EQ(std::get<StaticSampler>(Elem).Flags, ValidStaticSamplerFlags);
+
+  ASSERT_TRUE(Consumer->isSatisfied());
+}
+
 TEST_F(ParseHLSLRootSignatureTest, ValidParseFloatsTest) {
   const llvm::StringLiteral Source = R"cc(
     StaticSampler(s0, mipLODBias = 0),
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp 
b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index f29f2c7602fc6..e2a1f242bfc8e 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -212,6 +212,7 @@ MDNode *MetadataBuilder::BuildStaticSampler(const 
StaticSampler &Sampler) {
       ConstantAsMetadata::get(Builder.getInt32(Sampler.Space)),
       ConstantAsMetadata::get(
           Builder.getInt32(to_underlying(Sampler.Visibility))),
+      ConstantAsMetadata::get(Builder.getInt32(to_underlying(Sampler.Flags))),
   };
   return MDNode::get(Ctx, Operands);
 }

>From 589668e1c87b45e4a551451c7ae0c745b8dad625 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saff...@microsoft.com>
Date: Wed, 24 Sep 2025 05:51:24 +0000
Subject: [PATCH 12/19] adding more test

---
 llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp 
b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
index 1eb03f16527ec..abdd8a6a21112 100644
--- a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
+++ b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
@@ -266,7 +266,8 @@ TEST(HLSLRootSignatureTest, DefaultStaticSamplerDump) {
                          "minLOD = 0.000000e+00, "
                          "maxLOD = 3.402823e+38, "
                          "space = 0, "
-                         "visibility = All"
+                         "visibility = All, "
+                         "flags = 0x0"
                          ")";
   EXPECT_EQ(Out, Expected);
 }
@@ -287,6 +288,7 @@ TEST(HLSLRootSignatureTest, DefinedStaticSamplerDump) {
   Sampler.MaxLOD = 32.0f;
   Sampler.Space = 7;
   Sampler.Visibility = llvm::dxbc::ShaderVisibility::Domain;
+  Sampler.Flags = llvm::dxbc::StaticSamplerFlags::NonNormalizedCoordinates;
 
   std::string Out;
   llvm::raw_string_ostream OS(Out);
@@ -305,7 +307,8 @@ TEST(HLSLRootSignatureTest, DefinedStaticSamplerDump) {
                          "minLOD = 1.000000e+00, "
                          "maxLOD = 3.200000e+01, "
                          "space = 7, "
-                         "visibility = Domain"
+                         "visibility = Domain, "
+                         "flags = 0x2"
                          ")";
   EXPECT_EQ(Out, Expected);
 }

>From e8b973fb9c0a3fccefc1299448c7c3bd322e52a2 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Thu, 25 Sep 2025 10:21:11 -0700
Subject: [PATCH 13/19] adding operator << to print StaticSamplerFlags

---
 llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp 
b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
index f9129adb4a4f9..5dbec8063dd77 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -113,6 +113,14 @@ static raw_ostream &operator<<(raw_ostream &OS,
   return OS;
 }
 
+static raw_ostream &operator<<(raw_ostream &OS,
+                               const llvm::dxbc::StaticSamplerFlags &Flags) {
+  printFlags(OS, Flags, dxbc::getStaticSamplerFlags());
+
+  return OS;
+}
+
+
 raw_ostream &operator<<(raw_ostream &OS, const dxbc::RootFlags &Flags) {
   OS << "RootFlags(";
   printFlags(OS, Flags, dxbc::getRootFlags());

>From 190cfcde07640fc9d6f06171dd4d8f8d5b664765 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Thu, 25 Sep 2025 10:21:35 -0700
Subject: [PATCH 14/19] updating comment with inbelic suggestion

---
 clang/lib/Parse/ParseHLSLRootSignature.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp 
b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 5677365688413..7be6eecc520b1 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -930,7 +930,7 @@ RootSignatureParser::parseStaticSamplerParams() {
         return std::nullopt;
       Params.Visibility = Visibility;
     } else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
-      // `flags` `=` UINT_BORDER_COLOR
+      // `flags` `=` STATIC_SAMPLE_FLAGS
       if (Params.Flags.has_value()) {
         reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
         return std::nullopt;

>From 79e9564613c700c9f1dbee8e7aa2b052ab6ff72d Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Thu, 25 Sep 2025 10:21:52 -0700
Subject: [PATCH 15/19] format

---
 llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp 
b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
index 5dbec8063dd77..2b33e560d74ac 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -120,7 +120,6 @@ static raw_ostream &operator<<(raw_ostream &OS,
   return OS;
 }
 
-
 raw_ostream &operator<<(raw_ostream &OS, const dxbc::RootFlags &Flags) {
   OS << "RootFlags(";
   printFlags(OS, Flags, dxbc::getRootFlags());

>From 1b1c37dfb518f7d5d2a5180b73100e2d1326c3a0 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Thu, 25 Sep 2025 12:32:34 -0700
Subject: [PATCH 16/19] fix test

---
 llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp 
b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
index abdd8a6a21112..451c376219c38 100644
--- a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
+++ b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
@@ -267,7 +267,7 @@ TEST(HLSLRootSignatureTest, DefaultStaticSamplerDump) {
                          "maxLOD = 3.402823e+38, "
                          "space = 0, "
                          "visibility = All, "
-                         "flags = 0x0"
+                         "flags = None"
                          ")";
   EXPECT_EQ(Out, Expected);
 }
@@ -308,7 +308,7 @@ TEST(HLSLRootSignatureTest, DefinedStaticSamplerDump) {
                          "maxLOD = 3.200000e+01, "
                          "space = 7, "
                          "visibility = Domain, "
-                         "flags = 0x2"
+                         "flags = NonNormalizedCoordinates"
                          ")";
   EXPECT_EQ(Out, Expected);
 }

>From daa5714d7506b8482a9c43247ccb9bbbf2820591 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Thu, 25 Sep 2025 12:33:20 -0700
Subject: [PATCH 17/19] update Root Signature Version flag

---
 clang/include/clang/Basic/LangOptions.h             |  2 +-
 clang/include/clang/Driver/Options.td               |  8 ++++----
 clang/lib/AST/TextNodeDumper.cpp                    |  3 +++
 clang/lib/Driver/ToolChains/HLSL.cpp                |  2 +-
 clang/test/AST/HLSL/RootSignature-Target-AST.hlsl   | 10 +++++++++-
 clang/test/AST/HLSL/RootSignatures-AST.hlsl         | 10 +++++++++-
 clang/test/AST/HLSL/rootsignature-define-ast.hlsl   |  6 +++---
 clang/test/CodeGenHLSL/RootSignature-Target.hlsl    |  2 +-
 clang/test/CodeGenHLSL/RootSignature.hlsl           | 12 ++++++------
 clang/test/Driver/dxc_rootsig-define.hlsl           |  2 +-
 llvm/include/llvm/BinaryFormat/DXContainer.h        |  1 +
 llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h |  4 ++--
 llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp |  2 +-
 llvm/lib/ObjectYAML/DXContainerYAML.cpp             |  2 +-
 14 files changed, 43 insertions(+), 23 deletions(-)

diff --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index a8943df5b39aa..280746fd4edeb 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -550,7 +550,7 @@ class LangOptions : public LangOptionsBase {
 
   /// The HLSL root signature version for dxil.
   llvm::dxbc::RootSignatureVersion HLSLRootSigVer =
-      llvm::dxbc::RootSignatureVersion::V1_1;
+      llvm::dxbc::RootSignatureVersion::V1_2;
 
   /// The HLSL root signature that will be used to overide the root signature
   /// used for the shader entry point.
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 16e1c396fedbe..c1b8928cf0528 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -9456,7 +9456,7 @@ def target_profile : DXCJoinedOrSeparate<"T">, 
MetaVarName<"<profile>">,
          "lib_6_3, lib_6_4, lib_6_5, lib_6_6, lib_6_7, lib_6_x,"
          "ms_6_5, ms_6_6, ms_6_7,"
          "as_6_5, as_6_6, as_6_7,"
-         "rootsig_1_0, rootsig_1_1">;
+         "rootsig_1_0, rootsig_1_1, rootsig_1_2">;
 def emit_pristine_llvm : DXCFlag<"emit-pristine-llvm">,
   HelpText<"Emit pristine LLVM IR from the frontend by not running any LLVM 
passes at all."
            "Same as -S + -emit-llvm + -disable-llvm-passes.">;
@@ -9469,10 +9469,10 @@ def fdx_rootsignature_version :
   Group<dxc_Group>,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Root Signature Version">,
-  Values<"rootsig_1_0,rootsig_1_1">,
+  Values<"rootsig_1_0,rootsig_1_1,rootsig_1_2">,
   NormalizedValuesScope<"llvm::dxbc::RootSignatureVersion">,
-  NormalizedValues<["V1_0", "V1_1"]>,
-  MarshallingInfoEnum<LangOpts<"HLSLRootSigVer">, "V1_1">;
+  NormalizedValues<["V1_0", "V1_1", "V1_2"]>,
+  MarshallingInfoEnum<LangOpts<"HLSLRootSigVer">, "V1_2">;
 def dxc_rootsig_ver :
   Separate<["/", "-"], "force-rootsig-ver">,
   Alias<fdx_rootsignature_version>,
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 8f7fe3bea4e8f..cf5e9147ad78b 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -3095,6 +3095,9 @@ void TextNodeDumper::VisitHLSLRootSignatureDecl(
   case llvm::dxbc::RootSignatureVersion::V1_1:
     OS << "1.1";
     break;
+  case llvm::dxbc::RootSignatureVersion::V1_2:
+    OS << "1.2";
+    break;
   }
   OS << ", ";
   llvm::hlsl::rootsig::dumpRootElements(OS, D->getRootElements());
diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp 
b/clang/lib/Driver/ToolChains/HLSL.cpp
index f4858e4c960de..2869549e6b3f0 100644
--- a/clang/lib/Driver/ToolChains/HLSL.cpp
+++ b/clang/lib/Driver/ToolChains/HLSL.cpp
@@ -64,7 +64,7 @@ bool isLegalShaderModel(Triple &T) {
   } break;
   case Triple::EnvironmentType::RootSignature:
     VersionTuple MinVer(1, 0);
-    VersionTuple MaxVer(1, 1);
+    VersionTuple MaxVer(1, 2);
     return MinVer <= Version && Version <= MaxVer;
   }
   return false;
diff --git a/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl 
b/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl
index 91441e32e047d..b5c71a86b7e48 100644
--- a/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl
+++ b/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl
@@ -1,10 +1,16 @@
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \
+// RUN:  -fdx-rootsignature-version=rootsig_1_1 \
 // RUN:  -hlsl-entry EntryRootSig -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK,CHECK-V1_1
 
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \
 // RUN:  -fdx-rootsignature-version=rootsig_1_0 \
 // RUN:  -hlsl-entry EntryRootSig -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK,CHECK-V1_0
 
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \
+// RUN:  -fdx-rootsignature-version=rootsig_1_2 \
+// RUN:  -hlsl-entry EntryRootSig -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK,CHECK-V1_2
+
+
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \
 // RUN:  -D CmdRS='"UAV(u0)"'\
 // RUN:  -hlsl-entry CmdRS -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefix=CMD
@@ -12,17 +18,19 @@
 // CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit 
[[ENTRY_RS_DECL:__hlsl_rootsig_decl_\d*]]
 // CHECK-V1_0-SAME: version: 1.0,
 // CHECK-V1_1-SAME: version: 1.1,
+// CHECK-V1_2-SAME: version: 1.2,
 // CHECK-SAME: RootElements{
 // CHECK-SAME: RootCBV(b0,
 // CHECK-SAME:   space = 0, visibility = All,
 // CHECK-V1_0-SAME: flags = DataVolatile
 // CHECK-V1_1-SAME: flags = DataStaticWhileSetAtExecute
+// CHECK-V1_2-SAME: flags = DataStaticWhileSetAtExecute
 // CHECK-SAME: )
 // CHECK-SAME: }
 #define EntryRootSig "CBV(b0)"
 
 // CMD: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit 
[[CMD_RS_DECL:__hlsl_rootsig_decl_\d*]]
-// CMD-SAME: version: 1.1,
+// CMD-SAME: version: 1.2,
 // CMD-SAME: RootElements{
 // CMD-SAME: RootUAV(u0, space = 0, visibility = All, flags = DataVolatile)
 // CMD-SAME: }
diff --git a/clang/test/AST/HLSL/RootSignatures-AST.hlsl 
b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
index 32da1f14853b0..f0c1a0d4ad58b 100644
--- a/clang/test/AST/HLSL/RootSignatures-AST.hlsl
+++ b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
@@ -1,11 +1,14 @@
 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \
-// RUN:  -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK,CHECK-V1_1
+// RUN:  -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK,CHECK-V1_2
 // 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-prefixes=CHECK,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-prefixes=CHECK,CHECK-V1_1
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \
+// RUN:  -fdx-rootsignature-version=rootsig_1_2 \
+// RUN:  -disable-llvm-passes -o - %s | FileCheck %s 
--check-prefixes=CHECK,CHECK-V1_2
 
 // 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
@@ -31,6 +34,7 @@
 // CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit 
[[SAMPLE_RS_DECL:__hlsl_rootsig_decl_\d*]]
 // CHECK-V1_0: version: 1.0,
 // CHECK-V1_1: version: 1.1,
+// CHECK-V1_2: version: 1.2,
 // CHECK-SAME: RootElements{
 // CHECK-SAME: RootFlags(AllowInputAssemblerInputLayout | 
DenyVertexShaderRootAccess),
 // CHECK-SAME: RootCBV(b0,
@@ -62,6 +66,7 @@
 // CHECK-SAME:   s0, numDescriptors = 4, space = 1, offset = 
DescriptorTableOffsetAppend,
 // CHECK-V1_0-SAME:  flags = DescriptorsVolatile
 // CHECK-V1_1-SAME:  flags = None
+// CHECK-V1_2-SAME:  flags = None
 // CHECK-SAME: ),
 // CHECK-SAME: DescriptorTable(
 // CHECK-SAME:   numClauses = 1, visibility = All
@@ -73,6 +78,9 @@
 // CHECK-SAME:   s1, filter = Anisotropic, addressU = Wrap, addressV = Wrap, 
addressW = Wrap,
 // CHECK-SAME:   mipLODBias = 0.000000e+00, maxAnisotropy = 16, comparisonFunc 
= LessEqual,
 // CHECK-SAME:   borderColor = OpaqueWhite, minLOD = 0.000000e+00, maxLOD = 
3.402823e+38, space = 0, visibility = All
+// CHECK-V1_0-SAME:  flags = None
+// CHECK-V1_1-SAME:  flags = None
+// CHECK-V1_2-SAME:  flags = None
 // CHECK-SAME: )}
 
 // CHECK: -RootSignatureAttr 0x{{.*}} {{.*}} [[SAMPLE_RS_DECL]]
diff --git a/clang/test/AST/HLSL/rootsignature-define-ast.hlsl 
b/clang/test/AST/HLSL/rootsignature-define-ast.hlsl
index 9c17cbc9ad2eb..508670175d1f5 100644
--- a/clang/test/AST/HLSL/rootsignature-define-ast.hlsl
+++ b/clang/test/AST/HLSL/rootsignature-define-ast.hlsl
@@ -21,13 +21,13 @@
 #define SampleUAV "UAV(u0)"
 
 // CMD: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit 
[[CMD_DECL:__hlsl_rootsig_decl_\d*]]
-// CMD-SAME: version: 1.1, RootElements{
+// CMD-SAME: version: 1.2, RootElements{
 // CMD-SAME: RootSRV(t0,
 // CMD-SAME:   space = 0, visibility = All, flags = DataStaticWhileSetAtExecute
 // CMD-SAME: )}
 
 // CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit 
[[CBV_DECL:__hlsl_rootsig_decl_\d*]]
-// CHECK-SAME: version: 1.1, RootElements{
+// CHECK-SAME: version: 1.2, RootElements{
 // CHECK-SAME: RootCBV(b0,
 // CHECK-SAME:   space = 0, visibility = All, flags = 
DataStaticWhileSetAtExecute
 // CHECK-SAME: )}
@@ -41,7 +41,7 @@
 void cbv_main() {}
 
 // CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit 
[[UAV_DECL:__hlsl_rootsig_decl_\d*]]
-// CHECK-SAME: version: 1.1, RootElements{
+// CHECK-SAME: version: 1.2, RootElements{
 // CHECK-SAME: RootUAV(u0,
 // CHECK-SAME:   space = 0, visibility = All, flags = DataVolatile
 // CHECK-SAME: )}
diff --git a/clang/test/CodeGenHLSL/RootSignature-Target.hlsl 
b/clang/test/CodeGenHLSL/RootSignature-Target.hlsl
index 50e6bae6786f0..b1b88081ded8c 100644
--- a/clang/test/CodeGenHLSL/RootSignature-Target.hlsl
+++ b/clang/test/CodeGenHLSL/RootSignature-Target.hlsl
@@ -2,7 +2,7 @@
 // RUN: -hlsl-entry EntryRS -emit-llvm -o - %s | FileCheck %s
 
 // CHECK: !dx.rootsignatures = !{![[#ENTRY:]]}
-// CHECK: ![[#ENTRY]] = !{null, ![[#ENTRY_RS:]], i32 2}
+// CHECK: ![[#ENTRY]] = !{null, ![[#ENTRY_RS:]], i32 3}
 // CHECK: ![[#ENTRY_RS]] = !{![[#ROOT_CBV:]]}
 // CHECK: ![[#ROOT_CBV]] = !{!"RootCBV", i32 0, i32 0, i32 0, i32 4}
 
diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl 
b/clang/test/CodeGenHLSL/RootSignature.hlsl
index eaff3a9e73305..da257ed9f5734 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:]], i32 2}
+// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]], i32 3}
 // CHECK: ![[#EMPTY]] = !{}
 
 [shader("compute"), RootSignature("")]
 [numthreads(1,1,1)]
 void EmptyEntry() {}
 
-// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]], i32 2}
+// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]], i32 3}
 // 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:]], i32 2}
+// CHECK: ![[#RF_ENTRY]] = !{ptr @RootFlagsEntry, ![[#RF_RS:]], i32 3}
 // 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:]], i32 2}
+// CHECK: ![[#RC_ENTRY]] = !{ptr @RootConstantsEntry, ![[#RC_RS:]], i32 3}
 // 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:]], i32 2}
+// CHECK: ![[#RD_ENTRY]] = !{ptr @RootDescriptorsEntry, ![[#RD_RS:]], i32 3}
 // 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:]], i32 2}
+// CHECK: ![[#SS_ENTRY]] = !{ptr @StaticSamplerEntry, ![[#SS_RS:]], i32 3}
 // CHECK: ![[#SS_RS]] = !{![[#STATIC_SAMPLER:]]}
 
 // checking filter = 0x4
diff --git a/clang/test/Driver/dxc_rootsig-define.hlsl 
b/clang/test/Driver/dxc_rootsig-define.hlsl
index 40c3e127f94d5..f9eb8c2e4c1ea 100644
--- a/clang/test/Driver/dxc_rootsig-define.hlsl
+++ b/clang/test/Driver/dxc_rootsig-define.hlsl
@@ -18,7 +18,7 @@
 #define NotEmptyRS "CBV(b0)"
 
 // CHECK: !dx.rootsignatures = !{![[#ENTRY:]]}
-// CHECK: ![[#ENTRY]] = !{ptr @main, ![[#RS:]], i32 2}
+// CHECK: ![[#ENTRY]] = !{ptr @main, ![[#RS:]], i32 3}
 
 // REG: ![[#RS]] = !{![[#CBV:]]}
 // REG: ![[#CBV]] = !{!"RootCBV"
diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h 
b/llvm/include/llvm/BinaryFormat/DXContainer.h
index a08cfff4b4974..8b0f8fab24c66 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainer.h
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -843,6 +843,7 @@ struct StaticSampler : public v1::StaticSampler {
 enum class RootSignatureVersion {
   V1_0 = 0x1,
   V1_1 = 0x2,
+  V1_2 = 0x3,
 };
 
 } // namespace dxbc
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h 
b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index 37224d8a94527..c5d89106a8537 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -56,7 +56,7 @@ struct RootDescriptor {
       return;
     }
 
-    assert(Version == llvm::dxbc::RootSignatureVersion::V1_1 &&
+    assert((Version == llvm::dxbc::RootSignatureVersion::V1_1 || Version == 
llvm::dxbc::RootSignatureVersion::V1_2) &&
            "Specified an invalid root signature version");
     switch (Type) {
     case dxil::ResourceClass::CBuffer:
@@ -100,7 +100,7 @@ struct DescriptorTableClause {
       return;
     }
 
-    assert(Version == dxbc::RootSignatureVersion::V1_1 &&
+    assert((Version == dxbc::RootSignatureVersion::V1_1 || Version == 
dxbc::RootSignatureVersion::V1_2)  &&
            "Specified an invalid root signature version");
     switch (Type) {
     case dxil::ResourceClass::CBuffer:
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp 
b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
index 8c298f0685286..0ce2aaf51bfd6 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
@@ -40,7 +40,7 @@ bool verifyRootDescriptorFlag(uint32_t Version, uint32_t 
FlagsVal) {
   if (Version == 1)
     return Flags == FlagT::DataVolatile;
 
-  assert(Version == 2 && "Provided invalid root signature version");
+  assert((Version == 2 || Version == 3) && "Provided invalid root signature 
version");
 
   // The data-specific flags are mutually exclusive.
   FlagT DataFlags = FlagT::DataVolatile | FlagT::DataStatic |
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp 
b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index bfb3837707f0a..f268aa85a705e 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -154,7 +154,7 @@ DXContainerYAML::RootSignatureYamlDesc::create(
         if (Error E = readDescriptorRanges<dxbc::RTS0::v1::DescriptorRange>(
                 Header, RootSigDesc, DTV))
           return std::move(E);
-      } else if (Version == 2) {
+      } else if (Version == 2 || Version == 3) {
         if (Error E = readDescriptorRanges<dxbc::RTS0::v2::DescriptorRange>(
                 Header, RootSigDesc, DTV))
           return std::move(E);

>From 11770c5cefcddddb984e88029d06d9729e6ea7ff Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Thu, 25 Sep 2025 13:23:39 -0700
Subject: [PATCH 18/19] fix objcopy test

---
 clang/test/Driver/dxc_frs.hlsl                  | 2 +-
 clang/test/Driver/dxc_rootsignature_target.hlsl | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/Driver/dxc_frs.hlsl b/clang/test/Driver/dxc_frs.hlsl
index 767cab604c829..9fa568901db81 100644
--- a/clang/test/Driver/dxc_frs.hlsl
+++ b/clang/test/Driver/dxc_frs.hlsl
@@ -3,7 +3,7 @@
 // Test to demonstrate extracting the root signature to the specified
 // output file with /Frs.
 
-// CHECK: "{{.*}}llvm-objcopy{{(.exe)?}}" "{{.*}}.obj" "{{.*}}.dxo" 
"--extract-section=RTS0={{.*}}.rs.dxo"
+// CHECK: "{{.*}}/llvm-objcopy{{(.exe)?}}" "{{.*}}.obj" "{{.*}}.{{(dxo|obj)}}" 
"--extract-section=RTS0={{.*}}.rs.dxo"
 
 [shader("compute"), RootSignature("")]
 [numthreads(1,1,1)]
diff --git a/clang/test/Driver/dxc_rootsignature_target.hlsl 
b/clang/test/Driver/dxc_rootsignature_target.hlsl
index 08cd1ab00089b..784523707746d 100644
--- a/clang/test/Driver/dxc_rootsignature_target.hlsl
+++ b/clang/test/Driver/dxc_rootsignature_target.hlsl
@@ -3,6 +3,6 @@
 // CMDS: "{{.*}}clang{{.*}}" "-cc1"
 // CMDS-SAME: "-triple" "dxilv1.1-unknown-shadermodel1.1-rootsignature"
 // CMDS-SAME: "-hlsl-entry" "EntryRS"
-// CMDS: "{{.*}}llvm-objcopy{{(.exe)?}}" "{{.*}}.dxo" "--only-section=RTS0"
+// CMDS: "{{.*}}llvm-objcopy{{(.exe)?}}" "{{.*}}.{{(dxo|obj)}}" 
"--only-section=RTS0"
 
 #define EntryRS "UAV(u0)"

>From c3746341bdf20e1c0bc803c9801291a7f0573ba3 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranl...@gmail.com>
Date: Fri, 26 Sep 2025 11:10:02 -0700
Subject: [PATCH 19/19] foramt

---
 llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h | 6 ++++--
 llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h 
b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index c5d89106a8537..edee6a7dec6fc 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -56,7 +56,8 @@ struct RootDescriptor {
       return;
     }
 
-    assert((Version == llvm::dxbc::RootSignatureVersion::V1_1 || Version == 
llvm::dxbc::RootSignatureVersion::V1_2) &&
+    assert((Version == llvm::dxbc::RootSignatureVersion::V1_1 ||
+            Version == llvm::dxbc::RootSignatureVersion::V1_2) &&
            "Specified an invalid root signature version");
     switch (Type) {
     case dxil::ResourceClass::CBuffer:
@@ -100,7 +101,8 @@ struct DescriptorTableClause {
       return;
     }
 
-    assert((Version == dxbc::RootSignatureVersion::V1_1 || Version == 
dxbc::RootSignatureVersion::V1_2)  &&
+    assert((Version == dxbc::RootSignatureVersion::V1_1 ||
+            Version == dxbc::RootSignatureVersion::V1_2) &&
            "Specified an invalid root signature version");
     switch (Type) {
     case dxil::ResourceClass::CBuffer:
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp 
b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
index 653305165cad5..8a2b03d9ede8b 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
@@ -40,7 +40,7 @@ bool verifyRootDescriptorFlag(uint32_t Version, uint32_t 
FlagsVal) {
   if (Version == 1)
     return Flags == FlagT::DataVolatile;
 
-  assert((Version == 2 || Version == 3) && "Provided invalid root signature 
version");
+  assert((Version <= 3) && "Provided invalid root signature version");
 
   // The data-specific flags are mutually exclusive.
   FlagT DataFlags = FlagT::DataVolatile | FlagT::DataStatic |

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to