Repository: llvm/llvm-project
Pull request #138315: [DirectX] adding support to read/write descriptor table data using obj2yaml/yaml2obj
Author: login: joaosaffran
Labels: name: llvm:mc
description: Machine (object) code
name: backend:DirectX
name: objectyaml
name: llvm:binary-utilities
Created: 2025-05-02T18:00:38Z | Merged: 2025-05-29T19:21:20Z

Closes: https://github.com/orgs/llvm/projects/4/views/22?sliceBy%5Bvalue%5D=joaosaffran&pane=issue&itemId=97332852&issue=llvm%7Cllvm-project%7C126635


Diff:
diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h
index 3494e0fe1a0e9..9bb182b6510d0 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainer.h
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -163,6 +163,11 @@ enum class RootDescriptorFlag : uint32_t {
 #include "DXContainerConstants.def"
 };
 
+#define DESCRIPTOR_RANGE_FLAG(Num, Val) Val = 1ull << Num,
+enum class DescriptorRangeFlag : uint32_t {
+#include "DXContainerConstants.def"
+};
+
 #define ROOT_PARAMETER(Val, Enum) Enum = Val,
 enum class RootParameterType : uint32_t {
 #include "DXContainerConstants.def"
@@ -170,6 +175,13 @@ enum class RootParameterType : uint32_t {
 
 ArrayRef<EnumEntry<RootParameterType>> getRootParameterTypes();
 
+#define DESCRIPTOR_RANGE(Val, Enum) Enum = Val,
+enum class DescriptorRangeType : uint32_t {
+#include "DXContainerConstants.def"
+};
+
+ArrayRef<EnumEntry<DescriptorRangeType>> getDescriptorRangeTypes();
+
 #define ROOT_PARAMETER(Val, Enum)                                              \
   case Val:                                                                    \
     return true;
@@ -588,6 +600,21 @@ static_assert(sizeof(ProgramSignatureElement) == 32,
 
 namespace RTS0 {
 namespace v1 {
+struct DescriptorRange {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  uint32_t OffsetInDescriptorsFromTableStart;
+  void swapBytes() {
+    sys::swapByteOrder(RangeType);
+    sys::swapByteOrder(NumDescriptors);
+    sys::swapByteOrder(BaseShaderRegister);
+    sys::swapByteOrder(RegisterSpace);
+    sys::swapByteOrder(OffsetInDescriptorsFromTableStart);
+  }
+};
+
 struct RootDescriptor {
   uint32_t ShaderRegister;
   uint32_t RegisterSpace;
@@ -655,6 +682,14 @@ struct RootDescriptor : public v1::RootDescriptor {
     sys::swapByteOrder(Flags);
   }
 };
+
+struct DescriptorRange : public v1::DescriptorRange {
+  uint32_t Flags;
+  void swapBytes() {
+    v1::DescriptorRange::swapBytes();
+    sys::swapByteOrder(Flags);
+  }
+};
 } // namespace v2
 } // namespace RTS0
 
diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
index 81d2c54b6e07c..a407dd0e8d2c2 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
+++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
@@ -86,8 +86,21 @@ ROOT_DESCRIPTOR_FLAG(3, DATA_STATIC)
 #endif // ROOT_DESCRIPTOR_FLAG
 
 
+// DESCRIPTOR_RANGE_FLAG(bit offset for the flag, name).
+#ifdef DESCRIPTOR_RANGE_FLAG
+
+DESCRIPTOR_RANGE_FLAG(0, NONE)
+DESCRIPTOR_RANGE_FLAG(1, DESCRIPTORS_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(2, DATA_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(3, DATA_STATIC_WHILE_SET_AT_EXECUTE)
+DESCRIPTOR_RANGE_FLAG(4, DATA_STATIC)
+DESCRIPTOR_RANGE_FLAG(16, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS)
+#undef DESCRIPTOR_RANGE_FLAG
+#endif // DESCRIPTOR_RANGE_FLAG
+
 #ifdef ROOT_PARAMETER
 
+ROOT_PARAMETER(0, DescriptorTable)
 ROOT_PARAMETER(1, Constants32Bit)
 ROOT_PARAMETER(2, CBV)
 ROOT_PARAMETER(3, SRV)
diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h
index 5f5919122b3c5..63d7b508d87dd 100644
--- a/llvm/include/llvm/MC/DXContainerRootSignature.h
+++ b/llvm/include/llvm/MC/DXContainerRootSignature.h
@@ -25,11 +25,22 @@ struct RootParameterInfo {
       : Header(Header), Location(Location) {}
 };
 
+struct DescriptorTable {
+  SmallVector<dxbc::RTS0::v2::DescriptorRange> Ranges;
+  SmallVector<dxbc::RTS0::v2::DescriptorRange>::const_iterator begin() const {
+    return Ranges.begin();
+  }
+  SmallVector<dxbc::RTS0::v2::DescriptorRange>::const_iterator end() const {
+    return Ranges.end();
+  }
+};
+
 struct RootParametersContainer {
   SmallVector<RootParameterInfo> ParametersInfo;
 
   SmallVector<dxbc::RTS0::v1::RootConstants> Constants;
   SmallVector<dxbc::RTS0::v2::RootDescriptor> Descriptors;
+  SmallVector<DescriptorTable> Tables;
 
   void addInfo(dxbc::RTS0::v1::RootParameterHeader Header, size_t Location) {
     ParametersInfo.push_back(RootParameterInfo(Header, Location));
@@ -51,6 +62,12 @@ struct RootParametersContainer {
     Descriptors.push_back(Descriptor);
   }
 
+  void addParameter(dxbc::RTS0::v1::RootParameterHeader Header,
+                    DescriptorTable Table) {
+    addInfo(Header, Tables.size());
+    Tables.push_back(Table);
+  }
+
   const std::pair<uint32_t, uint32_t>
   getTypeAndLocForParameter(uint32_t Location) const {
     const RootParameterInfo &Info = ParametersInfo[Location];
@@ -70,6 +87,10 @@ struct RootParametersContainer {
     return Descriptors[Index];
   }
 
+  const DescriptorTable &getDescriptorTable(size_t Index) const {
+    return Tables[Index];
+  }
+
   size_t size() const { return ParametersInfo.size(); }
 
   SmallVector<RootParameterInfo>::const_iterator begin() const {
diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h
index 37cd5ca7dc935..ef981a156e87d 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -20,6 +20,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Object/Error.h"
+#include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/TargetParser/Triple.h"
@@ -177,6 +178,50 @@ struct RootDescriptorView : RootParameterView {
   }
 };
 
+struct DescriptorTable {
+  uint32_t NumRanges;
+  uint32_t RangesOffset;
+  ViewArray<dxbc::RTS0::v2::DescriptorRange> Ranges;
+
+  typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator begin() const {
+    return Ranges.begin();
+  }
+
+  typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator end() const {
+    return Ranges.end();
+  }
+};
+
+struct DescriptorTableView : RootParameterView {
+  static bool classof(const RootParameterView *V) {
+    return (V->Header.ParameterType ==
+            llvm::to_underlying(dxbc::RootParameterType::DescriptorTable));
+  }
+
+  // Define a type alias to access the template parameter from inside classof
+  llvm::Expected<DescriptorTable> read(uint32_t Version) {
+    const char *Current = ParamData.begin();
+    DescriptorTable Table;
+
+    Table.NumRanges =
+        support::endian::read<uint32_t, llvm::endianness::little>(Current);
+    Current += sizeof(uint32_t);
+
+    Table.RangesOffset =
+        support::endian::read<uint32_t, llvm::endianness::little>(Current);
+    Current += sizeof(uint32_t);
+
+    size_t RangeSize = sizeof(dxbc::RTS0::v1::DescriptorRange);
+    if (Version > 1)
+      RangeSize = sizeof(dxbc::RTS0::v2::DescriptorRange);
+
+    Table.Ranges.Stride = RangeSize;
+    Table.Ranges.Data =
+        ParamData.substr(2 * sizeof(uint32_t), Table.NumRanges * RangeSize);
+    return Table;
+  }
+};
+
 static Error parseFailed(const Twine &Msg) {
   return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);
 }
@@ -213,6 +258,9 @@ class RootSignature {
   llvm::Expected<RootParameterView>
   getParameter(const dxbc::RTS0::v1::RootParameterHeader &Header) const {
     size_t DataSize;
+    size_t EndOfSectionByte = getNumStaticSamplers() == 0
+                                  ? PartData.size()
+                                  : getStaticSamplersOffset();
 
     if (!dxbc::isValidParameterType(Header.ParameterType))
       return parseFailed("invalid parameter type");
@@ -229,11 +277,23 @@ class RootSignature {
       else
         DataSize = sizeof(dxbc::RTS0::v2::RootDescriptor);
       break;
-    }
-    size_t EndOfSectionByte = getNumStaticSamplers() == 0
-                                  ? PartData.size()
-                                  : getStaticSamplersOffset();
+    case dxbc::RootParameterType::DescriptorTable:
+      if (Header.ParameterOffset + sizeof(uint32_t) > EndOfSectionByte)
+        return parseFailed("Reading structure out of file bounds");
 
+      uint32_t NumRanges =
+          support::endian::read<uint32_t, llvm::endianness::little>(
+              PartData.begin() + Header.ParameterOffset);
+      if (Version == 1)
+        DataSize = sizeof(dxbc::RTS0::v1::DescriptorRange) * NumRanges;
+      else
+        DataSize = sizeof(dxbc::RTS0::v2::DescriptorRange) * NumRanges;
+
+      // 4 bytes for the number of ranges in table and
+      // 4 bytes for the ranges offset
+      DataSize += 2 * sizeof(uint32_t);
+      break;
+    }
     if (Header.ParameterOffset + DataSize > EndOfSectionByte)
       return parseFailed("Reading structure out of file bounds");
 
diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index 3af1da552cc7a..33327e5a2de39 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -90,6 +90,25 @@ struct RootDescriptorYaml {
 #include "llvm/BinaryFormat/DXContainerConstants.def"
 };
 
+struct DescriptorRangeYaml {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  uint32_t OffsetInDescriptorsFromTableStart;
+
+  uint32_t getEncodedFlags() const;
+
+#define DESCRIPTOR_RANGE_FLAG(Num, Val) bool Val = false;
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+};
+
+struct DescriptorTableYaml {
+  uint32_t NumRanges;
+  uint32_t RangesOffset;
+  SmallVector<DescriptorRangeYaml> Ranges;
+};
+
 struct RootParameterHeaderYaml {
   uint32_t Type;
   uint32_t Visibility;
@@ -113,6 +132,7 @@ struct RootParameterYamlDesc {
 
   SmallVector<RootConstantsYaml> Constants;
   SmallVector<RootDescriptorYaml> Descriptors;
+  SmallVector<DescriptorTableYaml> Tables;
 
   template <typename T>
   T &getOrInsertImpl(RootParameterLocationYaml &ParamDesc,
@@ -134,6 +154,10 @@ struct RootParameterYamlDesc {
     return getOrInsertImpl(ParamDesc, Descriptors);
   }
 
+  DescriptorTableYaml &getOrInsertTable(RootParameterLocationYaml &ParamDesc) {
+    return getOrInsertImpl(ParamDesc, Tables);
+  }
+
   void insertLocation(RootParameterLocationYaml &Location) {
     Locations.push_back(Location);
   }
@@ -263,6 +287,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureElement)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::PSVInfo::MaskVector)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureParameter)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::RootParameterLocationYaml)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::DescriptorRangeYaml)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::SemanticKind)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::ComponentType)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::InterpolationMode)
@@ -351,6 +376,14 @@ template <> struct MappingTraits<llvm::DXContainerYAML::RootDescriptorYaml> {
   static void mapping(IO &IO, llvm::DXContainerYAML::RootDescriptorYaml &D);
 };
 
+template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorTableYaml> {
+  static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorTableYaml &D);
+};
+
+template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorRangeYaml> {
+  static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorRangeYaml &D);
+};
+
 } // namespace yaml
 
 } // namespace llvm
diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp
index 3a4bd8321eb95..01531b4d4dbc9 100644
--- a/llvm/lib/MC/DXContainerRootSignature.cpp
+++ b/llvm/lib/MC/DXContainerRootSignature.cpp
@@ -47,6 +47,18 @@ size_t RootSignatureDesc::getSize() const {
         Size += sizeof(dxbc::RTS0::v2::RootDescriptor);
 
       break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      const DescriptorTable &Table =
+          ParametersContainer.getDescriptorTable(I.Location);
+
+      // 4 bytes for the number of ranges in table and
+      // 4 bytes for the ranges offset
+      Size += 2 * sizeof(uint32_t);
+      if (Version == 1)
+        Size += sizeof(dxbc::RTS0::v1::DescriptorRange) * Table.Ranges.size();
+      else
+        Size += sizeof(dxbc::RTS0::v2::DescriptorRange) * Table.Ranges.size();
+      break;
     }
   }
   return Size;
