[llvm] 53eae22 - [DirectX] adding support in obj2yaml and yaml2obj to root constants (#127840)

via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 16 18:38:57 PDT 2025


Author: joaosaffran
Date: 2025-04-16T18:38:53-07:00
New Revision: 53eae22e228532fe3349890b6c7fc10b9c10dbee

URL: https://github.com/llvm/llvm-project/commit/53eae22e228532fe3349890b6c7fc10b9c10dbee
DIFF: https://github.com/llvm/llvm-project/commit/53eae22e228532fe3349890b6c7fc10b9c10dbee.diff

LOG: [DirectX] adding support in obj2yaml and yaml2obj to root constants (#127840)

Adding support for Root Constant in MC, Object and obj2yaml and
yaml2obj, this PR adds:
  - new structures to dxbc definition.
  - serialize and desirialize logic from dxcontainer to yaml
  - tests validating against dxc
  - adding support to multiple parts.

Closes: https://github.com/llvm/llvm-project/issues/126633

---------

Co-authored-by: joaosaffran <joao.saffran at microsoft.com>

Added: 
    llvm/test/ObjectYAML/DXContainer/RootSignature-InvalidType.yaml
    llvm/test/ObjectYAML/DXContainer/RootSignature-InvalidVisibility.yaml
    llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml

Modified: 
    llvm/include/llvm/BinaryFormat/DXContainer.h
    llvm/include/llvm/BinaryFormat/DXContainerConstants.def
    llvm/include/llvm/MC/DXContainerRootSignature.h
    llvm/include/llvm/Object/DXContainer.h
    llvm/include/llvm/ObjectYAML/DXContainerYAML.h
    llvm/lib/BinaryFormat/DXContainer.cpp
    llvm/lib/MC/DXContainerRootSignature.cpp
    llvm/lib/Object/DXContainer.cpp
    llvm/lib/ObjectYAML/DXContainerEmitter.cpp
    llvm/lib/ObjectYAML/DXContainerYAML.cpp
    llvm/lib/Target/DirectX/DXILRootSignature.cpp
    llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll
    llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll
    llvm/test/ObjectYAML/DXContainer/RootSignature-Flags.yaml
    llvm/tools/obj2yaml/dxcontainer2yaml.cpp
    llvm/unittests/Object/DXContainerTest.cpp
    llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h
index 28905e27837a7..455657980bf40 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainer.h
+++ b/llvm/include/llvm/BinaryFormat/DXContainer.h
@@ -14,6 +14,7 @@
 #define LLVM_BINARYFORMAT_DXCONTAINER_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/SwapByteOrder.h"
 #include "llvm/TargetParser/Triple.h"
 
@@ -157,6 +158,40 @@ enum class RootElementFlag : uint32_t {
 #include "DXContainerConstants.def"
 };
 
+#define ROOT_PARAMETER(Val, Enum) Enum = Val,
+enum class RootParameterType : uint32_t {
+#include "DXContainerConstants.def"
+};
+
+ArrayRef<EnumEntry<RootParameterType>> getRootParameterTypes();
+
+#define ROOT_PARAMETER(Val, Enum)                                              \
+  case Val:                                                                    \
+    return true;
+inline bool isValidParameterType(uint32_t V) {
+  switch (V) {
+#include "DXContainerConstants.def"
+  }
+  return false;
+}
+
+#define SHADER_VISIBILITY(Val, Enum) Enum = Val,
+enum class ShaderVisibility : uint32_t {
+#include "DXContainerConstants.def"
+};
+
+ArrayRef<EnumEntry<ShaderVisibility>> getShaderVisibility();
+
+#define SHADER_VISIBILITY(Val, Enum)                                           \
+  case Val:                                                                    \
+    return true;
+inline bool isValidShaderVisibility(uint32_t V) {
+  switch (V) {
+#include "DXContainerConstants.def"
+  }
+  return false;
+}
+
 PartType parsePartType(StringRef S);
 
 struct VertexPSVInfo {
@@ -546,15 +581,49 @@ struct ProgramSignatureElement {
 static_assert(sizeof(ProgramSignatureElement) == 32,
               "ProgramSignatureElement is misaligned");
 
-struct RootSignatureValidations {
+// following dx12 naming
+// https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_constants
+struct RootConstants {
+  uint32_t ShaderRegister;
+  uint32_t RegisterSpace;
+  uint32_t Num32BitValues;
+
+  void swapBytes() {
+    sys::swapByteOrder(ShaderRegister);
+    sys::swapByteOrder(RegisterSpace);
+    sys::swapByteOrder(Num32BitValues);
+  }
+};
 
-  static bool isValidRootFlag(uint32_t Flags) { return (Flags & ~0xfff) == 0; }
+struct RootParameterHeader {
+  uint32_t ParameterType;
+  uint32_t ShaderVisibility;
+  uint32_t ParameterOffset;
 
-  static bool isValidVersion(uint32_t Version) {
-    return (Version == 1 || Version == 2);
+  void swapBytes() {
+    sys::swapByteOrder(ParameterType);
+    sys::swapByteOrder(ShaderVisibility);
+    sys::swapByteOrder(ParameterOffset);
   }
 };
 
+struct RootSignatureHeader {
+  uint32_t Version;
+  uint32_t NumParameters;
+  uint32_t ParametersOffset;
+  uint32_t NumStaticSamplers;
+  uint32_t StaticSamplerOffset;
+  uint32_t Flags;
+
+  void swapBytes() {
+    sys::swapByteOrder(Version);
+    sys::swapByteOrder(NumParameters);
+    sys::swapByteOrder(ParametersOffset);
+    sys::swapByteOrder(NumStaticSamplers);
+    sys::swapByteOrder(StaticSamplerOffset);
+    sys::swapByteOrder(Flags);
+  }
+};
 } // namespace dxbc
 } // namespace llvm
 

diff  --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
index 6d44ea14df444..590ded5e8c899 100644
--- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
+++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def
@@ -72,6 +72,24 @@ ROOT_ELEMENT_FLAG(11, SamplerHeapDirectlyIndexed)
 #undef ROOT_ELEMENT_FLAG
 #endif // ROOT_ELEMENT_FLAG
 
+#ifdef ROOT_PARAMETER
+
+ROOT_PARAMETER(1, Constants32Bit)
+#undef ROOT_PARAMETER
+#endif // ROOT_PARAMETER
+
+#ifdef SHADER_VISIBILITY
+
+SHADER_VISIBILITY(0, All)
+SHADER_VISIBILITY(1, Vertex)
+SHADER_VISIBILITY(2, Hull)
+SHADER_VISIBILITY(3, Domain)
+SHADER_VISIBILITY(4, Geometry)
+SHADER_VISIBILITY(5, Pixel)
+SHADER_VISIBILITY(6, Amplification)
+SHADER_VISIBILITY(7, Mesh)
+#undef SHADER_VISIBILITY
+#endif // SHADER_VISIBILITY
 
 #ifdef DXIL_MODULE_FLAG
 

diff  --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h
index e414112498798..fee799249b255 100644
--- a/llvm/include/llvm/MC/DXContainerRootSignature.h
+++ b/llvm/include/llvm/MC/DXContainerRootSignature.h
@@ -6,23 +6,33 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/BinaryFormat/DXContainer.h"
 #include <cstdint>
 #include <limits>
 
 namespace llvm {
 
 class raw_ostream;
-
 namespace mcdxbc {
+
+struct RootParameter {
+  dxbc::RootParameterHeader Header;
+  union {
+    dxbc::RootConstants Constants;
+  };
+};
 struct RootSignatureDesc {
-  uint32_t Version = 2;
-  uint32_t NumParameters = 0;
-  uint32_t RootParametersOffset = 0;
-  uint32_t NumStaticSamplers = 0;
-  uint32_t StaticSamplersOffset = 0;
-  uint32_t Flags = 0;
+
+  uint32_t Version = 2U;
+  uint32_t Flags = 0U;
+  uint32_t RootParameterOffset = 0U;
+  uint32_t StaticSamplersOffset = 0u;
+  uint32_t NumStaticSamplers = 0u;
+  SmallVector<mcdxbc::RootParameter> Parameters;
 
   void write(raw_ostream &OS) const;
+
+  size_t getSize() const;
 };
 } // namespace mcdxbc
 } // namespace llvm

diff  --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h
index c3a2f756bd683..e8287ce078365 100644
--- a/llvm/include/llvm/Object/DXContainer.h
+++ b/llvm/include/llvm/Object/DXContainer.h
@@ -18,10 +18,12 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/DXContainer.h"
+#include "llvm/Object/Error.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/TargetParser/Triple.h"
 #include <array>
+#include <cstddef>
 #include <variant>
 
 namespace llvm {
@@ -116,6 +118,40 @@ template <typename T> struct ViewArray {
 };
 
 namespace DirectX {
+struct RootParameterView {
+  const dxbc::RootParameterHeader &Header;
+  StringRef ParamData;
+  RootParameterView(const dxbc::RootParameterHeader &H, StringRef P)
+      : Header(H), ParamData(P) {}
+
+  template <typename T> Expected<T> readParameter() {
+    T Struct;
+    if (sizeof(T) != ParamData.size())
+      return make_error<GenericBinaryError>(
+          "Reading structure out of file bounds", object_error::parse_failed);
+
+    memcpy(&Struct, ParamData.data(), sizeof(T));
+    // DXContainer is always little endian
+    if (sys::IsBigEndianHost)
+      Struct.swapBytes();
+    return Struct;
+  }
+};
+
+struct RootConstantView : RootParameterView {
+  static bool classof(const RootParameterView *V) {
+    return V->Header.ParameterType ==
+           (uint32_t)dxbc::RootParameterType::Constants32Bit;
+  }
+
+  llvm::Expected<dxbc::RootConstants> read() {
+    return readParameter<dxbc::RootConstants>();
+  }
+};
+
+static Error parseFailed(const Twine &Msg) {
+  return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);
+}
 
 class RootSignature {
 private:
@@ -125,17 +161,49 @@ class RootSignature {
   uint32_t NumStaticSamplers;
   uint32_t StaticSamplersOffset;
   uint32_t Flags;
+  ViewArray<dxbc::RootParameterHeader> ParametersHeaders;
+  StringRef PartData;
+
+  using param_header_iterator = ViewArray<dxbc::RootParameterHeader>::iterator;
 
 public:
-  RootSignature() {}
+  RootSignature(StringRef PD) : PartData(PD) {}
 
-  Error parse(StringRef Data);
+  Error parse();
   uint32_t getVersion() const { return Version; }
   uint32_t getNumParameters() const { return NumParameters; }
   uint32_t getRootParametersOffset() const { return RootParametersOffset; }
   uint32_t getNumStaticSamplers() const { return NumStaticSamplers; }
   uint32_t getStaticSamplersOffset() const { return StaticSamplersOffset; }
+  uint32_t getNumRootParameters() const { return ParametersHeaders.size(); }
+  llvm::iterator_range<param_header_iterator> param_headers() const {
+    return llvm::make_range(ParametersHeaders.begin(), ParametersHeaders.end());
+  }
   uint32_t getFlags() const { return Flags; }
+
+  llvm::Expected<RootParameterView>
+  getParameter(const dxbc::RootParameterHeader &Header) const {
+    size_t DataSize;
+
+    if (!dxbc::isValidParameterType(Header.ParameterType))
+      return parseFailed("invalid parameter type");
+
+    switch (static_cast<dxbc::RootParameterType>(Header.ParameterType)) {
+    case dxbc::RootParameterType::Constants32Bit:
+      DataSize = sizeof(dxbc::RootConstants);
+      break;
+    }
+    size_t EndOfSectionByte = getNumStaticSamplers() == 0
+                                  ? PartData.size()
+                                  : getStaticSamplersOffset();
+
+    if (Header.ParameterOffset + DataSize > EndOfSectionByte)
+      return parseFailed("Reading structure out of file bounds");
+
+    StringRef Buff = PartData.substr(Header.ParameterOffset, DataSize);
+    RootParameterView View = RootParameterView(Header, Buff);
+    return View;
+  }
 };
 
 class PSVRuntimeInfo {

diff  --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
index ecad35e82b155..393bba9c79bf8 100644
--- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h
@@ -74,18 +74,43 @@ struct ShaderHash {
 };
 
 #define ROOT_ELEMENT_FLAG(Num, Val) bool Val = false;
+
+struct RootConstantsYaml {
+  uint32_t ShaderRegister;
+  uint32_t RegisterSpace;
+  uint32_t Num32BitValues;
+};
+
+struct RootParameterYamlDesc {
+  uint32_t Type;
+  uint32_t Visibility;
+  uint32_t Offset;
+
+  union {
+    RootConstantsYaml Constants;
+  };
+};
+
 struct RootSignatureYamlDesc {
   RootSignatureYamlDesc() = default;
-  RootSignatureYamlDesc(const object::DirectX::RootSignature &Data);
 
   uint32_t Version;
-  uint32_t NumParameters;
+  uint32_t NumRootParameters;
   uint32_t RootParametersOffset;
   uint32_t NumStaticSamplers;
   uint32_t StaticSamplersOffset;
 
+  SmallVector<RootParameterYamlDesc> Parameters;
+
   uint32_t getEncodedFlags();
 
+  iterator_range<RootParameterYamlDesc *> params() {
+    return make_range(Parameters.begin(), Parameters.end());
+  }
+
+  static llvm::Expected<DXContainerYAML::RootSignatureYamlDesc>
+  create(const object::DirectX::RootSignature &Data);
+
 #include "llvm/BinaryFormat/DXContainerConstants.def"
 };
 
@@ -192,6 +217,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::ResourceBindInfo)
 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_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)
@@ -264,6 +290,14 @@ template <> struct MappingTraits<DXContainerYAML::RootSignatureYamlDesc> {
                       DXContainerYAML::RootSignatureYamlDesc &RootSignature);
 };
 
+template <> struct MappingTraits<llvm::DXContainerYAML::RootParameterYamlDesc> {
+  static void mapping(IO &IO, llvm::DXContainerYAML::RootParameterYamlDesc &P);
+};
+
+template <> struct MappingTraits<llvm::DXContainerYAML::RootConstantsYaml> {
+  static void mapping(IO &IO, llvm::DXContainerYAML::RootConstantsYaml &C);
+};
+
 } // namespace yaml
 
 } // namespace llvm

diff  --git a/llvm/lib/BinaryFormat/DXContainer.cpp b/llvm/lib/BinaryFormat/DXContainer.cpp
index 97ceb16ccf53f..8e7b7d313706a 100644
--- a/llvm/lib/BinaryFormat/DXContainer.cpp
+++ b/llvm/lib/BinaryFormat/DXContainer.cpp
@@ -60,6 +60,26 @@ ArrayRef<EnumEntry<SigComponentType>> dxbc::getSigComponentTypes() {
   return ArrayRef(SigComponentTypes);
 }
 
+#define SHADER_VISIBILITY(Val, Enum) {#Enum, ShaderVisibility::Enum},
+
+static const EnumEntry<ShaderVisibility> ShaderVisibilityValues[] = {
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+};
+
+ArrayRef<EnumEntry<ShaderVisibility>> dxbc::getShaderVisibility() {
+  return ArrayRef(ShaderVisibilityValues);
+}
+
+#define ROOT_PARAMETER(Val, Enum) {#Enum, RootParameterType::Enum},
+
+static const EnumEntry<RootParameterType> RootParameterTypes[] = {
+#include "llvm/BinaryFormat/DXContainerConstants.def"
+};
+
+ArrayRef<EnumEntry<RootParameterType>> dxbc::getRootParameterTypes() {
+  return ArrayRef(RootParameterTypes);
+}
+
 #define SEMANTIC_KIND(Val, Enum) {#Enum, PSV::SemanticKind::Enum},
 
 static const EnumEntry<PSV::SemanticKind> SemanticKindNames[] = {

diff  --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp
index b6f2b85bac74e..c2731d95c955e 100644
--- a/llvm/lib/MC/DXContainerRootSignature.cpp
+++ b/llvm/lib/MC/DXContainerRootSignature.cpp
@@ -7,17 +7,81 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/MC/DXContainerRootSignature.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/Support/EndianStream.h"
 
 using namespace llvm;
 using namespace llvm::mcdxbc;
 
+static uint32_t writePlaceholder(raw_svector_ostream &Stream) {
+  const uint32_t DummyValue = std::numeric_limits<uint32_t>::max();
+  uint32_t Offset = Stream.tell();
+  support::endian::write(Stream, DummyValue, llvm::endianness::little);
+  return Offset;
+}
+
+static void rewriteOffsetToCurrentByte(raw_svector_ostream &Stream,
+                                       uint32_t Offset) {
+  uint32_t Value =
+      support::endian::byte_swap<uint32_t, llvm::endianness::little>(
+          Stream.tell());
+  Stream.pwrite(reinterpret_cast<const char *>(&Value), sizeof(Value), Offset);
+}
+
+size_t RootSignatureDesc::getSize() const {
+  size_t Size = sizeof(dxbc::RootSignatureHeader) +
+                Parameters.size() * sizeof(dxbc::RootParameterHeader);
+
+  for (const mcdxbc::RootParameter &P : Parameters) {
+    switch (P.Header.ParameterType) {
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      Size += sizeof(dxbc::RootConstants);
+      break;
+    }
+  }
+  return Size;
+}
+
 void RootSignatureDesc::write(raw_ostream &OS) const {
+  SmallString<256> Storage;
+  raw_svector_ostream BOS(Storage);
+  BOS.reserveExtraSpace(getSize());
+
+  const uint32_t NumParameters = Parameters.size();
+
+  support::endian::write(BOS, Version, llvm::endianness::little);
+  support::endian::write(BOS, NumParameters, llvm::endianness::little);
+  support::endian::write(BOS, RootParameterOffset, llvm::endianness::little);
+  support::endian::write(BOS, NumStaticSamplers, llvm::endianness::little);
+  support::endian::write(BOS, StaticSamplersOffset, llvm::endianness::little);
+  support::endian::write(BOS, Flags, llvm::endianness::little);
+
+  SmallVector<uint32_t> ParamsOffsets;
+  for (const mcdxbc::RootParameter &P : Parameters) {
+    support::endian::write(BOS, P.Header.ParameterType,
+                           llvm::endianness::little);
+    support::endian::write(BOS, P.Header.ShaderVisibility,
+                           llvm::endianness::little);
+
+    ParamsOffsets.push_back(writePlaceholder(BOS));
+  }
+
+  assert(NumParameters == ParamsOffsets.size());
+  for (size_t I = 0; I < NumParameters; ++I) {
+    rewriteOffsetToCurrentByte(BOS, ParamsOffsets[I]);
+    const mcdxbc::RootParameter &P = Parameters[I];
 
-  support::endian::write(OS, Version, llvm::endianness::little);
-  support::endian::write(OS, NumParameters, llvm::endianness::little);
-  support::endian::write(OS, RootParametersOffset, llvm::endianness::little);
-  support::endian::write(OS, NumStaticSamplers, llvm::endianness::little);
-  support::endian::write(OS, StaticSamplersOffset, llvm::endianness::little);
-  support::endian::write(OS, Flags, llvm::endianness::little);
+    switch (P.Header.ParameterType) {
+    case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+      support::endian::write(BOS, P.Constants.ShaderRegister,
+                             llvm::endianness::little);
+      support::endian::write(BOS, P.Constants.RegisterSpace,
+                             llvm::endianness::little);
+      support::endian::write(BOS, P.Constants.Num32BitValues,
+                             llvm::endianness::little);
+      break;
+    }
+  }
+  assert(Storage.size() == getSize());
+  OS.write(Storage.data(), Storage.size());
 }

diff  --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp
index 1eb1453c65147..95f6788e75aa6 100644
--- a/llvm/lib/Object/DXContainer.cpp
+++ b/llvm/lib/Object/DXContainer.cpp
@@ -20,10 +20,6 @@ static Error parseFailed(const Twine &Msg) {
   return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);
 }
 
-static Error validationFailed(const Twine &Msg) {
-  return make_error<StringError>(Msg.str(), inconvertibleErrorCode());
-}
-
 template <typename T>
 static Error readStruct(StringRef Buffer, const char *Src, T &Struct) {
   // Don't read before the beginning or past the end of the file
@@ -100,8 +96,8 @@ Error DXContainer::parseHash(StringRef Part) {
 Error DXContainer::parseRootSignature(StringRef Part) {
   if (RootSignature)
     return parseFailed("More than one RTS0 part is present in the file");
-  RootSignature = DirectX::RootSignature();
-  if (Error Err = RootSignature->parse(Part))
+  RootSignature = DirectX::RootSignature(Part);
+  if (Error Err = RootSignature->parse())
     return Err;
   return Error::success();
 }
@@ -246,23 +242,17 @@ void DXContainer::PartIterator::updateIteratorImpl(const uint32_t Offset) {
   IteratorState.Offset = Offset;
 }
 
-Error DirectX::RootSignature::parse(StringRef Data) {
-  const char *Current = Data.begin();
+Error DirectX::RootSignature::parse() {
+  const char *Current = PartData.begin();
 
   // Root Signature headers expects 6 integers to be present.
-  if (Data.size() < 6 * sizeof(uint32_t))
+  if (PartData.size() < 6 * sizeof(uint32_t))
     return parseFailed(
         "Invalid root signature, insufficient space for header.");
 
-  uint32_t VValue =
-      support::endian::read<uint32_t, llvm::endianness::little>(Current);
+  Version = support::endian::read<uint32_t, llvm::endianness::little>(Current);
   Current += sizeof(uint32_t);
 
-  if (!dxbc::RootSignatureValidations::isValidVersion(VValue))
-    return validationFailed("unsupported root signature version read: " +
-                            llvm::Twine(VValue));
-  Version = VValue;
-
   NumParameters =
       support::endian::read<uint32_t, llvm::endianness::little>(Current);
   Current += sizeof(uint32_t);
@@ -279,14 +269,11 @@ Error DirectX::RootSignature::parse(StringRef Data) {
       support::endian::read<uint32_t, llvm::endianness::little>(Current);
   Current += sizeof(uint32_t);
 
-  uint32_t FValue =
-      support::endian::read<uint32_t, llvm::endianness::little>(Current);
+  Flags = support::endian::read<uint32_t, llvm::endianness::little>(Current);
   Current += sizeof(uint32_t);
 
-  if (!dxbc::RootSignatureValidations::isValidRootFlag(FValue))
-    return validationFailed("unsupported root signature flag value read: " +
-                            llvm::Twine(FValue));
-  Flags = FValue;
+  ParametersHeaders.Data = PartData.substr(
+      RootParametersOffset, NumParameters * sizeof(dxbc::RootParameterHeader));
 
   return Error::success();
 }

diff  --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
index f6ed09c857bb7..86e24eae4abc6 100644
--- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp
@@ -269,11 +269,26 @@ void DXContainerWriter::writeParts(raw_ostream &OS) {
       mcdxbc::RootSignatureDesc RS;
       RS.Flags = P.RootSignature->getEncodedFlags();
       RS.Version = P.RootSignature->Version;
-      RS.NumParameters = P.RootSignature->NumParameters;
-      RS.RootParametersOffset = P.RootSignature->RootParametersOffset;
+      RS.RootParameterOffset = P.RootSignature->RootParametersOffset;
       RS.NumStaticSamplers = P.RootSignature->NumStaticSamplers;
       RS.StaticSamplersOffset = P.RootSignature->StaticSamplersOffset;
 
+      for (const auto &Param : P.RootSignature->Parameters) {
+        mcdxbc::RootParameter NewParam;
+        NewParam.Header = dxbc::RootParameterHeader{
+            Param.Type, Param.Visibility, Param.Offset};
+
+        switch (Param.Type) {
+        case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+          NewParam.Constants.Num32BitValues = Param.Constants.Num32BitValues;
+          NewParam.Constants.RegisterSpace = Param.Constants.RegisterSpace;
+          NewParam.Constants.ShaderRegister = Param.Constants.ShaderRegister;
+          break;
+        }
+
+        RS.Parameters.push_back(NewParam);
+      }
+
       RS.write(OS);
       break;
     }

diff  --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
index f03c7da65999d..59914fe30082d 100644
--- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp
+++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp
@@ -12,9 +12,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ObjectYAML/DXContainerYAML.h"
+#include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/BinaryFormat/DXContainer.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/ScopedPrinter.h"
+#include <cstdint>
+#include <system_error>
 
 namespace llvm {
 
@@ -29,16 +33,60 @@ DXContainerYAML::ShaderFeatureFlags::ShaderFeatureFlags(uint64_t FlagData) {
 #include "llvm/BinaryFormat/DXContainerConstants.def"
 }
 
-DXContainerYAML::RootSignatureYamlDesc::RootSignatureYamlDesc(
-    const object::DirectX::RootSignature &Data)
-    : Version(Data.getVersion()), NumParameters(Data.getNumParameters()),
-      RootParametersOffset(Data.getRootParametersOffset()),
-      NumStaticSamplers(Data.getNumStaticSamplers()),
-      StaticSamplersOffset(Data.getStaticSamplersOffset()) {
+llvm::Expected<DXContainerYAML::RootSignatureYamlDesc>
+DXContainerYAML::RootSignatureYamlDesc::create(
+    const object::DirectX::RootSignature &Data) {
+
+  RootSignatureYamlDesc RootSigDesc;
+
+  RootSigDesc.Version = Data.getVersion();
+  RootSigDesc.NumStaticSamplers = Data.getNumStaticSamplers();
+  RootSigDesc.StaticSamplersOffset = Data.getStaticSamplersOffset();
+  RootSigDesc.NumRootParameters = Data.getNumRootParameters();
+  RootSigDesc.RootParametersOffset = Data.getRootParametersOffset();
+
   uint32_t Flags = Data.getFlags();
+  for (const dxbc::RootParameterHeader &PH : Data.param_headers()) {
+
+    RootParameterYamlDesc NewP;
+    NewP.Offset = PH.ParameterOffset;
+
+    if (!dxbc::isValidParameterType(PH.ParameterType))
+      return createStringError(std::errc::invalid_argument,
+                               "Invalid value for parameter type");
+
+    NewP.Type = PH.ParameterType;
+
+    if (!dxbc::isValidShaderVisibility(PH.ShaderVisibility))
+      return createStringError(std::errc::invalid_argument,
+                               "Invalid value for shader visibility");
+
+    NewP.Visibility = PH.ShaderVisibility;
+
+    llvm::Expected<object::DirectX::RootParameterView> ParamViewOrErr =
+        Data.getParameter(PH);
+    if (Error E = ParamViewOrErr.takeError())
+      return std::move(E);
+    object::DirectX::RootParameterView ParamView = ParamViewOrErr.get();
+
+    if (auto *RCV = dyn_cast<object::DirectX::RootConstantView>(&ParamView)) {
+      llvm::Expected<dxbc::RootConstants> ConstantsOrErr = RCV->read();
+      if (Error E = ConstantsOrErr.takeError())
+        return std::move(E);
+
+      auto Constants = *ConstantsOrErr;
+
+      NewP.Constants.Num32BitValues = Constants.Num32BitValues;
+      NewP.Constants.ShaderRegister = Constants.ShaderRegister;
+      NewP.Constants.RegisterSpace = Constants.RegisterSpace;
+    }
+    RootSigDesc.Parameters.push_back(NewP);
+  }
 #define ROOT_ELEMENT_FLAG(Num, Val)                                            \
-  Val = (Flags & (uint32_t)dxbc::RootElementFlag::Val) > 0;
+  RootSigDesc.Val =                                                            \
+      (Flags & llvm::to_underlying(dxbc::RootElementFlag::Val)) > 0;
 #include "llvm/BinaryFormat/DXContainerConstants.def"
+  return RootSigDesc;
 }
 
 uint32_t DXContainerYAML::RootSignatureYamlDesc::getEncodedFlags() {
@@ -212,14 +260,34 @@ void MappingTraits<DXContainerYAML::Signature>::mapping(
 void MappingTraits<DXContainerYAML::RootSignatureYamlDesc>::mapping(
     IO &IO, DXContainerYAML::RootSignatureYamlDesc &S) {
   IO.mapRequired("Version", S.Version);
-  IO.mapRequired("NumParameters", S.NumParameters);
+  IO.mapRequired("NumRootParameters", S.NumRootParameters);
   IO.mapRequired("RootParametersOffset", S.RootParametersOffset);
   IO.mapRequired("NumStaticSamplers", S.NumStaticSamplers);
   IO.mapRequired("StaticSamplersOffset", S.StaticSamplersOffset);
+  IO.mapRequired("Parameters", S.Parameters);
 #define ROOT_ELEMENT_FLAG(Num, Val) IO.mapOptional(#Val, S.Val, false);
 #include "llvm/BinaryFormat/DXContainerConstants.def"
 }
 
+void MappingTraits<llvm::DXContainerYAML::RootConstantsYaml>::mapping(
+    IO &IO, llvm::DXContainerYAML::RootConstantsYaml &C) {
+  IO.mapRequired("Num32BitValues", C.Num32BitValues);
+  IO.mapRequired("RegisterSpace", C.RegisterSpace);
+  IO.mapRequired("ShaderRegister", C.ShaderRegister);
+}
+
+void MappingTraits<llvm::DXContainerYAML::RootParameterYamlDesc>::mapping(
+    IO &IO, llvm::DXContainerYAML::RootParameterYamlDesc &P) {
+  IO.mapRequired("ParameterType", P.Type);
+  IO.mapRequired("ShaderVisibility", P.Visibility);
+
+  switch (P.Type) {
+  case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
+    IO.mapRequired("Constants", P.Constants);
+    break;
+  }
+}
+
 void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
                                                    DXContainerYAML::Part &P) {
   IO.mapRequired("Name", P.Name);

diff  --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
index fd390cdbf9057..3ba0535e0114b 100644
--- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp
+++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp
@@ -92,8 +92,10 @@ static bool parse(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
   return HasError;
 }
 
+static bool verifyRootFlag(uint32_t Flags) { return (Flags & ~0xfff) == 0; }
+
 static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
-  if (!dxbc::RootSignatureValidations::isValidRootFlag(RSD.Flags)) {
+  if (!verifyRootFlag(RSD.Flags)) {
     return reportError(Ctx, "Invalid Root Signature flag value");
   }
   return false;
@@ -189,6 +191,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
 
   SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> &RSDMap =
       AM.getResult<RootSignatureAnalysis>(M);
+
+  const size_t RSHSize = sizeof(dxbc::RootSignatureHeader);
   OS << "Root Signature Definitions"
      << "\n";
   uint8_t Space = 0;
@@ -203,12 +207,11 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
     Space++;
     OS << indent(Space) << "Flags: " << format_hex(RS.Flags, 8) << ":\n";
     OS << indent(Space) << "Version: " << RS.Version << ":\n";
-    OS << indent(Space) << "NumParameters: " << RS.NumParameters << ":\n";
-    OS << indent(Space) << "RootParametersOffset: " << RS.RootParametersOffset
-       << ":\n";
-    OS << indent(Space) << "NumStaticSamplers: " << RS.NumStaticSamplers
-       << ":\n";
-    OS << indent(Space) << "StaticSamplersOffset: " << RS.StaticSamplersOffset
+    OS << indent(Space) << "NumParameters: " << RS.Parameters.size() << ":\n";
+    OS << indent(Space) << "RootParametersOffset: " << RSHSize << ":\n";
+    OS << indent(Space) << "NumStaticSamplers: " << 0 << ":\n";
+    OS << indent(Space)
+       << "StaticSamplersOffset: " << RSHSize + RS.Parameters.size_in_bytes()
        << ":\n";
     Space--;
     // end root signature header

diff  --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll
index 3f5bb166ad0e5..ef2b97860bfae 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll
@@ -22,8 +22,9 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
 ; DXC-NEXT:    Size:            24
 ; DXC-NEXT:    RootSignature:
 ; DXC-NEXT:      Version:         2
-; DXC-NEXT:      NumParameters:   0
+; DXC-NEXT:      NumRootParameters: 0
 ; DXC-NEXT:      RootParametersOffset: 0
 ; DXC-NEXT:      NumStaticSamplers: 0
 ; DXC-NEXT:      StaticSamplersOffset: 0
+; DXC-NEXT:      Parameters: []
 ; DXC-NEXT:      AllowInputAssemblerInputLayout: true

diff  --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll
index 7adb17d0b022f..581ac9aaec110 100644
--- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll
@@ -27,14 +27,14 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
 ; CHECK-NEXT:   Flags: 0x000001
 ; CHECK-NEXT:   Version: 2
 ; CHECK-NEXT:   NumParameters: 0
-; CHECK-NEXT:   RootParametersOffset: 0
+; CHECK-NEXT:   RootParametersOffset: 24
 ; CHECK-NEXT:   NumStaticSamplers: 0
-; CHECK-NEXT:   StaticSamplersOffset: 0
+; CHECK-NEXT:   StaticSamplersOffset: 24
 
 ; CHECK-LABEL: Definition for 'anotherMain':
 ; CHECK-NEXT:   Flags: 0x000002
 ; CHECK-NEXT:   Version: 2
 ; CHECK-NEXT:   NumParameters: 0
-; CHECK-NEXT:   RootParametersOffset: 0
+; CHECK-NEXT:   RootParametersOffset: 24
 ; CHECK-NEXT:   NumStaticSamplers: 0
-; CHECK-NEXT:   StaticSamplersOffset: 0
+; CHECK-NEXT:   StaticSamplersOffset: 24

diff  --git a/llvm/test/ObjectYAML/DXContainer/RootSignature-Flags.yaml b/llvm/test/ObjectYAML/DXContainer/RootSignature-Flags.yaml
index b0a3e6945f454..74816d403183a 100644
--- a/llvm/test/ObjectYAML/DXContainer/RootSignature-Flags.yaml
+++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-Flags.yaml
@@ -14,10 +14,11 @@ Parts:
     Size:            24
     RootSignature:
       Version: 2
-      NumParameters: 1
-      RootParametersOffset: 3
-      NumStaticSamplers: 4
-      StaticSamplersOffset: 5
+      NumRootParameters: 0
+      RootParametersOffset: 24
+      NumStaticSamplers: 0
+      StaticSamplersOffset: 60
+      Parameters: []
       AllowInputAssemblerInputLayout: true
       DenyGeometryShaderRootAccess: true
 
@@ -25,9 +26,10 @@ Parts:
 # CHECK-NEXT:    Size:            24
 # CHECK-NEXT:    RootSignature:
 # CHECK-NEXT:      Version: 2
-# CHECK-NEXT:      NumParameters: 1
-# CHECK-NEXT:      RootParametersOffset: 3
-# CHECK-NEXT:      NumStaticSamplers: 4
-# CHECK-NEXT:      StaticSamplersOffset: 5
+# CHECK-NEXT:      NumRootParameters: 0
+# CHECK-NEXT:      RootParametersOffset: 24
+# CHECK-NEXT:      NumStaticSamplers: 0
+# CHECK-NEXT:      StaticSamplersOffset: 60
+# CHECK-NEXT:      Parameters: []
 # CHECK-NEXT:      AllowInputAssemblerInputLayout: true
 # CHECK-NEXT:      DenyGeometryShaderRootAccess: true

diff  --git a/llvm/test/ObjectYAML/DXContainer/RootSignature-InvalidType.yaml b/llvm/test/ObjectYAML/DXContainer/RootSignature-InvalidType.yaml
new file mode 100644
index 0000000000000..091e70789d956
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-InvalidType.yaml
@@ -0,0 +1,29 @@
+# RUN: yaml2obj %s -o %t
+# RUN: not obj2yaml 2>&1 %t | FileCheck %s -DFILE=%t
+
+# CHECK: Error reading file: [[FILE]]: Invalid value for parameter type
+
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  PartCount:       1
+  PartOffsets:     [ 60 ]
+Parts:
+  - Name:            RTS0
+    Size:            80
+    RootSignature:
+      Version: 2
+      NumRootParameters: 2
+      RootParametersOffset: 24
+      NumStaticSamplers: 0
+      StaticSamplersOffset: 64
+      Parameters:         
+      - ParameterType: 255 # INVALID
+        ShaderVisibility: 2 # Hull
+      AllowInputAssemblerInputLayout: true
+      DenyGeometryShaderRootAccess: true

diff  --git a/llvm/test/ObjectYAML/DXContainer/RootSignature-InvalidVisibility.yaml b/llvm/test/ObjectYAML/DXContainer/RootSignature-InvalidVisibility.yaml
new file mode 100644
index 0000000000000..1acaf6e4e08a4
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-InvalidVisibility.yaml
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %s -o %t
+# RUN: not obj2yaml 2>&1 %t | FileCheck %s -DFILE=%t
+
+# CHECK: Error reading file: [[FILE]]: Invalid value for shader visibility
+
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  PartCount:       1
+  PartOffsets:     [ 60 ]
+Parts:
+  - Name:            RTS0
+    Size:            80
+    RootSignature:
+      Version: 2
+      NumRootParameters: 2
+      RootParametersOffset: 24
+      NumStaticSamplers: 0
+      StaticSamplersOffset: 64
+      Parameters:         
+      - ParameterType: 1 # Constants32Bit
+        ShaderVisibility: 255 # INVALID
+        Constants:
+          Num32BitValues: 21
+          ShaderRegister: 22
+          RegisterSpace: 23   
+      AllowInputAssemblerInputLayout: true
+      DenyGeometryShaderRootAccess: true

diff  --git a/llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml b/llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml
new file mode 100644
index 0000000000000..f366d71714359
--- /dev/null
+++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-MultipleParameters.yaml
@@ -0,0 +1,59 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+
+--- !dxcontainer
+Header:
+  Hash:            [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
+  Version:
+    Major:           1
+    Minor:           0
+  PartCount:       1
+  PartOffsets:     [ 60 ]
+Parts:
+  - Name:            RTS0
+    Size:            80
+    RootSignature:
+      Version: 2
+      NumRootParameters: 2
+      RootParametersOffset: 24
+      NumStaticSamplers: 0
+      StaticSamplersOffset: 60
+      Parameters:         
+      - ParameterType: 1 # Constants32Bit
+        ShaderVisibility: 2 # Hull
+        Constants:
+          Num32BitValues: 16
+          ShaderRegister: 15
+          RegisterSpace: 14
+      - ParameterType: 1 # Constants32Bit
+        ShaderVisibility: 4 # Geometry
+        Constants:
+          Num32BitValues: 21
+          ShaderRegister: 22
+          RegisterSpace: 23     
+      AllowInputAssemblerInputLayout: true
+      DenyGeometryShaderRootAccess: true
+
+# CHECK:  - Name:            RTS0
+# CHECK-NEXT:    Size:            80
+# CHECK-NEXT:    RootSignature:
+# CHECK-NEXT:      Version:         2
+# CHECK-NEXT:      NumRootParameters: 2
+# CHECK-NEXT:      RootParametersOffset: 24
+# CHECK-NEXT:      NumStaticSamplers: 0
+# CHECK-NEXT:      StaticSamplersOffset: 60
+# CHECK-NEXT:      Parameters:
+# CHECK-NEXT:        - ParameterType:   1
+# CHECK-NEXT:          ShaderVisibility: 2
+# CHECK-NEXT:          Constants:
+# CHECK-NEXT:            Num32BitValues:  16
+# CHECK-NEXT:            RegisterSpace:   14
+# CHECK-NEXT:            ShaderRegister:  15
+# CHECK-NEXT:        - ParameterType:   1
+# CHECK-NEXT:          ShaderVisibility: 4
+# CHECK-NEXT:          Constants:
+# CHECK-NEXT:            Num32BitValues:  21
+# CHECK-NEXT:            RegisterSpace:   23
+# CHECK-NEXT:            ShaderRegister:  22
+# CHECK-NEXT:      AllowInputAssemblerInputLayout: true
+# CHECK-NEXT:      DenyGeometryShaderRootAccess: true

diff  --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
index f3ef1b6a27bcf..c727595406767 100644
--- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
+++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
@@ -155,8 +155,13 @@ dumpDXContainer(MemoryBufferRef Source) {
       break;
     case dxbc::PartType::RTS0:
       std::optional<DirectX::RootSignature> RS = Container.getRootSignature();
-      if (RS.has_value())
-        NewPart.RootSignature = DXContainerYAML::RootSignatureYamlDesc(*RS);
+      if (RS.has_value()) {
+        auto RootSigDescOrErr =
+            DXContainerYAML::RootSignatureYamlDesc::create(*RS);
+        if (Error E = RootSigDescOrErr.takeError())
+          return std::move(E);
+        NewPart.RootSignature = RootSigDescOrErr.get();
+      }
       break;
     }
   }

diff  --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp
index 5a73f32ab7c32..62ef8e385373f 100644
--- a/llvm/unittests/Object/DXContainerTest.cpp
+++ b/llvm/unittests/Object/DXContainerTest.cpp
@@ -11,6 +11,7 @@
 #include "llvm/BinaryFormat/Magic.h"
 #include "llvm/ObjectYAML/DXContainerYAML.h"
 #include "llvm/ObjectYAML/yaml2obj.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gtest/gtest.h"
@@ -822,6 +823,57 @@ TEST(DXCFile, MalformedSignature) {
   }
 }
 
+TEST(RootSignature, RootParameters) {
+  {
+    // Root Parameters offset has changed to 36, additional padding was added,
+    // as well as fixing the parameter offset.
+    uint8_t Buffer[] = {
+        0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,
+        0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,
+        0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+        0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+        0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x2c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+        0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00};
+
+    DXContainer C =
+        llvm::cantFail(DXContainer::create(getMemoryBuffer<144>(Buffer)));
+
+    auto MaybeRS = C.getRootSignature();
+    ASSERT_TRUE(MaybeRS.has_value());
+    const auto &RS = MaybeRS.value();
+    ASSERT_EQ(RS.getVersion(), 2u);
+    ASSERT_EQ(RS.getNumParameters(), 1u);
+    ASSERT_EQ(RS.getRootParametersOffset(), 36u);
+    ASSERT_EQ(RS.getNumStaticSamplers(), 0u);
+    ASSERT_EQ(RS.getStaticSamplersOffset(), 44u);
+    ASSERT_EQ(RS.getFlags(), 17u);
+
+    auto RootParam = *RS.param_headers().begin();
+    ASSERT_EQ((unsigned)RootParam.ParameterType, 1u);
+    ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 2u);
+    auto ParamView = RS.getParameter(RootParam);
+    ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());
+
+    DirectX::RootConstantView *RootConstantsView =
+        dyn_cast<DirectX::RootConstantView>(&*ParamView);
+    ASSERT_TRUE(RootConstantsView != nullptr);
+    auto Constants = RootConstantsView->read();
+
+    ASSERT_THAT_ERROR(Constants.takeError(), Succeeded());
+
+    ASSERT_EQ(Constants->ShaderRegister, 15u);
+    ASSERT_EQ(Constants->RegisterSpace, 14u);
+    ASSERT_EQ(Constants->Num32BitValues, 16u);
+  }
+}
+
 TEST(RootSignature, ParseRootFlags) {
   {
     uint8_t Buffer[] = {
@@ -829,7 +881,7 @@ TEST(RootSignature, ParseRootFlags) {
         0x05, 0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1, 0x01, 0x00, 0x00, 0x00,
         0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
         0x52, 0x54, 0x53, 0x30, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
     };
     DXContainer C =
@@ -839,12 +891,11 @@ TEST(RootSignature, ParseRootFlags) {
     ASSERT_TRUE(RS.has_value());
     ASSERT_EQ(RS->getVersion(), 2u);
     ASSERT_EQ(RS->getNumParameters(), 0u);
-    ASSERT_EQ(RS->getRootParametersOffset(), 0u);
+    ASSERT_EQ(RS->getRootParametersOffset(), 24u);
     ASSERT_EQ(RS->getNumStaticSamplers(), 0u);
     ASSERT_EQ(RS->getStaticSamplersOffset(), 0u);
     ASSERT_EQ(RS->getFlags(), 0x01u);
   }
-
   {
     // this parameter has the root signature definition missing some values.
     uint8_t Buffer[] = {
@@ -860,33 +911,51 @@ TEST(RootSignature, ParseRootFlags) {
         FailedWithMessage(
             "Invalid root signature, insufficient space for header."));
   }
+}
+
+TEST(RootSignature, ParseRootConstant) {
   {
-    // Version has been changed to an invalid number.
     uint8_t Buffer[] = {
-        0x44, 0x58, 0x42, 0x43, 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35, 0x6F,
-        0x05, 0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1, 0x01, 0x00, 0x00, 0x00,
-        0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
-        0x52, 0x54, 0x53, 0x30, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+        0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,
+        0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,
+        0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+        0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+        0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x2c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+        0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+        0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    };
-    EXPECT_THAT_EXPECTED(
-        DXContainer::create(getMemoryBuffer<100>(Buffer)),
-        FailedWithMessage("unsupported root signature version read: 3"));
-  }
-  {
-    // Flag has been set to an invalid value
-    uint8_t Buffer[] = {
-        0x44, 0x58, 0x42, 0x43, 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35, 0x6F,
-        0x05, 0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1, 0x01, 0x00, 0x00, 0x00,
-        0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
-        0x52, 0x54, 0x53, 0x30, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xFF,
-    };
-    EXPECT_THAT_EXPECTED(
-        DXContainer::create(getMemoryBuffer<100>(Buffer)),
-        FailedWithMessage(
-            "unsupported root signature flag value read: 4278190081"));
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00};
+    DXContainer C =
+        llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));
+
+    auto MaybeRS = C.getRootSignature();
+    ASSERT_TRUE(MaybeRS.has_value());
+    const auto &RS = MaybeRS.value();
+    ASSERT_EQ(RS.getVersion(), 2u);
+    ASSERT_EQ(RS.getNumParameters(), 1u);
+    ASSERT_EQ(RS.getRootParametersOffset(), 24u);
+    ASSERT_EQ(RS.getNumStaticSamplers(), 0u);
+    ASSERT_EQ(RS.getStaticSamplersOffset(), 44u);
+    ASSERT_EQ(RS.getFlags(), 17u);
+
+    auto RootParam = *RS.param_headers().begin();
+    ASSERT_EQ((unsigned)RootParam.ParameterType, 1u);
+    ASSERT_EQ((unsigned)RootParam.ShaderVisibility, 2u);
+    auto ParamView = RS.getParameter(RootParam);
+    ASSERT_THAT_ERROR(ParamView.takeError(), Succeeded());
+
+    DirectX::RootConstantView *RootConstantsView =
+        dyn_cast<DirectX::RootConstantView>(&*ParamView);
+    ASSERT_TRUE(RootConstantsView != nullptr);
+    auto Constants = RootConstantsView->read();
+
+    ASSERT_THAT_ERROR(Constants.takeError(), Succeeded());
+
+    ASSERT_EQ(Constants->ShaderRegister, 15u);
+    ASSERT_EQ(Constants->RegisterSpace, 14u);
+    ASSERT_EQ(Constants->Num32BitValues, 16u);
   }
 }

diff  --git a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
index b48cd9ce53987..61390049bc0df 100644
--- a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
+++ b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp
@@ -127,10 +127,11 @@ TEST(RootSignature, ParseRootFlags) {
       Size:            24
       RootSignature:
         Version:         2
-        NumParameters:   0
-        RootParametersOffset: 0
+        NumRootParameters: 0
+        RootParametersOffset: 24
         NumStaticSamplers: 0
         StaticSamplersOffset: 0
+        Parameters: []
         AllowInputAssemblerInputLayout: true
     )"));
 
@@ -139,10 +140,114 @@ TEST(RootSignature, ParseRootFlags) {
       0x05, 0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1, 0x01, 0x00, 0x00, 0x00,
       0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
       0x52, 0x54, 0x53, 0x30, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   };
 
   EXPECT_EQ(Storage.size(), 68u);
   EXPECT_TRUE(memcmp(Buffer, Storage.data(), 68u) == 0);
 }
+
+TEST(RootSignature, HeaderData) {
+  SmallString<128> Storage;
+
+  // First read a fully explicit yaml with all sizes and offsets provided
+  ASSERT_TRUE(convert(Storage, R"(--- !dxcontainer
+  Header:
+      Hash:            [ 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35, 0x6F, 0x5, 
+                        0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1 ]
+      Version:
+        Major:           1
+        Minor:           0
+      FileSize:        133
+      PartCount:       1
+      PartOffsets:     [ 36 ]
+  Parts:
+    - Name:            RTS0
+      Size:            89
+      RootSignature:
+        Version: 2
+        NumRootParameters: 1
+        RootParametersOffset: 255
+        NumStaticSamplers: 0
+        StaticSamplersOffset: 0
+        Parameters:
+          - ParameterType: 1
+            ShaderVisibility: 2
+            Constants:
+              Num32BitValues: 16
+              ShaderRegister: 15
+              RegisterSpace: 14
+        AllowInputAssemblerInputLayout: true
+        DenyGeometryShaderRootAccess: true
+    )"));
+
+  uint8_t Buffer[] = {
+      0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,
+      0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,
+      0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+      0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+      0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+      0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00};
+
+  EXPECT_EQ(Storage.size(), 133u);
+  EXPECT_TRUE(memcmp(Buffer, Storage.data(), 133u) == 0);
+}
+
+TEST(RootSignature, ParseRootConstants) {
+  SmallString<128> Storage;
+
+  // First read a fully explicit yaml with all sizes and offsets provided
+  ASSERT_TRUE(convert(Storage, R"(--- !dxcontainer
+  Header:
+      Hash:            [ 0x32, 0x9A, 0x53, 0xD8, 0xEC, 0xBE, 0x35, 0x6F, 0x5, 
+                        0x39, 0xE1, 0xFE, 0x31, 0x20, 0xF0, 0xC1 ]
+      Version:
+        Major:           1
+        Minor:           0
+      FileSize:        133
+      PartCount:       1
+      PartOffsets:     [ 36 ]
+  Parts:
+    - Name:            RTS0
+      Size:            89
+      RootSignature:
+        Version: 2
+        NumRootParameters: 1
+        RootParametersOffset: 36
+        NumStaticSamplers: 0
+        StaticSamplersOffset: 0
+        Parameters:
+          - ParameterType: 1
+            ShaderVisibility: 2
+            Constants:
+              Num32BitValues: 16
+              ShaderRegister: 15
+              RegisterSpace: 14
+        AllowInputAssemblerInputLayout: true
+        DenyGeometryShaderRootAccess: true
+    )"));
+
+  uint8_t Buffer[] = {
+      0x44, 0x58, 0x42, 0x43, 0x32, 0x9a, 0x53, 0xd8, 0xec, 0xbe, 0x35, 0x6f,
+      0x05, 0x39, 0xe1, 0xfe, 0x31, 0x20, 0xf0, 0xc1, 0x01, 0x00, 0x00, 0x00,
+      0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+      0x52, 0x54, 0x53, 0x30, 0x59, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+      0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+      0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00};
+
+  EXPECT_EQ(Storage.size(), 133u);
+  EXPECT_TRUE(memcmp(Buffer, Storage.data(), 133u) == 0);
+}


        


More information about the llvm-commits mailing list