Skip to content

Navigation Menu

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

Open
wants to merge 40 commits into
base: main
Choose a base branch
Loading
from

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 linked an issue May 14, 2025 that may be closed by this pull request
8 tasks
@joaosaffran joaosaffran marked this pull request as draft May 15, 2025 20:12
@joaosaffran joaosaffran changed the base branch from users/joaosaffran/137284 to main May 16, 2025 06:44
Copy link

github-actions bot commented May 16, 2025

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff HEAD~1 HEAD --extensions cpp,h -- llvm/include/llvm/BinaryFormat/DXContainer.h llvm/include/llvm/MC/DXContainerRootSignature.h llvm/include/llvm/Object/DXContainer.h llvm/include/llvm/ObjectYAML/DXContainerYAML.h llvm/lib/MC/DXContainerRootSignature.cpp llvm/lib/ObjectYAML/DXContainerEmitter.cpp llvm/lib/ObjectYAML/DXContainerYAML.cpp llvm/unittests/Object/DXContainerTest.cpp llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
View the diff from clang-format here.
diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h
index 5abcf1710..dc396acde 100644
--- a/llvm/include/llvm/MC/DXContainerRootSignature.h
+++ b/llvm/include/llvm/MC/DXContainerRootSignature.h
@@ -28,7 +28,6 @@ struct RootParameterInfo {
       : Header(Header), Location(Location) {}
 };
 
-
 struct DescriptorTable {
   SmallVector<dxbc::RTS0::v2::DescriptorRange> Ranges;
 
@@ -40,8 +39,6 @@ struct DescriptorTable {
   }
 };
 
-
-
 struct RootParametersContainer {
   SmallVector<RootParameterInfo> ParametersInfo;
   SmallVector<dxbc::RootConstants> Constants;
@@ -91,7 +88,7 @@ struct RootParametersContainer {
   const dxbc::RTS0::v2::RootDescriptor &getRootDescriptor(size_t Index) const {
     return Descriptors[Index];
   }
-   const DescriptorTable &getDescriptorTable(size_t Index) const {
+  const DescriptorTable &getDescriptorTable(size_t Index) const {
     return Tables[Index];
   }
 
diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h
index 890871964..3f15eb1a4 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -183,9 +183,13 @@ struct DescriptorTable {
   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 begin() const {
+    return Ranges.begin();
+  }
 
-  typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator end() const { return Ranges.end(); }
+  typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator end() const {
+    return Ranges.end();
+  }
 };
 
 struct DescriptorTableView : RootParameterView {
@@ -208,7 +212,7 @@ struct DescriptorTableView : RootParameterView {
     Current += sizeof(uint32_t);
 
     size_t RangeSize = sizeof(dxbc::RTS0::v1::DescriptorRange);
-    if(Version > 1)
+    if (Version > 1)
       RangeSize = sizeof(dxbc::RTS0::v2::DescriptorRange);
 
     Table.Ranges.Stride = RangeSize;
diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp
index 116ada468..dde7ecfb7 100644
--- a/llvm/lib/MC/DXContainerRootSignature.cpp
+++ b/llvm/lib/MC/DXContainerRootSignature.cpp
@@ -48,15 +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;
-    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;
+      break;
     }
   }
   return Size;
@@ -100,8 +101,7 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
                              llvm::endianness::little);
       support::endian::write(BOS, Constants.Num32BitValues,
                              llvm::endianness::little);
-                            }
-                            break;
+    } break;
     case llvm::to_underlying(dxbc::RootParameterType::CBV):
     case llvm::to_underlying(dxbc::RootParameterType::SRV):
     case llvm::to_underlying(dxbc::RootParameterType::UAV): {
@@ -114,29 +114,26 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
                              llvm::endianness::little);
       if (Version > 1)
         support::endian::write(BOS, Descriptor.Flags, llvm::endianness::little);
-    }
-    break;
-    case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):{
+    } 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);
-          }
+        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;
     }
   }
diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index 13ee8758e..8b1b61b88 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -300,16 +300,16 @@ void DXContainerWriter::writeParts(raw_ostream &OS) {
           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);
+            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;
diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index 64c9335ca..cccd5ea49 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -95,8 +95,10 @@ DXContainerYAML::RootSignatureYamlDesc::create(
        llvm::to_underlying(dxbc::RootDescriptorFlag::Val)) > 0;
 #include "llvm/BinaryFormat/DXContainerConstants.def"
       }
-    } else if (auto *TDV = dyn_cast<object::DirectX::DescriptorTableView>(&ParamView)) {
-      llvm::Expected<object::DirectX::DescriptorTable>TableOrErr = TDV->read(Version);
+    } else if (auto *TDV =
+                   dyn_cast<object::DirectX::DescriptorTableView>(&ParamView)) {
+      llvm::Expected<object::DirectX::DescriptorTable> TableOrErr =
+          TDV->read(Version);
       if (Error E = TableOrErr.takeError())
         return std::move(E);
       auto Table = *TableOrErr;
@@ -119,8 +121,8 @@ DXContainerYAML::RootSignatureYamlDesc::create(
 #include "llvm/BinaryFormat/DXContainerConstants.def"
         }
         NewP.Table.Ranges.push_back(NewR);
+      }
     }
-    } 
 
     RootSigDesc.Parameters.push_back(NewP);
   }
diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp
index d33a4264e..b52e96e9a 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -1086,8 +1086,7 @@ TEST(RootSignature, ParseDescriptorTable) {
     ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());
 
     auto *DescriptorTableView =
-        dyn_cast<DirectX::DescriptorTableView>(
-            &*ParamView);
+        dyn_cast<DirectX::DescriptorTableView>(&*ParamView);
     ASSERT_TRUE(DescriptorTableView != nullptr);
     auto Table = DescriptorTableView->read(2);
 
@@ -1139,8 +1138,7 @@ TEST(RootSignature, ParseDescriptorTable) {
     ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());
 
     auto *DescriptorTableView =
-        dyn_cast<DirectX::DescriptorTableView>(
-            &*ParamView);
+        dyn_cast<DirectX::DescriptorTableView>(&*ParamView);
     ASSERT_TRUE(DescriptorTableView != nullptr);
     auto Table = DescriptorTableView->read(1);
 

@joaosaffran joaosaffran marked this pull request as ready for review May 16, 2025 18:22
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
4 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.