@@ -106,6 +118,27 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
         support::endian::write(BOS, Descriptor.Flags, llvm::endianness::little);
       break;
     }
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
+      const DescriptorTable &Table =
+          ParametersContainer.getDescriptorTable(Loc);
+      support::endian::write(BOS, (uint32_t)Table.Ranges.size(),
+                             llvm::endianness::little);
+      rewriteOffsetToCurrentByte(BOS, writePlaceholder(BOS));
+      for (const auto &Range : Table) {
+        support::endian::write(BOS, Range.RangeType, llvm::endianness::little);
+        support::endian::write(BOS, Range.NumDescriptors,
+                               llvm::endianness::little);
+        support::endian::write(BOS, Range.BaseShaderRegister,
+                               llvm::endianness::little);
+        support::endian::write(BOS, Range.RegisterSpace,
+                               llvm::endianness::little);
+        support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart,
+                               llvm::endianness::little);
+        if (Version > 1)
+          support::endian::write(BOS, Range.Flags, llvm::endianness::little);
+      }
+      break;
+    }
     }
   }
   assert(Storage.size() == getSize());
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index d5fdf0bda68c3..233a79ea20fe9 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -303,6 +303,26 @@ void DXContainerWriter::writeParts(raw_ostream &OS) {
           RS.ParametersContainer.addParameter(Header, Descriptor);
           break;
         }
+        case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
+          const DXContainerYAML::DescriptorTableYaml &TableYaml =
+              P.RootSignature->Parameters.getOrInsertTable(L);
+          mcdxbc::DescriptorTable Table;
+          for (const auto &R : TableYaml.Ranges) {
+
+            dxbc::RTS0::v2::DescriptorRange Range;
+            Range.RangeType = R.RangeType;
+            Range.NumDescriptors = R.NumDescriptors;
+            Range.BaseShaderRegister = R.BaseShaderRegister;
+            Range.RegisterSpace = R.RegisterSpace;
+            Range.OffsetInDescriptorsFromTableStart =
+                R.OffsetInDescriptorsFromTableStart;
+            if (RS.Version > 1)
+              Range.Flags = R.getEncodedFlags();
+            Table.Ranges.push_back(Range);
+          }
+          RS.ParametersContainer.addParameter(Header, Table);
+          break;
+        }
         default:
           // Handling invalid parameter type edge case. We intentionally let
           // obj2yaml/yaml2obj parse and emit invalid dxcontainer data, in order
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 22561ec0ac9b9..9af4a93b30644 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -105,6 +105,38 @@ DXContainerYAML::RootSignatureYamlDesc::create(
        llvm::to_underlying(dxbc::RootDescriptorFlag::Val)) > 0;
 #include "llvm/BinaryFormat/DXContainerConstants.def"
       }
+    } else if (auto *DTV =
+                   dyn_cast<object::DirectX::DescriptorTableView>(&ParamView)) {
+      llvm::Expected<object::DirectX::DescriptorTable> TableOrErr =
+          DTV->read(Version);
+      if (Error E = TableOrErr.takeError())
+        return std::move(E);
+      auto Table = *TableOrErr;
+      RootParameterLocationYaml Location(Header);
+      DescriptorTableYaml &TableYaml =
+          RootSigDesc.Parameters.getOrInsertTable(Location);
+      RootSigDesc.Parameters.insertLocation(Location);
+
+      TableYaml.NumRanges = Table.NumRanges;
+      TableYaml.RangesOffset = Table.RangesOffset;
+
+      for (const auto &R : Table) {
+        DescriptorRangeYaml NewR;
+
+        NewR.OffsetInDescriptorsFromTableStart =
+            R.OffsetInDescriptorsFromTableStart;
+        NewR.NumDescriptors = R.NumDescriptors;
+        NewR.BaseShaderRegister = R.BaseShaderRegister;
+        NewR.RegisterSpace = R.RegisterSpace;
+        NewR.RangeType = R.RangeType;
+        if (Version > 1) {
+#define DESCRIPTOR_RANGE_FLAG(Num, Val)                                        \
+  NewR.Val =                                                                   \
+      (R.Flags & llvm::to_underlying(dxbc::DescriptorRangeFlag::Val)) > 0;
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+        }
+        TableYaml.Ranges.push_back(NewR);
+      }
     }
   }
 #define ROOT_ELEMENT_FLAG(Num, Val)                                            \
@@ -132,6 +164,15 @@ uint32_t DXContainerYAML::RootSignatureYamlDesc::getEncodedFlags() {
   return Flag;
 }
 
+uint32_t DXContainerYAML::DescriptorRangeYaml::getEncodedFlags() const {
+  uint64_t Flag = 0;
+#define DESCRIPTOR_RANGE_FLAG(Num, Val)                                        \
+  if (Val)                                                                     \
+    Flag |= (uint32_t)dxbc::DescriptorRangeFlag::Val;
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+  return Flag;
+}
+
 uint64_t DXContainerYAML::ShaderFeatureFlags::getEncodedFlags() {
   uint64_t Flag = 0;
 #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str)                      \
@@ -303,6 +344,37 @@ void MappingTraits<DXContainerYAML::RootSignatureYamlDesc>::mapping(
 #include "llvm/BinaryFormat/DXContainerConstants.def"
 }
 
+void MappingTraits<llvm::DXContainerYAML::DescriptorRangeYaml>::mapping(
+    IO &IO, llvm::DXContainerYAML::DescriptorRangeYaml &R) {
+  IO.mapRequired("RangeType", R.RangeType);
+  // handling the edge case where NumDescriptors might be -1
+  if (IO.outputting()) {
+    if (R.NumDescriptors == UINT_MAX) {
+      int32_t NegOne = -1;
+      IO.mapRequired("NumDescriptors", NegOne);
+    } else
+      IO.mapRequired("NumDescriptors", R.NumDescriptors);
+  } else {
+    int32_t TmpNumDesc = 0;
+    IO.mapRequired("NumDescriptors", TmpNumDesc);
+    R.NumDescriptors = static_cast<uint32_t>(TmpNumDesc);
+  }
+
+  IO.mapRequired("BaseShaderRegister", R.BaseShaderRegister);
+  IO.mapRequired("RegisterSpace", R.RegisterSpace);
+  IO.mapRequired("OffsetInDescriptorsFromTableStart",
+                 R.OffsetInDescriptorsFromTableStart);
+#define DESCRIPTOR_RANGE_FLAG(Num, Val) IO.mapOptional(#Val, R.Val, false);
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+}
+
+void MappingTraits<llvm::DXContainerYAML::DescriptorTableYaml>::mapping(
+    IO &IO, llvm::DXContainerYAML::DescriptorTableYaml &T) {
+  IO.mapRequired("NumRanges", T.NumRanges);
+  IO.mapOptional("RangesOffset", T.RangesOffset);
+  IO.mapRequired("Ranges", T.Ranges);
+}
+
 void MappingContextTraits<DXContainerYAML::RootParameterLocationYaml,
                           DXContainerYAML::RootSignatureYamlDesc>::
     mapping(IO &IO, DXContainerYAML::RootParameterLocationYaml &L,
@@ -325,6 +397,12 @@ void MappingContextTraits<DXContainerYAML::RootParameterLocationYaml,
     IO.mapRequired("Descriptor", Descriptor);
     break;
   }
+  case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
+    DXContainerYAML::DescriptorTableYaml &Table =
+        S.Parameters.getOrInsertTable(L);
+    IO.mapRequired("Table", Table);
+    break;
+  }
   }
 }
 
diff --git a/llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.0.yaml b/llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.0.yaml
new file mode 100644
index 0000000000000..0441bb7a256b1
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.0.yaml
@@ -0,0 +1,57 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+
+--- !dxcontainer
+Header:
+      Hash:            [ 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35, 0x6F, 0x5, 
+                        0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1 ]
+      Version:
+        Major:           1
+        Minor:           0
+      FileSize:        133
+      PartCount:       1
+      PartOffsets:     [ 36 ]
+Parts:
+- Name:            RTS0
+  Size:            89
+  RootSignature:
+    Version: 1
+    NumRootParameters: 1
+    RootParametersOffset: 24
+    NumStaticSamplers: 0
+    StaticSamplersOffset: 60
+    Parameters:         
+    - ParameterType: 0 # SRV
+      ShaderVisibility: 3 # Domain
+      Table:
+        NumRanges: 1
+        Ranges:
+          - RangeType: 0
+            NumDescriptors: -1
+            BaseShaderRegister: 42
+            RegisterSpace: 43
+            OffsetInDescriptorsFromTableStart: 41
+    AllowInputAssemblerInputLayout: true
+    DenyGeometryShaderRootAccess: true
+
+# CHECK: - Name:            RTS0
+# CHECK-NEXT:   Size:            89
+# CHECK-NEXT:   RootSignature:
+# CHECK-NEXT:     Version: 1
+# CHECK-NEXT:     NumRootParameters: 1
+# CHECK-NEXT:     RootParametersOffset: 24
+# CHECK-NEXT:     NumStaticSamplers: 0
+# CHECK-NEXT:     StaticSamplersOffset: 60
+# CHECK-NEXT:     Parameters:         
+# CHECK-NEXT:     - ParameterType: 0
+# CHECK-NEXT:       ShaderVisibility: 3
+# CHECK-NEXT:       Table:
+# CHECK-NEXT:         NumRanges: 1
+# CHECK-NEXT:         RangesOffset: 44
+# CHECK-NEXT:         Ranges:
+# CHECK-NEXT:           - RangeType: 0
+# CHECK-NEXT:             NumDescriptors: -1
+# CHECK-NEXT:             BaseShaderRegister: 42
+# CHECK-NEXT:             RegisterSpace: 43
+# CHECK-NEXT:             OffsetInDescriptorsFromTableStart: 41
+# CHECK-NEXT:     AllowInputAssemblerInputLayout: true
+# CHECK-NEXT:     DenyGeometryShaderRootAccess: true
diff --git a/llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.1.yaml b/llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.1.yaml
new file mode 100644
index 0000000000000..d06be5e181418
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.1.yaml
@@ -0,0 +1,59 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+
+--- !dxcontainer
+Header:
+      Hash:            [ 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35, 0x6F, 0x5, 
+                        0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1 ]
+      Version:
+        Major:           1
+        Minor:           0
+      FileSize:        133
+      PartCount:       1
+      PartOffsets:     [ 36 ]
+Parts:
+- Name:            RTS0
+  Size:            89
+  RootSignature:
+    Version: 2
+    NumRootParameters: 1
+    RootParametersOffset: 24
+    NumStaticSamplers: 0
+    StaticSamplersOffset: 60
+    Parameters:         
+    - ParameterType: 0 # SRV
+      ShaderVisibility: 3 # Domain
+      Table:
+        NumRanges: 1
+        Ranges:
+          - RangeType: 0
+            NumDescriptors: -1
+            BaseShaderRegister: 42
+            RegisterSpace: 43
+            OffsetInDescriptorsFromTableStart: 41
+            DATA_STATIC_WHILE_SET_AT_EXECUTE: true
+    AllowInputAssemblerInputLayout: true
+    DenyGeometryShaderRootAccess: true
+
+# CHECK: - Name:            RTS0
+# CHECK-NEXT:     Size:            89
+# CHECK-NEXT:     RootSignature:
+# CHECK-NEXT:       Version:         2
+# CHECK-NEXT:       NumRootParameters: 1
+# CHECK-NEXT:       RootParametersOffset: 24
+# CHECK-NEXT:       NumStaticSamplers: 0
+# CHECK-NEXT:       StaticSamplersOffset: 60
+# CHECK-NEXT:       Parameters:
+# CHECK-NEXT:         - ParameterType:   0
+# CHECK-NEXT:           ShaderVisibility: 3
+# CHECK-NEXT:           Table:
+# CHECK-NEXT:             NumRanges:       1
+# CHECK-NEXT:             RangesOffset:    44
+# CHECK-NEXT:             Ranges:
+# CHECK-NEXT:               - RangeType:       0
+# CHECK-NEXT:                 NumDescriptors:  -1
+# CHECK-NEXT:                 BaseShaderRegister: 42
+# CHECK-NEXT:                 RegisterSpace:   43
+# CHECK-NEXT:                 OffsetInDescriptorsFromTableStart: 41
+# CHECK-NEXT:                 DATA_STATIC_WHILE_SET_AT_EXECUTE: true
+# CHECK-NEXT:       AllowInputAssemblerInputLayout: true
+# CHECK-NEXT:       DenyGeometryShaderRootAccess: true
diff --git a/llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml b/llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml
index debb459c3944e..947fc096a9207 100644
--- a/llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml
@@ -11,7 +11,7 @@ Header:
   PartOffsets:     [ 60 ]
 Parts:
   - Name:            RTS0
-    Size:            96
+    Size:            200
     RootSignature:
       Version: 2
       NumRootParameters: 3
@@ -37,14 +37,25 @@ Parts:
           ShaderRegister: 31
           RegisterSpace: 32
           DATA_STATIC_WHILE_SET_AT_EXECUTE: true
