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