Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[DirectX] adding support to read/write descriptor table data using obj2yaml/yaml2obj #138315

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 70 commits into from
May 29, 2025

Conversation

joaosaffran
Copy link
Contributor

Closes: #126635

@joaosaffran joaosaffran marked this pull request as ready for review May 2, 2025 18:00
@llvmbot
Copy link
Member

llvmbot commented May 2, 2025

@llvm/pr-subscribers-objectyaml
@llvm/pr-subscribers-llvm-binary-utilities

@llvm/pr-subscribers-mc

Author: None (joaosaffran)

Changes

Closes: #126635


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 --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]

@llvmbot
Copy link
Member

llvmbot commented May 2, 2025

@llvm/pr-subscribers-backend-directx

Author: None (joaosaffran)

Changes

Closes: #126635


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 --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]

@joaosaffran joaosaffran requested a review from llvm-beanz May 28, 2025 19:51
@joaosaffran joaosaffran merged commit 8e19573 into llvm:main May 29, 2025
9 of 10 checks passed
google-yfyang pushed a commit to google-yfyang/llvm-project that referenced this pull request May 29, 2025
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Jun 3, 2025
Comment on lines +92 to +97
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)
Copy link
Contributor

Choose a reason for hiding this comment

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

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, will fix that

Copy link
Contributor

Choose a reason for hiding this comment

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

As noted here: #143041 (review).

Maybe reusing the values will address this as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fix PR: #143201

joaosaffran added a commit that referenced this pull request Jun 17, 2025
Update the descriptor range flag values in DXContainerConstants.def to
match
the Direct3D12 specification. This changes two aspects:

1. Modify the DESCRIPTOR_RANGE_FLAG macro to use direct values instead
of
   bit shifts
2. Update the flag values to use hex notation and match D3D12's
   D3D12_DESCRIPTOR_RANGE_FLAGS enumeration:
   - DESCRIPTORS_VOLATILE: 0x1
   - DATA_VOLATILE: 0x2
   - DATA_STATIC_WHILE_SET_AT_EXECUTE: 0x4
   - DATA_STATIC: 0x8
   - DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: 0x10000
3. Removed NONE value from ROOT_DESCRIPTOR_FLAG

This ensures better compatibility with the D3D12 API and makes the
values
more explicit in the code.

Requested here:
#138315 (comment)

---------

Co-authored-by: joaosaffran <joao.saffran@microsoft.com>
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Jun 17, 2025
…201)

Update the descriptor range flag values in DXContainerConstants.def to
match
the Direct3D12 specification. This changes two aspects:

1. Modify the DESCRIPTOR_RANGE_FLAG macro to use direct values instead
of
   bit shifts
2. Update the flag values to use hex notation and match D3D12's
   D3D12_DESCRIPTOR_RANGE_FLAGS enumeration:
   - DESCRIPTORS_VOLATILE: 0x1
   - DATA_VOLATILE: 0x2
   - DATA_STATIC_WHILE_SET_AT_EXECUTE: 0x4
   - DATA_STATIC: 0x8
   - DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: 0x10000
3. Removed NONE value from ROOT_DESCRIPTOR_FLAG

This ensures better compatibility with the D3D12 API and makes the
values
more explicit in the code.

Requested here:
llvm/llvm-project#138315 (comment)

---------

Co-authored-by: joaosaffran <joao.saffran@microsoft.com>
fschlimb pushed a commit to fschlimb/llvm-project that referenced this pull request Jun 18, 2025
Update the descriptor range flag values in DXContainerConstants.def to
match
the Direct3D12 specification. This changes two aspects:

1. Modify the DESCRIPTOR_RANGE_FLAG macro to use direct values instead
of
   bit shifts
2. Update the flag values to use hex notation and match D3D12's
   D3D12_DESCRIPTOR_RANGE_FLAGS enumeration:
   - DESCRIPTORS_VOLATILE: 0x1
   - DATA_VOLATILE: 0x2
   - DATA_STATIC_WHILE_SET_AT_EXECUTE: 0x4
   - DATA_STATIC: 0x8
   - DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: 0x10000
3. Removed NONE value from ROOT_DESCRIPTOR_FLAG

This ensures better compatibility with the D3D12 API and makes the
values
more explicit in the code.

Requested here:
llvm#138315 (comment)

---------

Co-authored-by: joaosaffran <joao.saffran@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[DirectX] Add Descriptor Table element support to obj2yaml/yaml2obj
5 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.