+      - ParameterType: 0 # SRV
+        ShaderVisibility: 3 # Domain
+        Table:
+          NumRanges: 1
+          Ranges:
+            - RangeType: 0
+              NumDescriptors: -1
+              BaseShaderRegister: 42
+              RegisterSpace: 43
+              OffsetInDescriptorsFromTableStart: 41
+              DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true
       AllowInputAssemblerInputLayout: true
       DenyGeometryShaderRootAccess: true
 
 # CHECK:  - Name:            RTS0
-# CHECK-NEXT:    Size:            96
+# CHECK-NEXT:    Size:            200
 # CHECK-NEXT:    RootSignature:
 # CHECK-NEXT:      Version:         2
-# CHECK-NEXT:      NumRootParameters: 3
+# CHECK-NEXT:      NumRootParameters: 4
 # CHECK-NEXT:      RootParametersOffset: 24
 # CHECK-NEXT:      NumStaticSamplers: 0
 # CHECK-NEXT:      StaticSamplersOffset: 60
@@ -67,5 +78,17 @@ Parts:
 # CHECK-NEXT:            RegisterSpace:   32
 # CHECK-NEXT:            ShaderRegister:  31
 # CHECK-NEXT:            DATA_STATIC_WHILE_SET_AT_EXECUTE: true
+# CHECK-NEXT:        - ParameterType:   0
+# CHECK-NEXT:          ShaderVisibility: 3
+# CHECK-NEXT:          Table:
+# CHECK-NEXT:            NumRanges:       1
+# CHECK-NEXT:            RangesOffset:    116
+# CHECK-NEXT:            Ranges:
+# CHECK-NEXT:              - RangeType:       0
+# CHECK-NEXT:                NumDescriptors:  -1
+# CHECK-NEXT:                BaseShaderRegister: 42
+# CHECK-NEXT:                RegisterSpace:   43
+# CHECK-NEXT:                OffsetInDescriptorsFromTableStart: 41
+# CHECK-NEXT:                DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true
 # CHECK-NEXT:      AllowInputAssemblerInputLayout: true
 # CHECK-NEXT:      DenyGeometryShaderRootAccess: true
diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp
index 72f860a5039ff..71503729b5f34 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -1050,3 +1050,108 @@ TEST(RootSignature, ParseRootDescriptor) {
     ASSERT_EQ(Descriptor->Flags, 4u);
   }
 }
+
+TEST(RootSignature, ParseDescriptorTable) {
+  {
+    uint8_t Buffer[] = {
+        0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,
+        0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,
+        0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+        0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+        0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+        0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00};
+    DXContainer C =
+        llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));
+
+    auto MaybeRS = C.getRootSignature();
+    ASSERT_TRUE(MaybeRS.has_value());
+    const auto &RS = MaybeRS.value();
+    ASSERT_EQ(RS.getVersion(), 2u);
+    ASSERT_EQ(RS.getNumParameters(), 1u);
+    ASSERT_EQ(RS.getRootParametersOffset(), 24u);
+    ASSERT_EQ(RS.getNumStaticSamplers(), 0u);
+    ASSERT_EQ(RS.getStaticSamplersOffset(), 60u);
+    ASSERT_EQ(RS.getFlags(), 17u);
+
+    auto RootParam = *RS.param_headers().begin();
+    ASSERT_EQ((unsigned)RootParam.ParameterType, 0u);
+    ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 3u);
+    auto ParamView = RS.getParameter(RootParam);
+    ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());
+
+    auto *DescriptorTableView =
+        dyn_cast<DirectX::DescriptorTableView>(&*ParamView);
+    ASSERT_TRUE(DescriptorTableView != nullptr);
+    auto Table = DescriptorTableView->read(2);
+
+    ASSERT_THAT_ERROR(Table.takeError(), Succeeded());
+
+    ASSERT_EQ(Table->NumRanges, 1u);
+
+    auto Range = *Table->begin();
+
+    ASSERT_EQ(Range.RangeType, 0u);
+    ASSERT_EQ(Range.NumDescriptors, -1u);
+    ASSERT_EQ(Range.BaseShaderRegister, 42u);
+    ASSERT_EQ(Range.RegisterSpace, 43u);
+    ASSERT_EQ(Range.OffsetInDescriptorsFromTableStart, 41u);
+    ASSERT_EQ(Range.Flags, 65536u);
+  }
+
+  {
+    uint8_t Buffer[] = {
+        0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,
+        0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,
+        0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+        0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+        0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x29, 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,
+        0x00};
+    DXContainer C =
+        llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));
+
+    auto MaybeRS = C.getRootSignature();
+    ASSERT_TRUE(MaybeRS.has_value());
+    const auto &RS = MaybeRS.value();
+    ASSERT_EQ(RS.getVersion(), 1u);
+    ASSERT_EQ(RS.getNumParameters(), 1u);
+    ASSERT_EQ(RS.getRootParametersOffset(), 24u);
+    ASSERT_EQ(RS.getNumStaticSamplers(), 0u);
+    ASSERT_EQ(RS.getStaticSamplersOffset(), 60u);
+    ASSERT_EQ(RS.getFlags(), 17u);
+
+    auto RootParam = *RS.param_headers().begin();
+    ASSERT_EQ((unsigned)RootParam.ParameterType, 0u);
+    ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 3u);
+    auto ParamView = RS.getParameter(RootParam);
+    ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());
+
+    auto *DescriptorTableView =
+        dyn_cast<DirectX::DescriptorTableView>(&*ParamView);
+    ASSERT_TRUE(DescriptorTableView != nullptr);
+    auto Table = DescriptorTableView->read(1);
+
+    ASSERT_THAT_ERROR(Table.takeError(), Succeeded());
+
+    ASSERT_EQ(Table->NumRanges, 1u);
+
+    auto Range = *Table->begin();
+
+    ASSERT_EQ(Range.RangeType, 0u);
+    ASSERT_EQ(Range.NumDescriptors, -1u);
+    ASSERT_EQ(Range.BaseShaderRegister, 42u);
+    ASSERT_EQ(Range.RegisterSpace, 43u);
+    ASSERT_EQ(Range.OffsetInDescriptorsFromTableStart, 41u);
+  }
+}
diff --git a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
index b6a5cee24b29d..9215b609a485a 100644
--- a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
+++ b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
@@ -354,3 +354,116 @@ TEST(RootSignature, ParseRootDescriptorsV11) {
   EXPECT_EQ(Storage.size(), 133u);
   EXPECT_TRUE(memcmp(Buffer, Storage.data(), 133u) == 0);
 }
