diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index 21e28d546286e..fbab066bf4517 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -14,6 +14,8 @@ #define LLVM_BINARYFORMAT_DXCONTAINER_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/BinaryStreamError.h" +#include "llvm/Support/Error.h" #include "llvm/Support/SwapByteOrder.h" #include "llvm/TargetParser/Triple.h" @@ -152,6 +154,11 @@ enum class FeatureFlags : uint64_t { static_assert((uint64_t)FeatureFlags::NextUnusedBit <= 1ull << 63, "Shader flag bits exceed enum size."); +#define ROOT_ELEMENT_FLAG(Num, Val) Val = 1ull << Num, +enum class RootElementFlag : uint32_t { +#include "DXContainerConstants.def" +}; + PartType parsePartType(StringRef S); struct VertexPSVInfo { @@ -541,6 +548,23 @@ struct ProgramSignatureElement { static_assert(sizeof(ProgramSignatureElement) == 32, "ProgramSignatureElement is misaligned"); +struct RootSignatureValidations { + + static Expected validateRootFlag(uint32_t Flags) { + if ((Flags & ~0x80000fff) != 0) + return llvm::make_error("Invalid Root Signature flag"); + return Flags; + } + + static Expected validateVersion(uint32_t Version) { + if (Version == 1 || Version == 2) + return Version; + + return llvm::make_error( + "Invalid Root Signature Version"); + } +}; + } // namespace dxbc } // namespace llvm diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def index 1aacbb2f65b27..39a0e7a5c8493 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def +++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def @@ -4,6 +4,7 @@ CONTAINER_PART(DXIL) CONTAINER_PART(SFI0) CONTAINER_PART(HASH) CONTAINER_PART(PSV0) +CONTAINER_PART(RTS0) CONTAINER_PART(ISG1) CONTAINER_PART(OSG1) CONTAINER_PART(PSG1) @@ -52,6 +53,26 @@ SHADER_FEATURE_FLAG(31, 36, NextUnusedBit, "Next reserved shader flag bit (not a #undef SHADER_FEATURE_FLAG #endif // SHADER_FEATURE_FLAG + +// ROOT_ELEMENT_FLAG(bit offset for the flag, name). +#ifdef ROOT_ELEMENT_FLAG + +ROOT_ELEMENT_FLAG(0, AllowInputAssemblerInputLayout) +ROOT_ELEMENT_FLAG(1, DenyVertexShaderRootAccess) +ROOT_ELEMENT_FLAG(2, DenyHullShaderRootAccess) +ROOT_ELEMENT_FLAG(3, DenyDomainShaderRootAccess) +ROOT_ELEMENT_FLAG(4, DenyGeometryShaderRootAccess) +ROOT_ELEMENT_FLAG(5, DenyPixelShaderRootAccess) +ROOT_ELEMENT_FLAG(6, AllowStreamOutput) +ROOT_ELEMENT_FLAG(7, LocalRootSignature) +ROOT_ELEMENT_FLAG(8, DenyAmplificationShaderRootAccess) +ROOT_ELEMENT_FLAG(9, DenyMeshShaderRootAccess) +ROOT_ELEMENT_FLAG(10, CBVSRVUAVHeapDirectlyIndexed) +ROOT_ELEMENT_FLAG(11, SamplerHeapDirectlyIndexed) +#undef ROOT_ELEMENT_FLAG +#endif // ROOT_ELEMENT_FLAG + + #ifdef DXIL_MODULE_FLAG // Only save DXIL module flags which not map to feature flags here. diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h new file mode 100644 index 0000000000000..e1a9be5fc52d8 --- /dev/null +++ b/llvm/include/llvm/MC/DXContainerRootSignature.h @@ -0,0 +1,28 @@ +//===- llvm/MC/DXContainerRootSignature.h - RootSignature -*- C++ -*- ========// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include + +namespace llvm { + +class raw_ostream; + +namespace mcdxbc { +struct RootSignatureHeader { + uint32_t Version = 2; + uint32_t NumParameters = 0; + uint32_t RootParametersOffset = 0; + uint32_t NumStaticSamplers = 0; + uint32_t StaticSamplersOffset = 0; + uint32_t Flags = 0; + + void write(raw_ostream &OS); +}; +} // namespace mcdxbc +} // namespace llvm diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h index 19c83ba6c6e85..c3a2f756bd683 100644 --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -116,6 +116,28 @@ template struct ViewArray { }; namespace DirectX { + +class RootSignature { +private: + uint32_t Version; + uint32_t NumParameters; + uint32_t RootParametersOffset; + uint32_t NumStaticSamplers; + uint32_t StaticSamplersOffset; + uint32_t Flags; + +public: + RootSignature() {} + + Error parse(StringRef Data); + 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 getFlags() const { return Flags; } +}; + class PSVRuntimeInfo { using ResourceArray = ViewArray; @@ -287,6 +309,7 @@ class DXContainer { std::optional ShaderFeatureFlags; std::optional Hash; std::optional PSVInfo; + std::optional RootSignature; DirectX::Signature InputSignature; DirectX::Signature OutputSignature; DirectX::Signature PatchConstantSignature; @@ -296,6 +319,7 @@ class DXContainer { Error parseDXILHeader(StringRef Part); Error parseShaderFeatureFlags(StringRef Part); Error parseHash(StringRef Part); + Error parseRootSignature(StringRef Part); Error parsePSVInfo(StringRef Part); Error parseSignature(StringRef Part, DirectX::Signature &Array); friend class PartIterator; @@ -382,6 +406,10 @@ class DXContainer { std::optional getShaderHash() const { return Hash; } + std::optional getRootSignature() const { + return RootSignature; + } + const std::optional &getPSVInfo() const { return PSVInfo; }; diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h index 66ad057ab0e30..0200f5cb196ff 100644 --- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h +++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/DXContainer.h" +#include "llvm/Object/DXContainer.h" #include "llvm/ObjectYAML/YAML.h" #include "llvm/Support/YAMLTraits.h" #include @@ -72,6 +73,22 @@ struct ShaderHash { std::vector Digest; }; +#define ROOT_ELEMENT_FLAG(Num, Val) bool Val = false; +struct RootSignatureDesc { + RootSignatureDesc() = default; + RootSignatureDesc(const object::DirectX::RootSignature &Data); + + uint32_t Version; + uint32_t NumParameters; + uint32_t RootParametersOffset; + uint32_t NumStaticSamplers; + uint32_t StaticSamplersOffset; + + uint32_t getEncodedFlags(); + +#include "llvm/BinaryFormat/DXContainerConstants.def" +}; + using ResourceFlags = dxbc::PSV::ResourceFlags; using ResourceBindInfo = dxbc::PSV::v2::ResourceBindInfo; @@ -159,6 +176,7 @@ struct Part { std::optional Hash; std::optional Info; std::optional Signature; + std::optional RootSignature; }; struct Object { @@ -241,6 +259,11 @@ template <> struct MappingTraits { static void mapping(IO &IO, llvm::DXContainerYAML::Signature &El); }; +template <> struct MappingTraits { + static void mapping(IO &IO, + DXContainerYAML::RootSignatureDesc &RootSignature); +}; + } // namespace yaml } // namespace llvm diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt index e1d19196c8766..f49f14c848b90 100644 --- a/llvm/lib/MC/CMakeLists.txt +++ b/llvm/lib/MC/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_component_library(LLVMMC ConstantPools.cpp DXContainerPSVInfo.cpp + DXContainerRootSignature.cpp ELFObjectWriter.cpp GOFFObjectWriter.cpp MCAsmBackend.cpp diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp new file mode 100644 index 0000000000000..000d23f24d241 --- /dev/null +++ b/llvm/lib/MC/DXContainerRootSignature.cpp @@ -0,0 +1,23 @@ +//===- llvm/MC/DXContainerRootSignature.cpp - RootSignature -*- C++ -*-=======// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/DXContainerRootSignature.h" +#include "llvm/Support/EndianStream.h" + +using namespace llvm; +using namespace llvm::mcdxbc; + +void RootSignatureHeader::write(raw_ostream &OS) { + + 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); +} diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp index 3b1a6203a1f8f..f28b096008b2f 100644 --- a/llvm/lib/Object/DXContainer.cpp +++ b/llvm/lib/Object/DXContainer.cpp @@ -10,6 +10,7 @@ #include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Object/Error.h" #include "llvm/Support/Alignment.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/FormatVariadic.h" using namespace llvm; @@ -92,6 +93,15 @@ Error DXContainer::parseHash(StringRef Part) { return Error::success(); } +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)) + return Err; + return Error::success(); +} + Error DXContainer::parsePSVInfo(StringRef Part) { if (PSVInfo) return parseFailed("More than one PSV0 part is present in the file"); @@ -193,6 +203,10 @@ Error DXContainer::parsePartOffsets() { break; case dxbc::PartType::Unknown: break; + case dxbc::PartType::RTS0: + if (Error Err = parseRootSignature(PartData)) + return Err; + break; } } @@ -228,6 +242,53 @@ void DXContainer::PartIterator::updateIteratorImpl(const uint32_t Offset) { IteratorState.Offset = Offset; } +Error DirectX::RootSignature::parse(StringRef Data) { + const char *Current = Data.begin(); + + // Root Signature headers expects 6 integers to be present. + if (Data.size() < 6 * sizeof(uint32_t)) + return parseFailed( + "Invalid root signature, insufficient space for header."); + + uint32_t VValue = + support::endian::read(Current); + Current += sizeof(uint32_t); + + Expected MaybeVersion = + dxbc::RootSignatureValidations::validateVersion(VValue); + if (Error E = MaybeVersion.takeError()) + return E; + Version = MaybeVersion.get(); + + NumParameters = + support::endian::read(Current); + Current += sizeof(uint32_t); + + RootParametersOffset = + support::endian::read(Current); + Current += sizeof(uint32_t); + + NumStaticSamplers = + support::endian::read(Current); + Current += sizeof(uint32_t); + + StaticSamplersOffset = + support::endian::read(Current); + Current += sizeof(uint32_t); + + uint32_t FValue = + support::endian::read(Current); + Current += sizeof(uint32_t); + + Expected MaybeFlag = + dxbc::RootSignatureValidations::validateRootFlag(FValue); + if (Error E = MaybeFlag.takeError()) + return E; + Flags = MaybeFlag.get(); + + return Error::success(); +} + Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) { Triple::EnvironmentType ShaderStage = dxbc::getShaderStage(ShaderKind); diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp index 175f1a12f9314..b7d1c6558fa1f 100644 --- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp +++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp @@ -13,6 +13,7 @@ #include "llvm/BinaryFormat/DXContainer.h" #include "llvm/MC/DXContainerPSVInfo.h" +#include "llvm/MC/DXContainerRootSignature.h" #include "llvm/ObjectYAML/ObjectYAML.h" #include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/Errc.h" @@ -261,6 +262,20 @@ void DXContainerWriter::writeParts(raw_ostream &OS) { } case dxbc::PartType::Unknown: break; // Skip any handling for unrecognized parts. + case dxbc::PartType::RTS0: + if (!P.RootSignature.has_value()) + continue; + + mcdxbc::RootSignatureHeader Header; + Header.Flags = P.RootSignature->getEncodedFlags(); + Header.Version = P.RootSignature->Version; + Header.NumParameters = P.RootSignature->NumParameters; + Header.RootParametersOffset = P.RootSignature->RootParametersOffset; + Header.NumStaticSamplers = P.RootSignature->NumStaticSamplers; + Header.StaticSamplersOffset = P.RootSignature->StaticSamplersOffset; + + Header.write(OS); + break; } uint64_t BytesWritten = OS.tell() - DataStart; RollingOffset += BytesWritten; diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index 5dee1221b27c0..0869fd4fa9785 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -29,6 +29,27 @@ DXContainerYAML::ShaderFeatureFlags::ShaderFeatureFlags(uint64_t FlagData) { #include "llvm/BinaryFormat/DXContainerConstants.def" } +DXContainerYAML::RootSignatureDesc::RootSignatureDesc( + const object::DirectX::RootSignature &Data) + : Version(Data.getVersion()), NumParameters(Data.getNumParameters()), + RootParametersOffset(Data.getRootParametersOffset()), + NumStaticSamplers(Data.getNumStaticSamplers()), + StaticSamplersOffset(Data.getStaticSamplersOffset()) { + uint32_t Flags = Data.getFlags(); +#define ROOT_ELEMENT_FLAG(Num, Val) \ + Val = (Flags & (uint32_t)dxbc::RootElementFlag::Val) > 0; +#include "llvm/BinaryFormat/DXContainerConstants.def" +} + +uint32_t DXContainerYAML::RootSignatureDesc::getEncodedFlags() { + uint64_t Flag = 0; +#define ROOT_ELEMENT_FLAG(Num, Val) \ + if (Val) \ + Flag |= (uint32_t)dxbc::RootElementFlag::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) \ @@ -188,6 +209,17 @@ void MappingTraits::mapping( IO.mapRequired("Parameters", S.Parameters); } +void MappingTraits::mapping( + IO &IO, DXContainerYAML::RootSignatureDesc &S) { + IO.mapRequired("Version", S.Version); + IO.mapRequired("NumParameters", S.NumParameters); + IO.mapRequired("RootParametersOffset", S.RootParametersOffset); + IO.mapRequired("NumStaticSamplers", S.NumStaticSamplers); + IO.mapRequired("StaticSamplersOffset", S.StaticSamplersOffset); +#define ROOT_ELEMENT_FLAG(Num, Val) IO.mapOptional(#Val, S.Val, false); +#include "llvm/BinaryFormat/DXContainerConstants.def" +} + void MappingTraits::mapping(IO &IO, DXContainerYAML::Part &P) { IO.mapRequired("Name", P.Name); @@ -197,6 +229,7 @@ void MappingTraits::mapping(IO &IO, IO.mapOptional("Hash", P.Hash); IO.mapOptional("PSVInfo", P.Info); IO.mapOptional("Signature", P.Signature); + IO.mapOptional("RootSignature", P.RootSignature); } void MappingTraits::mapping( diff --git a/llvm/test/ObjectYAML/DXContainer/RootSignature-Flags.yaml b/llvm/test/ObjectYAML/DXContainer/RootSignature-Flags.yaml new file mode 100644 index 0000000000000..b0a3e6945f454 --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-Flags.yaml @@ -0,0 +1,33 @@ +# 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: 24 + RootSignature: + Version: 2 + NumParameters: 1 + RootParametersOffset: 3 + NumStaticSamplers: 4 + StaticSamplersOffset: 5 + AllowInputAssemblerInputLayout: true + DenyGeometryShaderRootAccess: true + +# CHECK: - Name: RTS0 +# 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: AllowInputAssemblerInputLayout: true +# CHECK-NEXT: DenyGeometryShaderRootAccess: true diff --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp index 06966b1883586..54a912d9438af 100644 --- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp +++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp @@ -153,6 +153,11 @@ dumpDXContainer(MemoryBufferRef Source) { break; case dxbc::PartType::Unknown: break; + case dxbc::PartType::RTS0: + std::optional RS = Container.getRootSignature(); + if (RS.has_value()) + NewPart.RootSignature = DXContainerYAML::RootSignatureDesc(*RS); + break; } } diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp index 5a2c852d6aef9..88a915f560e05 100644 --- a/llvm/unittests/Object/DXContainerTest.cpp +++ b/llvm/unittests/Object/DXContainerTest.cpp @@ -821,3 +821,73 @@ TEST(DXCFile, MalformedSignature) { "the end of the part data")); } } + +TEST(RootSignature, ParseRootFlags) { + { + 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, 0x00, + }; + DXContainer C = + llvm::cantFail(DXContainer::create(getMemoryBuffer<68>(Buffer))); + + const auto &RS = C.getRootSignature(); + ASSERT_TRUE(RS.has_value()); + ASSERT_EQ(RS->getVersion(), 2); + ASSERT_EQ(RS->getNumParameters(), 0); + ASSERT_EQ(RS->getRootParametersOffset(), 0); + ASSERT_EQ(RS->getNumStaticSamplers(), 0); + ASSERT_EQ(RS->getStaticSamplersOffset(), 0); + ASSERT_EQ(RS->getFlags(), 0x01); + } + + { + // this parameter has the root signature definition missing some values. + 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, + }; + EXPECT_THAT_EXPECTED( + DXContainer::create(getMemoryBuffer<64>(Buffer)), + FailedWithMessage( + "Invalid root signature, insufficient space for header.")); + } + { + // 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, + 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<68>(Buffer)), + FailedWithMessage("Stream Error: An unspecified error has occurred. " + "Invalid Root Signature Version")); + } + { + // 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<68>(Buffer)), + FailedWithMessage("Stream Error: An unspecified error has occurred. " + "Invalid Root Signature flag")); + } +} diff --git a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp index d4232295c8584..b48cd9ce53987 100644 --- a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp +++ b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp @@ -107,3 +107,42 @@ TEST(DXCFile, ParseEmptyParts) { EXPECT_EQ(Storage.size(), 116u); EXPECT_TRUE(memcmp(Buffer, Storage.data(), 116) == 0); } + +TEST(RootSignature, ParseRootFlags) { + 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: 68 + PartCount: 1 + PartOffsets: [ 36 ] + Parts: + - Name: RTS0 + Size: 24 + RootSignature: + Version: 2 + NumParameters: 0 + RootParametersOffset: 0 + NumStaticSamplers: 0 + StaticSamplersOffset: 0 + AllowInputAssemblerInputLayout: 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, + 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, 0x00, + }; + + EXPECT_EQ(Storage.size(), 68u); + EXPECT_TRUE(memcmp(Buffer, Storage.data(), 68u) == 0); +}