diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index bd5a796c0b31c..819e7d3f4d571 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> 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> 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 #include 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 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 +#include #include namespace llvm { @@ -116,6 +118,40 @@ template struct ViewArray { }; namespace DirectX { +struct RootParameterView { + const dxbc::RootParameterHeader &Header; + StringRef ParamData; + RootParameterView(const dxbc::RootParameterHeader &H, StringRef P) + : Header(H), ParamData(P) {} + + template Expected readParameter() { + T Struct; + if (sizeof(T) != ParamData.size()) + return make_error( + "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 read() { + return readParameter(); + } +}; + +static Error parseFailed(const Twine &Msg) { + return make_error(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 ParametersHeaders; + StringRef PartData; + + using param_header_iterator = ViewArray::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_headers() const { + return llvm::make_range(ParametersHeaders.begin(), ParametersHeaders.end()); + } uint32_t getFlags() const { return Flags; } + + llvm::Expected + getParameter(const dxbc::RootParameterHeader &Header) const { + size_t DataSize; + + if (!dxbc::isValidParameterType(Header.ParameterType)) + return parseFailed("invalid parameter type"); + + switch (static_cast(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 Parameters; + uint32_t getEncodedFlags(); + iterator_range params() { + return make_range(Parameters.begin(), Parameters.end()); + } + + static llvm::Expected + 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 &RootSignature); }; +template <> struct MappingTraits { + static void mapping(IO &IO, llvm::DXContainerYAML::RootParameterYamlDesc &P); +}; + +template <> struct MappingTraits { + 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> dxbc::getSigComponentTypes() { return ArrayRef(SigComponentTypes); } +#define SHADER_VISIBILITY(Val, Enum) {#Enum, ShaderVisibility::Enum}, + +static const EnumEntry ShaderVisibilityValues[] = { +#include "llvm/BinaryFormat/DXContainerConstants.def" +}; + +ArrayRef> dxbc::getShaderVisibility() { + return ArrayRef(ShaderVisibilityValues); +} + +#define ROOT_PARAMETER(Val, Enum) {#Enum, RootParameterType::Enum}, + +static const EnumEntry RootParameterTypes[] = { +#include "llvm/BinaryFormat/DXContainerConstants.def" +}; + +ArrayRef> dxbc::getRootParameterTypes() { + return ArrayRef(RootParameterTypes); +} + #define SEMANTIC_KIND(Val, Enum) {#Enum, PSV::SemanticKind::Enum}, static const EnumEntry 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::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( + Stream.tell()); + Stream.pwrite(reinterpret_cast(&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 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(Msg.str(), object_error::parse_failed); } -static Error validationFailed(const Twine &Msg) { - return make_error(Msg.str(), inconvertibleErrorCode()); -} - template 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(Current); + Version = support::endian::read(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(Current); Current += sizeof(uint32_t); @@ -279,14 +269,11 @@ Error DirectX::RootSignature::parse(StringRef Data) { support::endian::read(Current); Current += sizeof(uint32_t); - uint32_t FValue = - support::endian::read(Current); + Flags = support::endian::read(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 +#include 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::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 ParamViewOrErr = + Data.getParameter(PH); + if (Error E = ParamViewOrErr.takeError()) + return std::move(E); + object::DirectX::RootParameterView ParamView = ParamViewOrErr.get(); + + if (auto *RCV = dyn_cast(&ParamView)) { + llvm::Expected 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::mapping( void MappingTraits::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::mapping( + IO &IO, llvm::DXContainerYAML::RootConstantsYaml &C) { + IO.mapRequired("Num32BitValues", C.Num32BitValues); + IO.mapRequired("RegisterSpace", C.RegisterSpace); + IO.mapRequired("ShaderRegister", C.ShaderRegister); +} + +void MappingTraits::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::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 &RSDMap = AM.getResult(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 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(&*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(&*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); +}