+
+TEST(RootSignature, ParseDescriptorTableV10) {
+  SmallString<128> Storage;
+
+  // First read a fully explicit yaml with all sizes and offsets provided
+  ASSERT_TRUE(convert(Storage, R"(--- !dxcontainer
+  Header:
+      Hash:            [ 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35, 0x6F, 0x5, 
+                        0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1 ]
+      Version:
+        Major:           1
+        Minor:           0
+      FileSize:        133
+      PartCount:       1
+      PartOffsets:     [ 36 ]
+  Parts:
+  - Name:            RTS0
+    Size:            89
+    RootSignature:
+      Version: 1
+      NumRootParameters: 1
+      RootParametersOffset: 24
+      NumStaticSamplers: 0
+      StaticSamplersOffset: 60
+      Parameters:         
+      - ParameterType: 0 # SRV
+        ShaderVisibility: 3 # Domain
+        Table:
+          NumRanges: 1
+          Ranges:
+            - RangeType: 0
+              NumDescriptors: 41
+              BaseShaderRegister: 42
+              RegisterSpace: 43
+              OffsetInDescriptorsFromTableStart: 44
+      AllowInputAssemblerInputLayout: true
+      DenyGeometryShaderRootAccess: true
+    )"));
+
+  uint8_t Buffer[] = {
+      0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,
+      0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,
+      0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+      0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+      0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x2c, 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,
+      0x00};
+
+  EXPECT_EQ(Storage.size(), 133u);
+  EXPECT_TRUE(memcmp(Buffer, Storage.data(), 133u) == 0);
+}
+
+TEST(RootSignature, ParseDescriptorTableV11) {
+  SmallString<128> Storage;
+
+  // First read a fully explicit yaml with all sizes and offsets provided
+  ASSERT_TRUE(convert(Storage, R"(--- !dxcontainer
+  Header:
+      Hash:            [ 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35, 0x6F, 0x5, 
+                        0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1 ]
+      Version:
+        Major:           1
+        Minor:           0
+      FileSize:        133
+      PartCount:       1
+      PartOffsets:     [ 36 ]
+  Parts:
+  - Name:            RTS0
+    Size:            89
+    RootSignature:
+      Version: 2
+      NumRootParameters: 1
+      RootParametersOffset: 24
+      NumStaticSamplers: 0
+      StaticSamplersOffset: 60
+      Parameters:         
+      - ParameterType: 0 # Descriptor Table
+        ShaderVisibility: 3 # Domain
+        Table:
+          NumRanges: 1
+          Ranges:
+            - RangeType: 0
+              NumDescriptors: -1
+              BaseShaderRegister: 42
+              RegisterSpace: 43
+              OffsetInDescriptorsFromTableStart: 41
+              DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true
+      AllowInputAssemblerInputLayout: true
+      DenyGeometryShaderRootAccess: true
+    )"));
+
+  uint8_t Buffer[] = {
+      0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,
+      0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,
+      0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+      0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+      0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+      0x2a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00};
+
+  EXPECT_EQ(Storage.size(), 133u);
+  EXPECT_TRUE(memcmp(Buffer, Storage.data(), 133u) == 0);
+}


Reviews:
user: login: inbelic
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T17:28:03Z
user: login: joaosaffran
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T18:13:37Z
user: login: joaosaffran
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T18:20:06Z
user: login: bogner
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T16:48:25Z
user: login: joaosaffran
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T17:16:19Z
user: login: joaosaffran
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T17:23:11Z
user: login: joaosaffran
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T17:25:22Z
user: login: joaosaffran
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T18:33:48Z
user: login: joaosaffran
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-22T19:33:17Z
user: login: llvm-beanz
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-28T14:11:48Z
user: login: bogner
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-29T16:13:44Z
user: login: bogner
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-06-06T19:42:45Z
user: login: joaosaffran
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-06-06T20:12:09Z
user: login: inbelic
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-06-06T20:14:40Z
user: login: joaosaffran
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-06-06T20:38:10Z

Review comments:
diff_hunk: @@ -595,6 +607,21 @@ struct RootDescriptor {
     sys::swapByteOrder(RegisterSpace);
   }
 };
+
+struct DescriptorRange {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  int32_t OffsetInDescriptorsFromTableStart;
path: llvm/include/llvm/BinaryFormat/DXContainer.h
user: login: inbelic
body: I would have expected this to also be `uint32_t`?
created_at: 2025-05-20T16:46:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -69,6 +87,9 @@ struct RootParametersContainer {
   const dxbc::RTS0::v2::RootDescriptor &getRootDescriptor(size_t Index) const {
     return Descriptors[Index];
   }
+  const DescriptorTable &getDescriptorTable(size_t Index) const {
path: llvm/include/llvm/MC/DXContainerRootSignature.h
user: login: inbelic
body: nit: add extra line above
created_at: 2025-05-20T16:46:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -324,6 +379,10 @@ void MappingTraits<llvm::DXContainerYAML::RootParameterYamlDesc>::mapping(
   case llvm::to_underlying(dxbc::RootParameterType::UAV):
     IO.mapRequired("Descriptor", P.Descriptor);
     break;
+  case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+    IO.mapRequired("Table", P.Table);
+    break;
+    break;
path: llvm/lib/ObjectYAML/DXContainerYAML.cpp
user: login: inbelic
body: ```suggestion
```
created_at: 2025-05-20T16:49:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -625,8 +628,8 @@ TEST(DXCFile, PSVResourceIteratorsStride) {
   EXPECT_EQ(Binding.Type, dxbc::PSV::ResourceType::SRVStructured);
   EXPECT_EQ(Binding.Space, 6u);
   EXPECT_EQ(Binding.LowerBound, 7u);
-  EXPECT_EQ(Binding.UpperBound, 8u);;
-
+  EXPECT_EQ(Binding.UpperBound, 8u);
+  ;
path: llvm/unittests/Object/DXContainerTest.cpp
user: login: inbelic
body: ```suggestion
```

I guess the changes above are a clang-format of this file? It might be less confusing to leave those out and then just do an NFC change after all the implementations are complete to format the file
created_at: 2025-05-20T16:54:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -46,6 +48,16 @@ size_t RootSignatureDesc::getSize() const {
         Size += sizeof(dxbc::RTS0::v2::RootDescriptor);
 
       break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      const DescriptorTable &Table =
+          ParametersContainer.getDescriptorTable(I.Location);
+      if (Version == 1)
+        Size +=
+            sizeof(dxbc::RTS0::v1::DescriptorRange) * Table.Ranges.size() + 8;
+      else
+        Size +=
+            sizeof(dxbc::RTS0::v2::DescriptorRange) * Table.Ranges.size() + 8;
path: llvm/lib/MC/DXContainerRootSignature.cpp
user: login: inbelic
body: ```suggestion
      if (Version == 1)
        Size +=
            sizeof(dxbc::RTS0::v1::DescriptorRange) * Table.Ranges.size();
      else
        Size +=
            sizeof(dxbc::RTS0::v2::DescriptorRange) * Table.Ranges.size();
      Size += sizeof(uint32_t); // Ranges offset
```
I think the extra space is for the offset correct?
created_at: 2025-05-20T17:00:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -103,8 +114,27 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
                              llvm::endianness::little);
       if (Version > 1)
         support::endian::write(BOS, Descriptor.Flags, llvm::endianness::little);
-      break;
-    }
+    } break;
path: llvm/lib/MC/DXContainerRootSignature.cpp
user: login: inbelic
body: nit: I guess you have a code formatter that prefers `} break;` but I think in previous reviews it was agreed to use the other version.
created_at: 2025-05-20T17:01:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -11,6 +11,7 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/STLForwardCompat.h"
path: llvm/lib/ObjectYAML/DXContainerEmitter.cpp
user: login: inbelic
body: ```suggestion
```

I think this is included other places redundantly as well
created_at: 2025-05-20T17:02:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -595,6 +607,21 @@ struct RootDescriptor {
     sys::swapByteOrder(RegisterSpace);
   }
 };
+
+struct DescriptorRange {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  int32_t OffsetInDescriptorsFromTableStart;
path: llvm/include/llvm/BinaryFormat/DXContainer.h
user: login: joaosaffran
body: `OffsetInDescriptorsFromTableStart`, supports -1 to represent unbounded
created_at: 2025-05-20T18:13:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -46,6 +48,16 @@ size_t RootSignatureDesc::getSize() const {
         Size += sizeof(dxbc::RTS0::v2::RootDescriptor);
 
       break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      const DescriptorTable &Table =
+          ParametersContainer.getDescriptorTable(I.Location);
+      if (Version == 1)
+        Size +=
+            sizeof(dxbc::RTS0::v1::DescriptorRange) * Table.Ranges.size() + 8;
+      else
+        Size +=
+            sizeof(dxbc::RTS0::v2::DescriptorRange) * Table.Ranges.size() + 8;
path: llvm/lib/MC/DXContainerRootSignature.cpp
user: login: joaosaffran
body: 4 bits for offset, and 4 bits for the amount of ranges in the table.
created_at: 2025-05-20T18:20:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -595,6 +607,21 @@ struct RootDescriptor {
     sys::swapByteOrder(RegisterSpace);
   }
 };
+
+struct DescriptorRange {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  int32_t OffsetInDescriptorsFromTableStart;
path: llvm/include/llvm/BinaryFormat/DXContainer.h
user: login: bogner
body: Are other negative numbers (that is, unsigned values between 2147483648 and 4294967294) impossible / invalid, or do we need to treat them as large numbers?
created_at: 2025-05-22T16:23:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,6 +62,11 @@ struct RootParametersContainer {
     Descriptors.push_back(Descriptor);
   }
 
+  void addParameter(dxbc::RootParameterHeader H, DescriptorTable D) {
path: llvm/include/llvm/MC/DXContainerRootSignature.h
user: login: bogner
body: ```suggestion
  void addParameter(dxbc::RootParameterHeader Header, DescriptorTable Table) {
```
created_at: 2025-05-22T16:25:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -228,6 +273,19 @@ class RootSignature {
       else
         DataSize = sizeof(dxbc::RTS0::v2::RootDescriptor);
       break;
+    case dxbc::RootParameterType::DescriptorTable:
+      uint32_t NumRanges =
+          support::endian::read<uint32_t, llvm::endianness::little>(
+              PartData.begin() + Header.ParameterOffset);
+      if (Version == 1)
+        DataSize = sizeof(dxbc::RTS0::v1::DescriptorRange) * NumRanges;
+      else
+        DataSize = sizeof(dxbc::RTS0::v2::DescriptorRange) * NumRanges;
+
+      // 4 bits for the number of ranges in table and
+      // 4 bits for the ranges offset
path: llvm/include/llvm/Object/DXContainer.h
user: login: bogner
body: Do you mean bytes here, rather than bits?
created_at: 2025-05-22T16:27:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,13 +125,82 @@ struct RootParameterYamlDesc {
     case llvm::to_underlying(dxbc::RootParameterType::UAV):
       Descriptor = RootDescriptorYaml();
       break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table = DescriptorTableYaml();
+      break;
+    }
+  }
+
+  ~RootParameterYamlDesc() {
+    switch (Type) {
+
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      Constants.~RootConstantsYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      Descriptor.~RootDescriptorYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table.~DescriptorTableYaml();
+      break;
     }
   }
 
+  RootParameterYamlDesc(const RootParameterYamlDesc &Other)
+      : Type(Other.Type), Visibility(Other.Visibility), Offset(Other.Offset) {
+    // Initialize the appropriate union member based on Type
+    switch (Type) {
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      // Placement new to construct the union member
+      new (&Constants) RootConstantsYaml(Other.Constants);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      new (&Table) DescriptorTableYaml(Other.Table);
+      break;
+    }
+  }
+
+  RootParameterYamlDesc &operator=(const RootParameterYamlDesc &Other) {
+    if (this != &Other) {
+      // First, destroy the current union member
+      this->~RootParameterYamlDesc();
+
+      // Copy the basic members
+      Type = Other.Type;
+      Visibility = Other.Visibility;
+      Offset = Other.Offset;
+
+      // Initialize the new union member based on the Type from 'other'
+      switch (Type) {
+      case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+        new (&Constants) RootConstantsYaml(Other.Constants);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::CBV):
+      case llvm::to_underlying(dxbc::RootParameterType::SRV):
+      case llvm::to_underlying(dxbc::RootParameterType::UAV):
+        new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+        new (&Table) DescriptorTableYaml(Other.Table);
+        break;
+      }
+    }
+    return *this;
+  }
+
+  // ToDo: Fix this (Already have a follow up PR with it)
path: llvm/include/llvm/ObjectYAML/DXContainerYAML.h
user: login: bogner
body: I haven't seen the other PR yet, so it isn't clear to me how much work it would be, but shouldn't we just do this first? Presumably all of the custom constructor/destructor logic gets cleaned up by the re-design, right?

It's hard to tell what to review with this kind of TODO...
created_at: 2025-05-22T16:32:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -228,6 +273,19 @@ class RootSignature {
       else
         DataSize = sizeof(dxbc::RTS0::v2::RootDescriptor);
       break;
+    case dxbc::RootParameterType::DescriptorTable:
+      uint32_t NumRanges =
+          support::endian::read<uint32_t, llvm::endianness::little>(
+              PartData.begin() + Header.ParameterOffset);
path: llvm/include/llvm/Object/DXContainer.h
user: login: bogner
body: It's a bit unfortunate that we need to read the data here in order to parse it. Do we do anything elsewhere to make sure that corrupted data doesn't bite us here? That is, does this do something reasonable for an absurdly large incorrect size or does it fall over?
created_at: 2025-05-22T16:40:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -46,6 +46,18 @@ size_t RootSignatureDesc::getSize() const {
         Size += sizeof(dxbc::RTS0::v2::RootDescriptor);
 
       break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      const DescriptorTable &Table =
+          ParametersContainer.getDescriptorTable(I.Location);
+
+      // 4 bits for the number of ranges in table and
+      // 4 bits for the ranges offset
+      Size += 2 * sizeof(uint32_t);
path: llvm/lib/MC/DXContainerRootSignature.cpp
user: login: bogner
body: bits/bytes, as in the other identical comment
created_at: 2025-05-22T16:41:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -295,16 +295,33 @@ void DXContainerWriter::writeParts(raw_ostream &OS) {
             Descriptor.Flags = Param.Descriptor.getEncodedFlags();
           RS.ParametersContainer.addParameter(Header, Descriptor);
           break;
+        case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
+          mcdxbc::DescriptorTable Table;
+          for (const auto &R : Param.Table.Ranges) {
+
+            dxbc::RTS0::v2::DescriptorRange Range;
+            Range.RangeType = R.RangeType;
+            Range.NumDescriptors = R.NumDescriptors;
+            Range.BaseShaderRegister = R.BaseShaderRegister;
+            Range.RegisterSpace = R.RegisterSpace;
+            Range.OffsetInDescriptorsFromTableStart =
+                R.OffsetInDescriptorsFromTableStart;
+            if (RS.Version > 1)
+              Range.Flags = R.getEncodedFlags();
+            Table.Ranges.push_back(Range);
+          }
+          RS.ParametersContainer.addParameter(Header, Table);
+        } break;
         default:
           // Handling invalid parameter type edge case. We intentionally let
           // obj2yaml/yaml2obj parse and emit invalid dxcontainer data, in order
           // for that to be used as a testing tool more effectively.
           RS.ParametersContainer.addInvalidParameter(Header);
+          break;
         }
       }
 
       RS.write(OS);
-      break;
path: llvm/lib/ObjectYAML/DXContainerEmitter.cpp
user: login: bogner
body: Why remove this break? Isn't this the break for the outer `switch (PT)`?

Aside: as a follow up we should really consider breaking this function up into smaller parts - it's getting very hard to follow.
created_at: 2025-05-22T16:44:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -95,6 +95,33 @@ DXContainerYAML::RootSignatureYamlDesc::create(
        llvm::to_underlying(dxbc::RootDescriptorFlag::Val)) > 0;
 #include "llvm/BinaryFormat/DXContainerConstants.def"
       }
+    } else if (auto *TDV =
path: llvm/lib/ObjectYAML/DXContainerYAML.cpp
user: login: bogner
body: TDV?
created_at: 2025-05-22T16:45:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -37,35 +37,58 @@ Parts:
           ShaderRegister: 31
           RegisterSpace: 32
           DATA_STATIC_WHILE_SET_AT_EXECUTE: true
+      - ParameterType: 0 # SRV
+        ShaderVisibility: 3 # Domain
+        Table:
+          NumRanges: 1
+          Ranges:
+            - RangeType: 0
+              NumDescriptors: 41
+              BaseShaderRegister: 42
+              RegisterSpace: 43
+              OffsetInDescriptorsFromTableStart: -1
+              DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true
       AllowInputAssemblerInputLayout: true
       DenyGeometryShaderRootAccess: true
 
-# CHECK:  - Name:            RTS0
-# CHECK-NEXT:    Size:            96
-# CHECK-NEXT:    RootSignature:
-# CHECK-NEXT:      Version:         2
-# CHECK-NEXT:      NumRootParameters: 3
-# CHECK-NEXT:      RootParametersOffset: 24
-# CHECK-NEXT:      NumStaticSamplers: 0
-# CHECK-NEXT:      StaticSamplersOffset: 60
-# CHECK-NEXT:      Parameters:
-# CHECK-NEXT:        - ParameterType:   1
-# CHECK-NEXT:          ShaderVisibility: 2
-# CHECK-NEXT:          Constants:
-# CHECK-NEXT:            Num32BitValues:  16
-# CHECK-NEXT:            RegisterSpace:   14
-# CHECK-NEXT:            ShaderRegister:  15
-# CHECK-NEXT:        - ParameterType:   1
-# CHECK-NEXT:          ShaderVisibility: 4
-# CHECK-NEXT:          Constants:
-# CHECK-NEXT:            Num32BitValues:  21
-# CHECK-NEXT:            RegisterSpace:   23
-# CHECK-NEXT:            ShaderRegister:  22
-# CHECK-NEXT:        - ParameterType:   2
-# CHECK-NEXT:          ShaderVisibility: 3
-# CHECK-NEXT:          Descriptor:
-# CHECK-NEXT:            RegisterSpace:   32
-# CHECK-NEXT:            ShaderRegister:  31
-# CHECK-NEXT:            DATA_STATIC_WHILE_SET_AT_EXECUTE: true
-# CHECK-NEXT:      AllowInputAssemblerInputLayout: true
-# CHECK-NEXT:      DenyGeometryShaderRootAccess: true
+#CHECK:  - Name:            RTS0
path: llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml
user: login: bogner
body: Looks like you accidentally removed the space after the comment character in this block of checks
created_at: 2025-05-22T16:47:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -595,6 +607,21 @@ struct RootDescriptor {
     sys::swapByteOrder(RegisterSpace);
   }
 };
+
+struct DescriptorRange {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  int32_t OffsetInDescriptorsFromTableStart;
path: llvm/include/llvm/BinaryFormat/DXContainer.h
user: login: joaosaffran
body: Just checked the spec, I made a mistake `NumDescriptors` allows -1 to describe unbounded [UINT_MAX ](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_descriptor_range#members). 

According to the spec: "Use -1 or UINT_MAX to specify an unbounded size.", my understanding is that only -1 is a valid here. 

Since folks are annoyed with this I will make it `uint32_t`.
created_at: 2025-05-22T17:16:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -95,6 +95,33 @@ DXContainerYAML::RootSignatureYamlDesc::create(
        llvm::to_underlying(dxbc::RootDescriptorFlag::Val)) > 0;
 #include "llvm/BinaryFormat/DXContainerConstants.def"
       }
+    } else if (auto *TDV =
path: llvm/lib/ObjectYAML/DXContainerYAML.cpp
user: login: joaosaffran
body: Sorry... dyslexia, DTV (Descriptor table view)
created_at: 2025-05-22T17:23:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,13 +125,82 @@ struct RootParameterYamlDesc {
     case llvm::to_underlying(dxbc::RootParameterType::UAV):
       Descriptor = RootDescriptorYaml();
       break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table = DescriptorTableYaml();
+      break;
+    }
+  }
+
+  ~RootParameterYamlDesc() {
+    switch (Type) {
+
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      Constants.~RootConstantsYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      Descriptor.~RootDescriptorYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table.~DescriptorTableYaml();
+      break;
     }
   }
 
+  RootParameterYamlDesc(const RootParameterYamlDesc &Other)
+      : Type(Other.Type), Visibility(Other.Visibility), Offset(Other.Offset) {
+    // Initialize the appropriate union member based on Type
+    switch (Type) {
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      // Placement new to construct the union member
+      new (&Constants) RootConstantsYaml(Other.Constants);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      new (&Table) DescriptorTableYaml(Other.Table);
+      break;
+    }
+  }
+
+  RootParameterYamlDesc &operator=(const RootParameterYamlDesc &Other) {
+    if (this != &Other) {
+      // First, destroy the current union member
+      this->~RootParameterYamlDesc();
+
+      // Copy the basic members
+      Type = Other.Type;
+      Visibility = Other.Visibility;
+      Offset = Other.Offset;
+
+      // Initialize the new union member based on the Type from 'other'
+      switch (Type) {
+      case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+        new (&Constants) RootConstantsYaml(Other.Constants);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::CBV):
+      case llvm::to_underlying(dxbc::RootParameterType::SRV):
+      case llvm::to_underlying(dxbc::RootParameterType::UAV):
+        new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+        new (&Table) DescriptorTableYaml(Other.Table);
+        break;
+      }
+    }
+    return *this;
+  }
+
+  // ToDo: Fix this (Already have a follow up PR with it)
path: llvm/include/llvm/ObjectYAML/DXContainerYAML.h
user: login: joaosaffran
body: Will Remove that and swap the PRs order
created_at: 2025-05-22T17:25:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -228,6 +273,19 @@ class RootSignature {
       else
         DataSize = sizeof(dxbc::RTS0::v2::RootDescriptor);
       break;
+    case dxbc::RootParameterType::DescriptorTable:
+      uint32_t NumRanges =
+          support::endian::read<uint32_t, llvm::endianness::little>(
+              PartData.begin() + Header.ParameterOffset);
path: llvm/include/llvm/Object/DXContainer.h
user: login: joaosaffran
body: We don't handle this case while reading the root signature part, not sure if there is validation process before reading the parts. 

What will happen is: in case of absurdly larger numbers, invalid data would be read, since this would overflow the section containing descriptor ranges, and it would likely crash due to access out of bounds sections.
created_at: 2025-05-22T18:33:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,13 +125,82 @@ struct RootParameterYamlDesc {
     case llvm::to_underlying(dxbc::RootParameterType::UAV):
       Descriptor = RootDescriptorYaml();
       break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table = DescriptorTableYaml();
+      break;
+    }
+  }
+
+  ~RootParameterYamlDesc() {
+    switch (Type) {
+
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      Constants.~RootConstantsYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      Descriptor.~RootDescriptorYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table.~DescriptorTableYaml();
+      break;
     }
   }
 
+  RootParameterYamlDesc(const RootParameterYamlDesc &Other)
+      : Type(Other.Type), Visibility(Other.Visibility), Offset(Other.Offset) {
+    // Initialize the appropriate union member based on Type
+    switch (Type) {
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      // Placement new to construct the union member
+      new (&Constants) RootConstantsYaml(Other.Constants);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      new (&Table) DescriptorTableYaml(Other.Table);
+      break;
+    }
+  }
+
+  RootParameterYamlDesc &operator=(const RootParameterYamlDesc &Other) {
+    if (this != &Other) {
+      // First, destroy the current union member
+      this->~RootParameterYamlDesc();
+
+      // Copy the basic members
+      Type = Other.Type;
+      Visibility = Other.Visibility;
+      Offset = Other.Offset;
+
+      // Initialize the new union member based on the Type from 'other'
+      switch (Type) {
+      case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+        new (&Constants) RootConstantsYaml(Other.Constants);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::CBV):
+      case llvm::to_underlying(dxbc::RootParameterType::SRV):
+      case llvm::to_underlying(dxbc::RootParameterType::UAV):
+        new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+        new (&Table) DescriptorTableYaml(Other.Table);
+        break;
+      }
+    }
+    return *this;
+  }
+
+  // ToDo: Fix this (Already have a follow up PR with it)
path: llvm/include/llvm/ObjectYAML/DXContainerYAML.h
user: login: joaosaffran
body: PR Doing the refactoring: https://github.com/llvm/llvm-project/pull/138318
created_at: 2025-05-22T19:33:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -228,6 +273,19 @@ class RootSignature {
       else
         DataSize = sizeof(dxbc::RTS0::v2::RootDescriptor);
       break;
+    case dxbc::RootParameterType::DescriptorTable:
+      uint32_t NumRanges =
+          support::endian::read<uint32_t, llvm::endianness::little>(
+              PartData.begin() + Header.ParameterOffset);
path: llvm/include/llvm/Object/DXContainer.h
user: login: llvm-beanz
body: The DXContainer reader really needs to be hardened against crashing since this code may be used in drivers and/or runtime libraries.

We should at least validate that the offset is within the part's range and error appropriately.
created_at: 2025-05-28T14:11:48Z
author_association: COLLABORATOR
diff_hunk: @@ -86,8 +86,21 @@ ROOT_DESCRIPTOR_FLAG(3, DATA_STATIC)
 #endif // ROOT_DESCRIPTOR_FLAG
 
 
+// DESCRIPTOR_RANGE_FLAG(bit offset for the flag, name).
+#ifdef DESCRIPTOR_RANGE_FLAG
+
+DESCRIPTOR_RANGE_FLAG(0, NONE)
+DESCRIPTOR_RANGE_FLAG(1, DESCRIPTORS_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(2, DATA_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(3, DATA_STATIC_WHILE_SET_AT_EXECUTE)
+DESCRIPTOR_RANGE_FLAG(4, DATA_STATIC)
+DESCRIPTOR_RANGE_FLAG(16, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS)
path: llvm/include/llvm/BinaryFormat/DXContainerConstants.def
user: login: bogner
body: These values are wrong - when we turn these into an enum in DXContainer.h, we do `Val = 1ull << Num`,  so we get NONE equal to 1 and DESCRIPTORS_VOLATILE equal to 2, even though DESCRIPTORS_VOLATILE should be 1 AFAICT
created_at: 2025-06-06T19:42:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -86,8 +86,21 @@ ROOT_DESCRIPTOR_FLAG(3, DATA_STATIC)
 #endif // ROOT_DESCRIPTOR_FLAG
 
 
+// DESCRIPTOR_RANGE_FLAG(bit offset for the flag, name).
+#ifdef DESCRIPTOR_RANGE_FLAG
+
+DESCRIPTOR_RANGE_FLAG(0, NONE)
+DESCRIPTOR_RANGE_FLAG(1, DESCRIPTORS_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(2, DATA_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(3, DATA_STATIC_WHILE_SET_AT_EXECUTE)
+DESCRIPTOR_RANGE_FLAG(4, DATA_STATIC)
+DESCRIPTOR_RANGE_FLAG(16, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS)
path: llvm/include/llvm/BinaryFormat/DXContainerConstants.def
user: login: joaosaffran
body: True, will fix that 
created_at: 2025-06-06T20:12:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -86,8 +86,21 @@ ROOT_DESCRIPTOR_FLAG(3, DATA_STATIC)
 #endif // ROOT_DESCRIPTOR_FLAG
 
 
+// DESCRIPTOR_RANGE_FLAG(bit offset for the flag, name).
+#ifdef DESCRIPTOR_RANGE_FLAG
+
+DESCRIPTOR_RANGE_FLAG(0, NONE)
+DESCRIPTOR_RANGE_FLAG(1, DESCRIPTORS_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(2, DATA_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(3, DATA_STATIC_WHILE_SET_AT_EXECUTE)
+DESCRIPTOR_RANGE_FLAG(4, DATA_STATIC)
+DESCRIPTOR_RANGE_FLAG(16, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS)
path: llvm/include/llvm/BinaryFormat/DXContainerConstants.def
user: login: inbelic
body: As noted here: https://github.com/llvm/llvm-project/pull/143041#pullrequestreview-2906011689.

Maybe reusing the values will address this as well?
created_at: 2025-06-06T20:14:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -86,8 +86,21 @@ ROOT_DESCRIPTOR_FLAG(3, DATA_STATIC)
 #endif // ROOT_DESCRIPTOR_FLAG
 
 
+// DESCRIPTOR_RANGE_FLAG(bit offset for the flag, name).
+#ifdef DESCRIPTOR_RANGE_FLAG
+
+DESCRIPTOR_RANGE_FLAG(0, NONE)
+DESCRIPTOR_RANGE_FLAG(1, DESCRIPTORS_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(2, DATA_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(3, DATA_STATIC_WHILE_SET_AT_EXECUTE)
+DESCRIPTOR_RANGE_FLAG(4, DATA_STATIC)
+DESCRIPTOR_RANGE_FLAG(16, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS)
path: llvm/include/llvm/BinaryFormat/DXContainerConstants.def
user: login: joaosaffran
body: Fix PR: https://github.com/llvm/llvm-project/pull/143201

created_at: 2025-06-06T20:38:10Z
author_association: CONTRIBUTOR

PR comments:
user: login: llvmbot
created_at: 2025-05-02T18:01:25Z
body: 
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-objectyaml
@llvm/pr-subscribers-llvm-binary-utilities

@llvm/pr-subscribers-mc

Author: None (joaosaffran)

<details>
<summary>Changes</summary>

Closes: https://github.com/orgs/llvm/projects/4/views/22?sliceBy%5Bvalue%5D=joaosaffran&amp;pane=issue&amp;itemId=97332852&amp;issue=llvm%7Cllvm-project%7C126635

---

Patch is 45.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138315.diff


13 Files Affected:

- (modified) llvm/include/llvm/BinaryFormat/DXContainer.h (+35) 
- (modified) llvm/include/llvm/BinaryFormat/DXContainerConstants.def (+24-1) 
- (modified) llvm/include/llvm/MC/DXContainerRootSignature.h (+27-5) 
- (modified) llvm/include/llvm/Object/DXContainer.h (+66-3) 
- (modified) llvm/include/llvm/ObjectYAML/DXContainerYAML.h (+99) 
- (modified) llvm/lib/MC/DXContainerRootSignature.cpp (+72-6) 
- (modified) llvm/lib/ObjectYAML/DXContainerEmitter.cpp (+27) 
- (modified) llvm/lib/ObjectYAML/DXContainerYAML.cpp (+81) 
- (added) llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.0.yaml (+57) 
- (added) llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.1.yaml (+59) 
- (modified) llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml (+53-30) 
- (modified) llvm/unittests/Object/DXContainerTest.cpp (+107) 
- (modified) llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp (+113) 


``````````diff
diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h
index 3dbcfa82f3d7c..a441fa3a36886 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainer.h
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -163,6 +163,11 @@ enum class RootDescriptorFlag : uint32_t {
 #include "DXContainerConstants.def"
 };
 
+#define DESCRIPTOR_RANGE_FLAG(Num, Val) Val = 1ull << Num,
+enum class DescriptorRangeFlag : uint32_t {
+#include "DXContainerConstants.def"
+};
+
 #define ROOT_PARAMETER(Val, Enum) Enum = Val,
 enum class RootParameterType : uint32_t {
 #include "DXContainerConstants.def"
@@ -170,6 +175,13 @@ enum class RootParameterType : uint32_t {
 
 ArrayRef<EnumEntry<RootParameterType>> getRootParameterTypes();
 
+#define DESCRIPTOR_RANGE(Val, Enum) Enum = Val,
+enum class DescriptorRangeType : uint32_t {
+#include "DXContainerConstants.def"
+};
+
+ArrayRef<EnumEntry<DescriptorRangeType>> getDescriptorRangeTypes();
+
 #define ROOT_PARAMETER(Val, Enum)                                              \
   case Val:                                                                    \
     return true;
@@ -595,6 +607,21 @@ struct RootDescriptor {
     sys::swapByteOrder(RegisterSpace);
   }
 };
+
+struct DescriptorRange {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  int32_t OffsetInDescriptorsFromTableStart;
+  void swapBytes() {
+    sys::swapByteOrder(RangeType);
+    sys::swapByteOrder(NumDescriptors);
+    sys::swapByteOrder(BaseShaderRegister);
+    sys::swapByteOrder(RegisterSpace);
+    sys::swapByteOrder(OffsetInDescriptorsFromTableStart);
+  }
+};
 } // namespace v0
 
 namespace v1 {
@@ -605,6 +632,14 @@ struct RootDescriptor : public v0::RootDescriptor {
     sys::swapByteOrder(Flags);
   }
 };
+
+struct DescriptorRange : public v0::DescriptorRange {
+  uint32_t Flags;
+  void swapBytes() {
+    v0::DescriptorRange::swapBytes();
+    sys::swapByteOrder(Flags);
+  }
+};
 } // namespace v1
 } // namespace RST0
 // following dx12 naming
diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
index bd9bd760547dc..5fe7e7c321a33 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
+++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
@@ -73,7 +73,7 @@ ROOT_ELEMENT_FLAG(11, SamplerHeapDirectlyIndexed)
 #endif // ROOT_ELEMENT_FLAG
 
  
-// ROOT_ELEMENT_FLAG(bit offset for the flag, name).
+// ROOT_DESCRIPTOR_FLAG(bit offset for the flag, name).
 #ifdef ROOT_DESCRIPTOR_FLAG
 
 ROOT_DESCRIPTOR_FLAG(0, NONE)
@@ -84,8 +84,21 @@ ROOT_DESCRIPTOR_FLAG(3, DATA_STATIC)
 #endif // ROOT_DESCRIPTOR_FLAG
 
 
+// DESCRIPTOR_RANGE_FLAG(bit offset for the flag, name).
+#ifdef DESCRIPTOR_RANGE_FLAG
+
+DESCRIPTOR_RANGE_FLAG(0, NONE)
+DESCRIPTOR_RANGE_FLAG(1, DESCRIPTORS_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(2, DATA_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(3, DATA_STATIC_WHILE_SET_AT_EXECUTE)
+DESCRIPTOR_RANGE_FLAG(4, DATA_STATIC)
+DESCRIPTOR_RANGE_FLAG(16, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS)
+#undef DESCRIPTOR_RANGE_FLAG
+#endif // DESCRIPTOR_RANGE_FLAG
+
 #ifdef ROOT_PARAMETER
 
+ROOT_PARAMETER(0, DescriptorTable)
 ROOT_PARAMETER(1, Constants32Bit)
 ROOT_PARAMETER(2, CBV)
 ROOT_PARAMETER(3, SRV)
@@ -93,6 +106,16 @@ ROOT_PARAMETER(4, UAV)
 #undef ROOT_PARAMETER
 #endif // ROOT_PARAMETER
 
+
+#ifdef DESCRIPTOR_RANGE
+
+DESCRIPTOR_RANGE(0, SRV)
+DESCRIPTOR_RANGE(1, UAV)
+DESCRIPTOR_RANGE(2, CBV)
+DESCRIPTOR_RANGE(3, Sampler)
+#undef DESCRIPTOR_RANGE
+#endif // DESCRIPTOR_RANGE
+
 #ifdef SHADER_VISIBILITY
 
 SHADER_VISIBILITY(0, All)
diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h
index c8af613a57094..3f5960a6de2f9 100644
--- a/llvm/include/llvm/MC/DXContainerRootSignature.h
+++ b/llvm/include/llvm/MC/DXContainerRootSignature.h
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include <cstddef>
 #include <cstdint>
@@ -28,17 +29,30 @@ struct RootParameterInfo {
   RootParameterInfo(dxbc::RootParameterHeader H, size_t L)
       : Header(H), Location(L) {}
 };
+using DescriptorRanges = std::variant<dxbc::RST0::v0::DescriptorRange,
+                                      dxbc::RST0::v1::DescriptorRange>;
+struct DescriptorTable {
+  SmallVector<DescriptorRanges> Ranges;
+
+  SmallVector<DescriptorRanges>::const_iterator begin() const {
+    return Ranges.begin();
+  }
+  SmallVector<DescriptorRanges>::const_iterator end() const {
+    return Ranges.end();
+  }
+};
 
 using RootDescriptor = std::variant<dxbc::RST0::v0::RootDescriptor,
                                     dxbc::RST0::v1::RootDescriptor>;
-using ParametersView = std::variant<const dxbc::RootConstants *,
-                                    const dxbc::RST0::v0::RootDescriptor *,
-                                    const dxbc::RST0::v1::RootDescriptor *>;
+
+using ParametersView = std::variant<
+    const dxbc::RootConstants *, const dxbc::RST0::v0::RootDescriptor *,
+    const dxbc::RST0::v1::RootDescriptor *, const DescriptorTable *>;
 struct RootParametersContainer {
   SmallVector<RootParameterInfo> ParametersInfo;
-
   SmallVector<dxbc::RootConstants> Constants;
   SmallVector<RootDescriptor> Descriptors;
+  SmallVector<DescriptorTable> Tables;
 
   void addInfo(dxbc::RootParameterHeader H, size_t L) {
     ParametersInfo.push_back(RootParameterInfo(H, L));
@@ -61,13 +75,18 @@ struct RootParametersContainer {
     Descriptors.push_back(D);
   }
 
+  void addParameter(dxbc::RootParameterHeader H, DescriptorTable D) {
+    addInfo(H, Tables.size());
+    Tables.push_back(D);
+  }
+
   std::optional<ParametersView> getParameter(const RootParameterInfo *H) const {
     switch (H->Header.ParameterType) {
     case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
       return &Constants[H->Location];
     case llvm::to_underlying(dxbc::RootParameterType::CBV):
     case llvm::to_underlying(dxbc::RootParameterType::SRV):
-    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV): {
       const RootDescriptor &VersionedParam = Descriptors[H->Location];
       if (std::holds_alternative<dxbc::RST0::v0::RootDescriptor>(
               VersionedParam)) {
@@ -75,6 +94,9 @@ struct RootParametersContainer {
       }
       return &std::get<dxbc::RST0::v1::RootDescriptor>(VersionedParam);
     }
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      return &Tables[H->Location];
+    }
 
     return std::nullopt;
   }
diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h
index e359d85f08bec..c6c22213d7de8 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -19,11 +19,11 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Object/Error.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/TargetParser/Triple.h"
-#include <array>
-#include <cstddef>
 #include <variant>
 
 namespace llvm {
@@ -39,6 +39,7 @@ template <typename T>
 std::enable_if_t<std::is_class<T>::value, void> swapBytes(T &value) {
   value.swapBytes();
 }
+
 } // namespace detail
 
 // This class provides a view into the underlying resource array. The Resource
@@ -121,8 +122,10 @@ namespace DirectX {
 struct RootParameterView {
   const dxbc::RootParameterHeader &Header;
   StringRef ParamData;
+  uint32_t Version;
+
   RootParameterView(uint32_t V, const dxbc::RootParameterHeader &H, StringRef P)
-      : Header(H), ParamData(P) {}
+      : Header(H), ParamData(P), Version(V) {}
 
   template <typename T, typename VersionT = T> Expected<T> readParameter() {
     assert(sizeof(VersionT) <= sizeof(T) &&
@@ -169,6 +172,55 @@ struct RootDescriptorView : RootParameterView {
     return readParameter<dxbc::RST0::v1::RootDescriptor>();
   }
 };
+template <typename T> struct DescriptorTable {
+  uint32_t NumRanges;
+  uint32_t RangesOffset;
+  ViewArray<T> Ranges;
+
+  typename ViewArray<T>::iterator begin() const { return Ranges.begin(); }
+
+  typename ViewArray<T>::iterator end() const { return Ranges.end(); }
+};
+template <typename T> struct TemplateTypeToVersion {
+  // Default version
+  static constexpr uint32_t Value = -1;
+};
+
+template <> struct TemplateTypeToVersion<dxbc::RST0::v0::DescriptorRange> {
+  static constexpr uint32_t Value = 1;
+};
+
+template <> struct TemplateTypeToVersion<dxbc::RST0::v1::DescriptorRange> {
+  static constexpr uint32_t Value = 2;
+};
+
+template <typename T> struct DescriptorTableView : RootParameterView {
+  using TemplateType = T;
+
+  static bool classof(const RootParameterView *V) {
+    return (V->Header.ParameterType ==
+            llvm::to_underlying(dxbc::RootParameterType::DescriptorTable)) &&
+           (V->Version == TemplateTypeToVersion<T>::Value);
+  }
+
+  // Define a type alias to access the template parameter from inside classof
+  llvm::Expected<DescriptorTable<T>> read() {
+    const char *Current = ParamData.begin();
+    DescriptorTable<T> Table;
+
+    Table.NumRanges =
+        support::endian::read<uint32_t, llvm::endianness::little>(Current);
+    Current += sizeof(uint32_t);
+
+    Table.RangesOffset =
+        support::endian::read<uint32_t, llvm::endianness::little>(Current);
+    Current += sizeof(uint32_t);
+
+    Table.Ranges.Data =
+        ParamData.substr(2 * sizeof(uint32_t), Table.NumRanges * sizeof(T));
+    return Table;
+  }
+};
 
 static Error parseFailed(const Twine &Msg) {
   return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);
@@ -221,6 +273,17 @@ class RootSignature {
       else
         DataSize = sizeof(dxbc::RST0::v1::RootDescriptor);
       break;
+    case dxbc::RootParameterType::DescriptorTable:
+      uint32_t NumRanges =
+          support::endian::read<uint32_t, llvm::endianness::little>(
+              PartData.begin() + Header.ParameterOffset);
+      if (Version == 1)
+        DataSize = sizeof(dxbc::RST0::v0::DescriptorRange) * NumRanges +
+                   2 * sizeof(uint32_t);
+      else
+        DataSize = sizeof(dxbc::RST0::v1::DescriptorRange) * NumRanges +
+                   2 * sizeof(uint32_t);
+      break;
     }
     size_t EndOfSectionByte = getNumStaticSamplers() == 0
                                   ? PartData.size()
diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index 8bb9da7884bed..9cf0f8df1debf 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -15,6 +15,8 @@
 #ifndef LLVM_OBJECTYAML_DXCONTAINERYAML_H
 #define LLVM_OBJECTYAML_DXCONTAINERYAML_H
 
+#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Object/DXContainer.h"
@@ -91,6 +93,25 @@ struct RootDescriptorYaml {
 #include "llvm/BinaryFormat/DXContainerConstants.def"
 };
 
+struct DescriptorRangeYaml {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  int32_t OffsetInDescriptorsFromTableStart;
+
+  uint32_t getEncodedFlags() const;
+
+#define DESCRIPTOR_RANGE_FLAG(Num, Val) bool Val = false;
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+};
+
+struct DescriptorTableYaml {
+  uint32_t NumRanges;
+  uint32_t RangesOffset;
+  SmallVector<DescriptorRangeYaml> Ranges;
+};
+
 struct RootParameterYamlDesc {
   uint32_t Type;
   uint32_t Visibility;
@@ -107,13 +128,82 @@ struct RootParameterYamlDesc {
     case llvm::to_underlying(dxbc::RootParameterType::UAV):
       Descriptor = RootDescriptorYaml();
       break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table = DescriptorTableYaml();
+      break;
+    }
+  }
+
+  ~RootParameterYamlDesc() {
+    switch (Type) {
+
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      Constants.~RootConstantsYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      Descriptor.~RootDescriptorYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table.~DescriptorTableYaml();
+      break;
     }
   }
 
+  RootParameterYamlDesc(const RootParameterYamlDesc &Other)
+      : Type(Other.Type), Visibility(Other.Visibility), Offset(Other.Offset) {
+    // Initialize the appropriate union member based on Type
+    switch (Type) {
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      // Placement new to construct the union member
+      new (&Constants) RootConstantsYaml(Other.Constants);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      new (&Table) DescriptorTableYaml(Other.Table);
+      break;
+    }
+  }
+
+  RootParameterYamlDesc &operator=(const RootParameterYamlDesc &Other) {
+    if (this != &Other) {
+      // First, destroy the current union member
+      this->~RootParameterYamlDesc();
+
+      // Copy the basic members
+      Type = Other.Type;
+      Visibility = Other.Visibility;
+      Offset = Other.Offset;
+
+      // Initialize the new union member based on the Type from 'other'
+      switch (Type) {
+      case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+        new (&Constants) RootConstantsYaml(Other.Constants);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::CBV):
+      case llvm::to_underlying(dxbc::RootParameterType::SRV):
+      case llvm::to_underlying(dxbc::RootParameterType::UAV):
+        new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+        new (&Table) DescriptorTableYaml(Other.Table);
+        break;
+      }
+    }
+    return *this;
+  }
+
+  // ToDo: Fix this (Already have a follow up PR with it)
   union {
     RootConstantsYaml Constants;
     RootDescriptorYaml Descriptor;
   };
+  DescriptorTableYaml Table;
 };
 
 struct RootSignatureYamlDesc {
@@ -244,6 +334,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureElement)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::PSVInfo::MaskVector)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureParameter)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::RootParameterYamlDesc)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::DescriptorRangeYaml)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::SemanticKind)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::ComponentType)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::InterpolationMode)
@@ -328,6 +419,14 @@ template <> struct MappingTraits<llvm::DXContainerYAML::RootDescriptorYaml> {
   static void mapping(IO &IO, llvm::DXContainerYAML::RootDescriptorYaml &D);
 };
 
+template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorTableYaml> {
+  static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorTableYaml &D);
+};
+
+template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorRangeYaml> {
+  static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorRangeYaml &D);
+};
+
 } // namespace yaml
 
 } // namespace llvm
diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp
index 641c2f5fa1b1b..4c725969e63cf 100644
--- a/llvm/lib/MC/DXContainerRootSignature.cpp
+++ b/llvm/lib/MC/DXContainerRootSignature.cpp
@@ -10,11 +10,43 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Support/EndianStream.h"
+#include <cstdint>
 #include <variant>
 
 using namespace llvm;
 using namespace llvm::mcdxbc;
 
+class SizeCalculatorVisitor {
+public:
+  SizeCalculatorVisitor(uint32_t Version, size_t &SizeRef)
+      : Size(SizeRef), Version(Version) {}
+
+  void operator()(const dxbc::RootConstants *Value) const {
+    Size += sizeof(dxbc::RootConstants);
+  }
+
+  void operator()(const dxbc::RST0::v0::RootDescriptor *Value) const {
+    Size += sizeof(dxbc::RST0::v0::RootDescriptor);
+  }
+
+  void operator()(const dxbc::RST0::v1::RootDescriptor *Value) const {
+    Size += sizeof(dxbc::RST0::v1::RootDescriptor);
+  }
+
+  void operator()(const DescriptorTable *Value) const {
+    if (Version == 1)
+      Size +=
+          sizeof(dxbc::RST0::v0::DescriptorRange) * Value->Ranges.size() + 8;
+    else
+      Size +=
+          sizeof(dxbc::RST0::v1::DescriptorRange) * Value->Ranges.size() + 8;
+  }
+
+private:
+  size_t &Size;
+  uint32_t Version;
+};
+
 static uint32_t writePlaceholder(raw_svector_ostream &Stream) {
   const uint32_t DummyValue = std::numeric_limits<uint32_t>::max();
   uint32_t Offset = Stream.tell();
@@ -38,12 +70,8 @@ size_t RootSignatureDesc::getSize() const {
     std::optional<ParametersView> P = ParametersContainer.getParameter(&I);
     if (!P)
       continue;
-    std::visit(
-        [&Size](auto &Value) -> void {
-          using T = std::decay_t<decltype(*Value)>;
-          Size += sizeof(T);
-        },
-        *P);
+
+    std::visit(SizeCalculatorVisitor(Version, Size), *P);
   }
 
   return Size;
@@ -106,6 +134,44 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
       support::endian::write(BOS, Descriptor->RegisterSpace,
                              llvm::endianness::little);
       support::endian::write(BOS, Descriptor->Flags, llvm::endianness::little);
+    } else if (std::holds_alternative<const DescriptorTable *>(P.value())) {
+      auto *Table = std::get<const DescriptorTable *>(P.value());
+
+      support::endian::write(BOS, (uint32_t)Table->Ranges.size(),
+                             llvm::endianness::little);
+      rewriteOffsetToCurrentByte(BOS, writePlaceholder(BOS));
+      for (const auto &R : *Table) {
+        if (std::holds_alternative<dxbc::RST0::v0::DescriptorRange>(R)) {
+          auto Range = std::get<dxbc::RST0::v0::DescriptorRange>(R);
+
+          support::endian::write(BOS, Range.RangeType,
+                                 llvm::endianness::little);
+          support::endian::write(BOS, Range.NumDescriptors,
+                                 llvm::endianness::little);
+          support::endian::write(BOS, Range.BaseShaderRegister,
+                                 llvm::endianness::little);
+          support::endian::write(BOS, Range.RegisterSpace,
+                                 llvm::endianness::little);
+          support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart,
+                                 llvm::endianness::little);
+        } else {
+          if (std::holds_alternative<dxbc::RST0::v1::DescriptorRange>(R)) {
+            auto Range = std::get<dxbc::RST0::v1::DescriptorRange>(R);
+
+            support::endian::write(BOS, Range.RangeType,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.NumDescriptors,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.BaseShaderRegister,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.RegisterSpace,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.Flags, llvm::endianness::little);
+          }
+        }
+      }
     }
   }
   assert(Storage.size() == getSize());
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index b8ea1b048edfe..6336a42c8e4ae 100644
--- a/llv...
[truncated]

``````````

</details>

author_association: MEMBER
user: login: llvmbot
created_at: 2025-05-02T18:01:26Z
body: 
<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-directx

Author: None (joaosaffran)

<details>
<summary>Changes</summary>

Closes: https://github.com/orgs/llvm/projects/4/views/22?sliceBy%5Bvalue%5D=joaosaffran&amp;pane=issue&amp;itemId=97332852&amp;issue=llvm%7Cllvm-project%7C126635

---

Patch is 45.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138315.diff


13 Files Affected:

- (modified) llvm/include/llvm/BinaryFormat/DXContainer.h (+35) 
- (modified) llvm/include/llvm/BinaryFormat/DXContainerConstants.def (+24-1) 
- (modified) llvm/include/llvm/MC/DXContainerRootSignature.h (+27-5) 
- (modified) llvm/include/llvm/Object/DXContainer.h (+66-3) 
- (modified) llvm/include/llvm/ObjectYAML/DXContainerYAML.h (+99) 
- (modified) llvm/lib/MC/DXContainerRootSignature.cpp (+72-6) 
- (modified) llvm/lib/ObjectYAML/DXContainerEmitter.cpp (+27) 
- (modified) llvm/lib/ObjectYAML/DXContainerYAML.cpp (+81) 
- (added) llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.0.yaml (+57) 
- (added) llvm/test/ObjectYAML/DXContainer/RootSignature-DescriptorTable1.1.yaml (+59) 
- (modified) llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml (+53-30) 
- (modified) llvm/unittests/Object/DXContainerTest.cpp (+107) 
- (modified) llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp (+113) 


``````````diff
diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h
index 3dbcfa82f3d7c..a441fa3a36886 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainer.h
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -163,6 +163,11 @@ enum class RootDescriptorFlag : uint32_t {
 #include "DXContainerConstants.def"
 };
 
+#define DESCRIPTOR_RANGE_FLAG(Num, Val) Val = 1ull << Num,
+enum class DescriptorRangeFlag : uint32_t {
+#include "DXContainerConstants.def"
+};
+
 #define ROOT_PARAMETER(Val, Enum) Enum = Val,
 enum class RootParameterType : uint32_t {
 #include "DXContainerConstants.def"
@@ -170,6 +175,13 @@ enum class RootParameterType : uint32_t {
 
 ArrayRef<EnumEntry<RootParameterType>> getRootParameterTypes();
 
+#define DESCRIPTOR_RANGE(Val, Enum) Enum = Val,
+enum class DescriptorRangeType : uint32_t {
+#include "DXContainerConstants.def"
+};
+
+ArrayRef<EnumEntry<DescriptorRangeType>> getDescriptorRangeTypes();
+
 #define ROOT_PARAMETER(Val, Enum)                                              \
   case Val:                                                                    \
     return true;
@@ -595,6 +607,21 @@ struct RootDescriptor {
     sys::swapByteOrder(RegisterSpace);
   }
 };
+
+struct DescriptorRange {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  int32_t OffsetInDescriptorsFromTableStart;
+  void swapBytes() {
+    sys::swapByteOrder(RangeType);
+    sys::swapByteOrder(NumDescriptors);
+    sys::swapByteOrder(BaseShaderRegister);
+    sys::swapByteOrder(RegisterSpace);
+    sys::swapByteOrder(OffsetInDescriptorsFromTableStart);
+  }
+};
 } // namespace v0
 
 namespace v1 {
@@ -605,6 +632,14 @@ struct RootDescriptor : public v0::RootDescriptor {
     sys::swapByteOrder(Flags);
   }
 };
+
+struct DescriptorRange : public v0::DescriptorRange {
+  uint32_t Flags;
+  void swapBytes() {
+    v0::DescriptorRange::swapBytes();
+    sys::swapByteOrder(Flags);
+  }
+};
 } // namespace v1
 } // namespace RST0
 // following dx12 naming
diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
index bd9bd760547dc..5fe7e7c321a33 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
+++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
@@ -73,7 +73,7 @@ ROOT_ELEMENT_FLAG(11, SamplerHeapDirectlyIndexed)
 #endif // ROOT_ELEMENT_FLAG
 
  
-// ROOT_ELEMENT_FLAG(bit offset for the flag, name).
+// ROOT_DESCRIPTOR_FLAG(bit offset for the flag, name).
 #ifdef ROOT_DESCRIPTOR_FLAG
 
 ROOT_DESCRIPTOR_FLAG(0, NONE)
@@ -84,8 +84,21 @@ ROOT_DESCRIPTOR_FLAG(3, DATA_STATIC)
 #endif // ROOT_DESCRIPTOR_FLAG
 
 
+// DESCRIPTOR_RANGE_FLAG(bit offset for the flag, name).
+#ifdef DESCRIPTOR_RANGE_FLAG
+
+DESCRIPTOR_RANGE_FLAG(0, NONE)
+DESCRIPTOR_RANGE_FLAG(1, DESCRIPTORS_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(2, DATA_VOLATILE)
+DESCRIPTOR_RANGE_FLAG(3, DATA_STATIC_WHILE_SET_AT_EXECUTE)
+DESCRIPTOR_RANGE_FLAG(4, DATA_STATIC)
+DESCRIPTOR_RANGE_FLAG(16, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS)
+#undef DESCRIPTOR_RANGE_FLAG
+#endif // DESCRIPTOR_RANGE_FLAG
+
 #ifdef ROOT_PARAMETER
 
+ROOT_PARAMETER(0, DescriptorTable)
 ROOT_PARAMETER(1, Constants32Bit)
 ROOT_PARAMETER(2, CBV)
 ROOT_PARAMETER(3, SRV)
@@ -93,6 +106,16 @@ ROOT_PARAMETER(4, UAV)
 #undef ROOT_PARAMETER
 #endif // ROOT_PARAMETER
 
+
+#ifdef DESCRIPTOR_RANGE
+
+DESCRIPTOR_RANGE(0, SRV)
+DESCRIPTOR_RANGE(1, UAV)
+DESCRIPTOR_RANGE(2, CBV)
+DESCRIPTOR_RANGE(3, Sampler)
+#undef DESCRIPTOR_RANGE
+#endif // DESCRIPTOR_RANGE
+
 #ifdef SHADER_VISIBILITY
 
 SHADER_VISIBILITY(0, All)
diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h
index c8af613a57094..3f5960a6de2f9 100644
--- a/llvm/include/llvm/MC/DXContainerRootSignature.h
+++ b/llvm/include/llvm/MC/DXContainerRootSignature.h
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include <cstddef>
 #include <cstdint>
@@ -28,17 +29,30 @@ struct RootParameterInfo {
   RootParameterInfo(dxbc::RootParameterHeader H, size_t L)
       : Header(H), Location(L) {}
 };
+using DescriptorRanges = std::variant<dxbc::RST0::v0::DescriptorRange,
+                                      dxbc::RST0::v1::DescriptorRange>;
+struct DescriptorTable {
+  SmallVector<DescriptorRanges> Ranges;
+
+  SmallVector<DescriptorRanges>::const_iterator begin() const {
+    return Ranges.begin();
+  }
+  SmallVector<DescriptorRanges>::const_iterator end() const {
+    return Ranges.end();
+  }
+};
 
 using RootDescriptor = std::variant<dxbc::RST0::v0::RootDescriptor,
                                     dxbc::RST0::v1::RootDescriptor>;
-using ParametersView = std::variant<const dxbc::RootConstants *,
-                                    const dxbc::RST0::v0::RootDescriptor *,
-                                    const dxbc::RST0::v1::RootDescriptor *>;
+
+using ParametersView = std::variant<
+    const dxbc::RootConstants *, const dxbc::RST0::v0::RootDescriptor *,
+    const dxbc::RST0::v1::RootDescriptor *, const DescriptorTable *>;
 struct RootParametersContainer {
   SmallVector<RootParameterInfo> ParametersInfo;
-
   SmallVector<dxbc::RootConstants> Constants;
   SmallVector<RootDescriptor> Descriptors;
+  SmallVector<DescriptorTable> Tables;
 
   void addInfo(dxbc::RootParameterHeader H, size_t L) {
     ParametersInfo.push_back(RootParameterInfo(H, L));
@@ -61,13 +75,18 @@ struct RootParametersContainer {
     Descriptors.push_back(D);
   }
 
+  void addParameter(dxbc::RootParameterHeader H, DescriptorTable D) {
+    addInfo(H, Tables.size());
+    Tables.push_back(D);
+  }
+
   std::optional<ParametersView> getParameter(const RootParameterInfo *H) const {
     switch (H->Header.ParameterType) {
     case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
       return &Constants[H->Location];
     case llvm::to_underlying(dxbc::RootParameterType::CBV):
     case llvm::to_underlying(dxbc::RootParameterType::SRV):
-    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV): {
       const RootDescriptor &VersionedParam = Descriptors[H->Location];
       if (std::holds_alternative<dxbc::RST0::v0::RootDescriptor>(
               VersionedParam)) {
@@ -75,6 +94,9 @@ struct RootParametersContainer {
       }
       return &std::get<dxbc::RST0::v1::RootDescriptor>(VersionedParam);
     }
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      return &Tables[H->Location];
+    }
 
     return std::nullopt;
   }
diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h
index e359d85f08bec..c6c22213d7de8 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -19,11 +19,11 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Object/Error.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/TargetParser/Triple.h"
-#include <array>
-#include <cstddef>
 #include <variant>
 
 namespace llvm {
@@ -39,6 +39,7 @@ template <typename T>
 std::enable_if_t<std::is_class<T>::value, void> swapBytes(T &value) {
   value.swapBytes();
 }
+
 } // namespace detail
 
 // This class provides a view into the underlying resource array. The Resource
@@ -121,8 +122,10 @@ namespace DirectX {
 struct RootParameterView {
   const dxbc::RootParameterHeader &Header;
   StringRef ParamData;
+  uint32_t Version;
+
   RootParameterView(uint32_t V, const dxbc::RootParameterHeader &H, StringRef P)
-      : Header(H), ParamData(P) {}
+      : Header(H), ParamData(P), Version(V) {}
 
   template <typename T, typename VersionT = T> Expected<T> readParameter() {
     assert(sizeof(VersionT) <= sizeof(T) &&
@@ -169,6 +172,55 @@ struct RootDescriptorView : RootParameterView {
     return readParameter<dxbc::RST0::v1::RootDescriptor>();
   }
 };
+template <typename T> struct DescriptorTable {
+  uint32_t NumRanges;
+  uint32_t RangesOffset;
+  ViewArray<T> Ranges;
+
+  typename ViewArray<T>::iterator begin() const { return Ranges.begin(); }
+
+  typename ViewArray<T>::iterator end() const { return Ranges.end(); }
+};
+template <typename T> struct TemplateTypeToVersion {
+  // Default version
+  static constexpr uint32_t Value = -1;
+};
+
+template <> struct TemplateTypeToVersion<dxbc::RST0::v0::DescriptorRange> {
+  static constexpr uint32_t Value = 1;
+};
+
+template <> struct TemplateTypeToVersion<dxbc::RST0::v1::DescriptorRange> {
+  static constexpr uint32_t Value = 2;
+};
+
+template <typename T> struct DescriptorTableView : RootParameterView {
+  using TemplateType = T;
+
+  static bool classof(const RootParameterView *V) {
+    return (V->Header.ParameterType ==
+            llvm::to_underlying(dxbc::RootParameterType::DescriptorTable)) &&
+           (V->Version == TemplateTypeToVersion<T>::Value);
+  }
+
+  // Define a type alias to access the template parameter from inside classof
+  llvm::Expected<DescriptorTable<T>> read() {
+    const char *Current = ParamData.begin();
+    DescriptorTable<T> Table;
+
+    Table.NumRanges =
+        support::endian::read<uint32_t, llvm::endianness::little>(Current);
+    Current += sizeof(uint32_t);
+
+    Table.RangesOffset =
+        support::endian::read<uint32_t, llvm::endianness::little>(Current);
+    Current += sizeof(uint32_t);
+
+    Table.Ranges.Data =
+        ParamData.substr(2 * sizeof(uint32_t), Table.NumRanges * sizeof(T));
+    return Table;
+  }
+};
 
 static Error parseFailed(const Twine &Msg) {
   return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);
@@ -221,6 +273,17 @@ class RootSignature {
       else
         DataSize = sizeof(dxbc::RST0::v1::RootDescriptor);
       break;
+    case dxbc::RootParameterType::DescriptorTable:
+      uint32_t NumRanges =
+          support::endian::read<uint32_t, llvm::endianness::little>(
+              PartData.begin() + Header.ParameterOffset);
+      if (Version == 1)
+        DataSize = sizeof(dxbc::RST0::v0::DescriptorRange) * NumRanges +
+                   2 * sizeof(uint32_t);
+      else
+        DataSize = sizeof(dxbc::RST0::v1::DescriptorRange) * NumRanges +
+                   2 * sizeof(uint32_t);
+      break;
     }
     size_t EndOfSectionByte = getNumStaticSamplers() == 0
                                   ? PartData.size()
diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index 8bb9da7884bed..9cf0f8df1debf 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -15,6 +15,8 @@
 #ifndef LLVM_OBJECTYAML_DXCONTAINERYAML_H
 #define LLVM_OBJECTYAML_DXCONTAINERYAML_H
 
+#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Object/DXContainer.h"
@@ -91,6 +93,25 @@ struct RootDescriptorYaml {
 #include "llvm/BinaryFormat/DXContainerConstants.def"
 };
 
+struct DescriptorRangeYaml {
+  uint32_t RangeType;
+  uint32_t NumDescriptors;
+  uint32_t BaseShaderRegister;
+  uint32_t RegisterSpace;
+  int32_t OffsetInDescriptorsFromTableStart;
+
+  uint32_t getEncodedFlags() const;
+
+#define DESCRIPTOR_RANGE_FLAG(Num, Val) bool Val = false;
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+};
+
+struct DescriptorTableYaml {
+  uint32_t NumRanges;
+  uint32_t RangesOffset;
+  SmallVector<DescriptorRangeYaml> Ranges;
+};
+
 struct RootParameterYamlDesc {
   uint32_t Type;
   uint32_t Visibility;
@@ -107,13 +128,82 @@ struct RootParameterYamlDesc {
     case llvm::to_underlying(dxbc::RootParameterType::UAV):
       Descriptor = RootDescriptorYaml();
       break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table = DescriptorTableYaml();
+      break;
+    }
+  }
+
+  ~RootParameterYamlDesc() {
+    switch (Type) {
+
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      Constants.~RootConstantsYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      Descriptor.~RootDescriptorYaml();
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      Table.~DescriptorTableYaml();
+      break;
     }
   }
 
+  RootParameterYamlDesc(const RootParameterYamlDesc &Other)
+      : Type(Other.Type), Visibility(Other.Visibility), Offset(Other.Offset) {
+    // Initialize the appropriate union member based on Type
+    switch (Type) {
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      // Placement new to construct the union member
+      new (&Constants) RootConstantsYaml(Other.Constants);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::CBV):
+    case llvm::to_underlying(dxbc::RootParameterType::SRV):
+    case llvm::to_underlying(dxbc::RootParameterType::UAV):
+      new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+      break;
+    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+      new (&Table) DescriptorTableYaml(Other.Table);
+      break;
+    }
+  }
+
+  RootParameterYamlDesc &operator=(const RootParameterYamlDesc &Other) {
+    if (this != &Other) {
+      // First, destroy the current union member
+      this->~RootParameterYamlDesc();
+
+      // Copy the basic members
+      Type = Other.Type;
+      Visibility = Other.Visibility;
+      Offset = Other.Offset;
+
+      // Initialize the new union member based on the Type from 'other'
+      switch (Type) {
+      case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+        new (&Constants) RootConstantsYaml(Other.Constants);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::CBV):
+      case llvm::to_underlying(dxbc::RootParameterType::SRV):
+      case llvm::to_underlying(dxbc::RootParameterType::UAV):
+        new (&Descriptor) RootDescriptorYaml(Other.Descriptor);
+        break;
+      case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
+        new (&Table) DescriptorTableYaml(Other.Table);
+        break;
+      }
+    }
+    return *this;
+  }
+
+  // ToDo: Fix this (Already have a follow up PR with it)
   union {
     RootConstantsYaml Constants;
     RootDescriptorYaml Descriptor;
   };
+  DescriptorTableYaml Table;
 };
 
 struct RootSignatureYamlDesc {
@@ -244,6 +334,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureElement)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::PSVInfo::MaskVector)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureParameter)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::RootParameterYamlDesc)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::DescriptorRangeYaml)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::SemanticKind)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::ComponentType)
 LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::InterpolationMode)
@@ -328,6 +419,14 @@ template <> struct MappingTraits<llvm::DXContainerYAML::RootDescriptorYaml> {
   static void mapping(IO &IO, llvm::DXContainerYAML::RootDescriptorYaml &D);
 };
 
+template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorTableYaml> {
+  static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorTableYaml &D);
+};
+
+template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorRangeYaml> {
+  static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorRangeYaml &D);
+};
+
 } // namespace yaml
 
 } // namespace llvm
diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp
index 641c2f5fa1b1b..4c725969e63cf 100644
--- a/llvm/lib/MC/DXContainerRootSignature.cpp
+++ b/llvm/lib/MC/DXContainerRootSignature.cpp
@@ -10,11 +10,43 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/BinaryFormat/DXContainer.h"
 #include "llvm/Support/EndianStream.h"
+#include <cstdint>
 #include <variant>
 
 using namespace llvm;
 using namespace llvm::mcdxbc;
 
+class SizeCalculatorVisitor {
+public:
+  SizeCalculatorVisitor(uint32_t Version, size_t &SizeRef)
+      : Size(SizeRef), Version(Version) {}
+
+  void operator()(const dxbc::RootConstants *Value) const {
+    Size += sizeof(dxbc::RootConstants);
+  }
+
+  void operator()(const dxbc::RST0::v0::RootDescriptor *Value) const {
+    Size += sizeof(dxbc::RST0::v0::RootDescriptor);
+  }
+
+  void operator()(const dxbc::RST0::v1::RootDescriptor *Value) const {
+    Size += sizeof(dxbc::RST0::v1::RootDescriptor);
+  }
+
+  void operator()(const DescriptorTable *Value) const {
+    if (Version == 1)
+      Size +=
+          sizeof(dxbc::RST0::v0::DescriptorRange) * Value->Ranges.size() + 8;
+    else
+      Size +=
+          sizeof(dxbc::RST0::v1::DescriptorRange) * Value->Ranges.size() + 8;
+  }
+
+private:
+  size_t &Size;
+  uint32_t Version;
+};
+
 static uint32_t writePlaceholder(raw_svector_ostream &Stream) {
   const uint32_t DummyValue = std::numeric_limits<uint32_t>::max();
   uint32_t Offset = Stream.tell();
@@ -38,12 +70,8 @@ size_t RootSignatureDesc::getSize() const {
     std::optional<ParametersView> P = ParametersContainer.getParameter(&I);
     if (!P)
       continue;
-    std::visit(
-        [&Size](auto &Value) -> void {
-          using T = std::decay_t<decltype(*Value)>;
-          Size += sizeof(T);
-        },
-        *P);
+
+    std::visit(SizeCalculatorVisitor(Version, Size), *P);
   }
 
   return Size;
@@ -106,6 +134,44 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
       support::endian::write(BOS, Descriptor->RegisterSpace,
                              llvm::endianness::little);
       support::endian::write(BOS, Descriptor->Flags, llvm::endianness::little);
+    } else if (std::holds_alternative<const DescriptorTable *>(P.value())) {
+      auto *Table = std::get<const DescriptorTable *>(P.value());
+
+      support::endian::write(BOS, (uint32_t)Table->Ranges.size(),
+                             llvm::endianness::little);
+      rewriteOffsetToCurrentByte(BOS, writePlaceholder(BOS));
+      for (const auto &R : *Table) {
+        if (std::holds_alternative<dxbc::RST0::v0::DescriptorRange>(R)) {
+          auto Range = std::get<dxbc::RST0::v0::DescriptorRange>(R);
+
+          support::endian::write(BOS, Range.RangeType,
+                                 llvm::endianness::little);
+          support::endian::write(BOS, Range.NumDescriptors,
+                                 llvm::endianness::little);
+          support::endian::write(BOS, Range.BaseShaderRegister,
+                                 llvm::endianness::little);
+          support::endian::write(BOS, Range.RegisterSpace,
+                                 llvm::endianness::little);
+          support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart,
+                                 llvm::endianness::little);
+        } else {
+          if (std::holds_alternative<dxbc::RST0::v1::DescriptorRange>(R)) {
+            auto Range = std::get<dxbc::RST0::v1::DescriptorRange>(R);
+
+            support::endian::write(BOS, Range.RangeType,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.NumDescriptors,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.BaseShaderRegister,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.RegisterSpace,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart,
+                                   llvm::endianness::little);
+            support::endian::write(BOS, Range.Flags, llvm::endianness::little);
+          }
+        }
+      }
     }
   }
   assert(Storage.size() == getSize());
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index b8ea1b048edfe..6336a42c8e4ae 100644
--- a/llv...
[truncated]

``````````

</details>

author_association: MEMBER
user: login: github-actions[bot]
created_at: 2025-05-16T06:45:26Z
body: <!--LLVM CODE FORMAT COMMENT: {clang-format}-->

:white_check_mark: With the latest revision this PR passed the C/C++ code formatter.
author_association: NONE