https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/160616
>From 787c77638092b06e7648f03660a4429dc602aac6 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Thu, 18 Sep 2025 14:16:25 -0700 Subject: [PATCH 01/19] adding yaml representation and updating write logic --- llvm/include/llvm/BinaryFormat/DXContainer.h | 24 ++++++++ .../BinaryFormat/DXContainerConstants.def | 10 +++ .../llvm/MC/DXContainerRootSignature.h | 1 + .../include/llvm/ObjectYAML/DXContainerYAML.h | 5 ++ llvm/lib/BinaryFormat/DXContainer.cpp | 9 +++ .../HLSL/RootSignatureValidations.cpp | 4 +- llvm/lib/MC/DXContainerRootSignature.cpp | 7 ++- llvm/lib/ObjectYAML/DXContainerEmitter.cpp | 3 + llvm/lib/ObjectYAML/DXContainerYAML.cpp | 12 ++++ .../ObjectYAML/DXContainerYAMLTest.cpp | 61 +++++++++++++++++++ 10 files changed, 134 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index c04380667a640..a08cfff4b4974 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -185,6 +185,15 @@ enum class DescriptorRangeFlags : uint32_t { LLVM_ABI ArrayRef<EnumEntry<DescriptorRangeFlags>> getDescriptorRangeFlags(); +#define STATIC_SAMPLER_FLAG(Num, Enum, Flag) Enum = Num, +enum class StaticSamplerFlags : uint32_t { +#include "DXContainerConstants.def" + + LLVM_MARK_AS_BITMASK_ENUM(NonNormalizedCoordinates) +}; + +LLVM_ABI ArrayRef<EnumEntry<StaticSamplerFlags>> getStaticSamplerFlags(); + #define ROOT_PARAMETER(Val, Enum) Enum = Val, enum class RootParameterType : uint32_t { #include "DXContainerConstants.def" @@ -813,6 +822,21 @@ struct DescriptorRange { } }; } // namespace v2 +namespace v3 { +struct StaticSampler : public v1::StaticSampler { + uint32_t Flags; + + StaticSampler() = default; + explicit StaticSampler(v1::StaticSampler &Base) + : v1::StaticSampler(Base), Flags(0U) {} + + void swapBytes() { + v1::StaticSampler::swapBytes(); + sys::swapByteOrder(Flags); + } +}; + +} // namespace v3 } // namespace RTS0 // D3D_ROOT_SIGNATURE_VERSION diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def index 889653611d79a..f576d958037cd 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def +++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def @@ -104,6 +104,16 @@ DESCRIPTOR_RANGE_FLAG(0x10000, DescriptorsStaticKeepingBufferBoundsChecks, DESCR #undef DESCRIPTOR_RANGE_FLAG #endif // DESCRIPTOR_RANGE_FLAG +// STATIC_SAMPLER_FLAG(flag value, name, flag). +#ifdef STATIC_SAMPLER_FLAG + +STATIC_SAMPLER_FLAG(0x0, None, SAMPLER_FLAG_NONE) +STATIC_SAMPLER_FLAG(0x1, UintBorderColor, SAMPLER_FLAG_UINT_BORDER_COLOR) +STATIC_SAMPLER_FLAG(0x2, NonNormalizedCoordinates, SAMPLER_FLAG_NON_NORMALIZED_COORDINATES) + +#undef STATIC_SAMPLER_FLAG +#endif // STATIC_SAMPLER_FLAG + #ifdef ROOT_PARAMETER ROOT_PARAMETER(0, DescriptorTable) diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h index 54677ef70244f..2a76e81fefc5f 100644 --- a/llvm/include/llvm/MC/DXContainerRootSignature.h +++ b/llvm/include/llvm/MC/DXContainerRootSignature.h @@ -74,6 +74,7 @@ struct StaticSampler { uint32_t ShaderRegister; uint32_t RegisterSpace; dxbc::ShaderVisibility ShaderVisibility; + uint32_t Flags; }; struct RootParametersContainer { diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h index 62bfee7693db1..b5b110d0f59a1 100644 --- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h +++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h @@ -178,6 +178,11 @@ struct StaticSamplerYamlDesc { uint32_t ShaderRegister; uint32_t RegisterSpace; dxbc::ShaderVisibility ShaderVisibility; + + LLVM_ABI uint32_t getEncodedFlags() const; + +#define STATIC_SAMPLER_FLAG(Num, Enum, Flag) bool Enum = false; +#include "llvm/BinaryFormat/DXContainerConstants.def" }; struct RootSignatureYamlDesc { diff --git a/llvm/lib/BinaryFormat/DXContainer.cpp b/llvm/lib/BinaryFormat/DXContainer.cpp index 36d10d0b63078..c06a3e34653f0 100644 --- a/llvm/lib/BinaryFormat/DXContainer.cpp +++ b/llvm/lib/BinaryFormat/DXContainer.cpp @@ -89,6 +89,15 @@ ArrayRef<EnumEntry<DescriptorRangeFlags>> dxbc::getDescriptorRangeFlags() { return ArrayRef(DescriptorRangeFlagNames); } +static const EnumEntry<StaticSamplerFlags> StaticSamplerFlagNames[] = { +#define STATIC_SAMPLER_FLAG(Val, Enum, Flag) {#Enum, StaticSamplerFlags::Enum}, +#include "llvm/BinaryFormat/DXContainerConstants.def" +}; + +ArrayRef<EnumEntry<StaticSamplerFlags>> dxbc::getStaticSamplerFlags() { + return ArrayRef(StaticSamplerFlagNames); +} + #define SHADER_VISIBILITY(Val, Enum) {#Enum, ShaderVisibility::Enum}, static const EnumEntry<ShaderVisibility> ShaderVisibilityValues[] = { diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 0970977b5064f..8c298f0685286 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -20,7 +20,9 @@ namespace rootsig { bool verifyRootFlag(uint32_t Flags) { return (Flags & ~0xfff) == 0; } -bool verifyVersion(uint32_t Version) { return (Version == 1 || Version == 2); } +bool verifyVersion(uint32_t Version) { + return (Version == 1 || Version == 2 || Version == 3); +} bool verifyRegisterValue(uint32_t RegisterValue) { return RegisterValue != ~0U; diff --git a/llvm/lib/MC/DXContainerRootSignature.cpp b/llvm/lib/MC/DXContainerRootSignature.cpp index b9ebb7a9e789c..13784e7c86684 100644 --- a/llvm/lib/MC/DXContainerRootSignature.cpp +++ b/llvm/lib/MC/DXContainerRootSignature.cpp @@ -33,7 +33,9 @@ static uint32_t rewriteOffsetToCurrentByte(raw_svector_ostream &Stream, size_t RootSignatureDesc::getSize() const { uint32_t StaticSamplersOffset = computeStaticSamplersOffset(); size_t StaticSamplersSize = - StaticSamplers.size() * sizeof(dxbc::RTS0::v1::StaticSampler); + (Version > 2 ? sizeof(dxbc::RTS0::v3::StaticSampler) + : sizeof(dxbc::RTS0::v1::StaticSampler)) * + StaticSamplers.size(); return size_t(StaticSamplersOffset) + StaticSamplersSize; } @@ -171,6 +173,9 @@ void RootSignatureDesc::write(raw_ostream &OS) const { support::endian::write(BOS, S.ShaderRegister, llvm::endianness::little); support::endian::write(BOS, S.RegisterSpace, llvm::endianness::little); support::endian::write(BOS, S.ShaderVisibility, llvm::endianness::little); + + if (Version > 2) + support::endian::write(BOS, S.Flags, llvm::endianness::little); } assert(Storage.size() == getSize()); OS.write(Storage.data(), Storage.size()); diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp index 910383816f43b..b00e45d912be1 100644 --- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp +++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp @@ -343,6 +343,9 @@ Error DXContainerWriter::writeParts(raw_ostream &OS) { NewSampler.RegisterSpace = Param.RegisterSpace; NewSampler.ShaderVisibility = Param.ShaderVisibility; + if (RS.Version > 2) + NewSampler.Flags = Param.getEncodedFlags(); + RS.StaticSamplers.push_back(NewSampler); } diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index 22674b1ceb734..39f42fb4dc839 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -245,6 +245,15 @@ uint32_t DXContainerYAML::DescriptorRangeYaml::getEncodedFlags() const { return Flags; } +uint32_t DXContainerYAML::StaticSamplerYamlDesc::getEncodedFlags() const { + uint64_t Flags = 0; +#define STATIC_SAMPLER_FLAG(Num, Enum, Flag) \ + if (Enum) \ + Flags |= (uint32_t)dxbc::StaticSamplerFlags::Enum; +#include "llvm/BinaryFormat/DXContainerConstants.def" + return Flags; +} + uint64_t DXContainerYAML::ShaderFeatureFlags::getEncodedFlags() { uint64_t Flag = 0; #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str) \ @@ -512,6 +521,9 @@ void MappingTraits<llvm::DXContainerYAML::StaticSamplerYamlDesc>::mapping( IO.mapRequired("ShaderRegister", S.ShaderRegister); IO.mapRequired("RegisterSpace", S.RegisterSpace); IO.mapRequired("ShaderVisibility", S.ShaderVisibility); + +#define STATIC_SAMPLER_FLAG_FLAG(Num, Val) IO.mapOptional(#Val, S.Val, false); +#include "llvm/BinaryFormat/DXContainerConstants.def" } void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO, diff --git a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp index b0ad208625436..eee0b64e4b866 100644 --- a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp +++ b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp @@ -526,3 +526,64 @@ TEST(RootSignature, ParseStaticSamplers) { EXPECT_EQ(Storage.size(), 144u); EXPECT_TRUE(memcmp(Buffer, Storage.data(), 144u) == 0); } + +TEST(RootSignature, ParseStaticSamplersV13) { + SmallString<128> Storage; + + // First read a fully explicit yaml with all sizes and offsets provided + ASSERT_TRUE(convert(Storage, R"(--- !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: 76 + RootSignature: + Version: 3 + NumRootParameters: 0 + RootParametersOffset: 24 + NumStaticSamplers: 1 + StaticSamplersOffset: 24 + Parameters: [] + Samplers: + - Filter: MinLinearMagMipPoint + AddressU: Wrap + AddressV: Mirror + AddressW: MirrorOnce + MipLODBias: 1.23 + MaxAnisotropy: 20 + ComparisonFunc: LessEqual + BorderColor: TransparentBlack + MinLOD: 4.56 + MaxLOD: 8.90 + ShaderRegister: 31 + RegisterSpace: 32 + ShaderVisibility: Mesh + SAMPLER_FLAG_UINT_BORDER_COLOR: true + AllowInputAssemblerInputLayout: true + DenyGeometryShaderRootAccess: true + )")); + + uint8_t Buffer[] = { + 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 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, + 0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41, + 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x01}; + + EXPECT_EQ(Storage.size(), 148U); + EXPECT_TRUE(memcmp(Buffer, Storage.data(), 148U) == 0); +} >From 57fd710107c459b53e2f9fe2c3f0de3f24d6b064 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Thu, 18 Sep 2025 16:54:27 -0700 Subject: [PATCH 02/19] fix test --- llvm/lib/ObjectYAML/DXContainerYAML.cpp | 4 ++-- llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index 39f42fb4dc839..42074731c4e16 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -521,8 +521,8 @@ void MappingTraits<llvm::DXContainerYAML::StaticSamplerYamlDesc>::mapping( IO.mapRequired("ShaderRegister", S.ShaderRegister); IO.mapRequired("RegisterSpace", S.RegisterSpace); IO.mapRequired("ShaderVisibility", S.ShaderVisibility); - -#define STATIC_SAMPLER_FLAG_FLAG(Num, Val) IO.mapOptional(#Val, S.Val, false); +#define STATIC_SAMPLER_FLAG(Num, Enum, Flag) \ + IO.mapOptional(#Flag, S.Enum, false); #include "llvm/BinaryFormat/DXContainerConstants.def" } diff --git a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp index eee0b64e4b866..db9861f0149a4 100644 --- a/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp +++ b/llvm/unittests/ObjectYAML/DXContainerYAMLTest.cpp @@ -528,7 +528,7 @@ TEST(RootSignature, ParseStaticSamplers) { } TEST(RootSignature, ParseStaticSamplersV13) { - SmallString<128> Storage; + SmallString<160> Storage; // First read a fully explicit yaml with all sizes and offsets provided ASSERT_TRUE(convert(Storage, R"(--- !dxcontainer @@ -575,14 +575,14 @@ TEST(RootSignature, ParseStaticSamplersV13) { 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 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, - 0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x01}; + 0x01, 0x00, 0x00, 0x00}; EXPECT_EQ(Storage.size(), 148U); EXPECT_TRUE(memcmp(Buffer, Storage.data(), 148U) == 0); >From d72adfe11a56a57e970f28b7ff0725c316ec8900 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Fri, 19 Sep 2025 10:46:53 -0700 Subject: [PATCH 03/19] adding missing test --- .../RootSignature-Invalid-Version.ll | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Invalid-Version.ll diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Invalid-Version.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Invalid-Version.ll new file mode 100644 index 0000000000000..26867e6d7ec25 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Invalid-Version.ll @@ -0,0 +1,20 @@ +; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s + +target triple = "dxil-unknown-shadermodel6.0-compute" + + +; CHECK: error: Invalid value for Version: 4 +; CHECK-NOT: Root Signature Definitions +define void @main() #0 { +entry: + ret void +} +attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } + + +!dx.rootsignatures = !{!2, !3, !4, !5} ; list of function/root signature pairs +!2 = !{ ptr @main, !6, i32 1 } ; function, root signature +!3 = !{ ptr @main, !6, i32 4 } ; function, root signature +!4 = !{ ptr @main, !6, i32 2 } ; function, root signature +!5 = !{ ptr @main, !6, i32 3 } ; function, root signature +!6 = !{ } ; list of root signature elements >From fefd58c2ab1044ac51c546b6bc6df968eb5edaa8 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Fri, 19 Sep 2025 12:48:11 -0700 Subject: [PATCH 04/19] fix test --- llvm/include/llvm/Object/DXContainer.h | 57 ++++++++++++++++------- llvm/lib/ObjectYAML/DXContainerYAML.cpp | 16 ++++++- llvm/unittests/Object/DXContainerTest.cpp | 16 ++++--- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h index 9bc1918852335..e3e532f6635a4 100644 --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -123,25 +123,26 @@ template <typename T> struct ViewArray { }; namespace DirectX { + +template <typename T> Expected<T> readParameter(StringRef Data) { + T Struct; + if (sizeof(T) != Data.size()) + return make_error<GenericBinaryError>( + "Reading structure out of file bounds", object_error::parse_failed); + + memcpy(&Struct, Data.data(), sizeof(T)); + // DXContainer is always little endian + if (sys::IsBigEndianHost) + Struct.swapBytes(); + return Struct; +} + struct RootParameterView { const dxbc::RTS0::v1::RootParameterHeader &Header; StringRef ParamData; RootParameterView(const dxbc::RTS0::v1::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 { @@ -151,7 +152,7 @@ struct RootConstantView : RootParameterView { } llvm::Expected<dxbc::RTS0::v1::RootConstants> read() { - return readParameter<dxbc::RTS0::v1::RootConstants>(); + return readParameter<dxbc::RTS0::v1::RootConstants>(ParamData); } }; @@ -167,7 +168,8 @@ struct RootDescriptorView : RootParameterView { llvm::Expected<dxbc::RTS0::v2::RootDescriptor> read(uint32_t Version) { if (Version == 1) { - auto Descriptor = readParameter<dxbc::RTS0::v1::RootDescriptor>(); + auto Descriptor = + readParameter<dxbc::RTS0::v1::RootDescriptor>(ParamData); if (Error E = Descriptor.takeError()) return E; return dxbc::RTS0::v2::RootDescriptor(*Descriptor); @@ -176,9 +178,10 @@ struct RootDescriptorView : RootParameterView { return make_error<GenericBinaryError>("Invalid Root Signature version: " + Twine(Version), object_error::parse_failed); - return readParameter<dxbc::RTS0::v2::RootDescriptor>(); + return readParameter<dxbc::RTS0::v2::RootDescriptor>(ParamData); } }; + template <typename T> struct DescriptorTable { uint32_t NumRanges; uint32_t RangesOffset; @@ -247,8 +250,26 @@ class RootSignature { llvm::iterator_range<param_header_iterator> param_headers() const { return llvm::make_range(ParametersHeaders.begin(), ParametersHeaders.end()); } - llvm::iterator_range<samplers_iterator> samplers() const { - return llvm::make_range(StaticSamplers.begin(), StaticSamplers.end()); + llvm::Expected<dxbc::RTS0::v3::StaticSampler> getSampler(uint32_t Loc) const { + if (Loc >= getNumStaticSamplers()) + return parseFailed("Static sampler index out of range"); + + auto SamplerSize = (Version <= 2) ? sizeof(dxbc::RTS0::v1::StaticSampler) + : sizeof(dxbc::RTS0::v3::StaticSampler); + + StringRef Buff = PartData.substr(StaticSamplersOffset + (Loc * SamplerSize), + SamplerSize); + if (Version < 3) { + auto Sampler = readParameter<dxbc::RTS0::v1::StaticSampler>(Buff); + if (Error E = Sampler.takeError()) + return E; + return dxbc::RTS0::v3::StaticSampler(*Sampler); + } + if (Version != 3) + return make_error<GenericBinaryError>("Invalid Root Signature version: " + + Twine(Version), + object_error::parse_failed); + return readParameter<dxbc::RTS0::v3::StaticSampler>(Buff); } uint32_t getFlags() const { return Flags; } diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index 42074731c4e16..6f24b7d2573ec 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -163,7 +163,13 @@ DXContainerYAML::RootSignatureYamlDesc::create( } } - for (const auto &S : Data.samplers()) { + for (uint32_t Loc = 0; Loc < Data.getNumStaticSamplers(); ++Loc) { + llvm::Expected<dxbc::RTS0::v3::StaticSampler> MaybeSampler = + Data.getSampler(Loc); + if (Error E = MaybeSampler.takeError()) + return std::move(E); + const llvm::dxbc::RTS0::v3::StaticSampler &S = *MaybeSampler; + if (!dxbc::isValidSamplerFilter(S.Filter)) return createStringError(std::errc::invalid_argument, "Invalid value for static sampler filter"); @@ -209,6 +215,14 @@ DXContainerYAML::RootSignatureYamlDesc::create( NewS.RegisterSpace = S.RegisterSpace; NewS.ShaderVisibility = dxbc::ShaderVisibility(S.ShaderVisibility); + if (Version > 2) { + if (Version > 1) { +#define STATIC_SAMPLER_FLAG(Num, Enum, Flag) \ + NewS.Enum = \ + (S.Flags & llvm::to_underlying(dxbc::StaticSamplerFlags::Enum)) > 0; +#include "llvm/BinaryFormat/DXContainerConstants.def" + } + } RootSigDesc.StaticSamplers.push_back(NewS); } diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp index 396d060a75bfd..f2a7bdfdcd75a 100644 --- a/llvm/unittests/Object/DXContainerTest.cpp +++ b/llvm/unittests/Object/DXContainerTest.cpp @@ -1165,11 +1165,11 @@ TEST(RootSignature, ParseStaticSamplers) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x7f, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00}; DXContainer C = llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer))); @@ -1179,12 +1179,14 @@ TEST(RootSignature, ParseStaticSamplers) { const auto &RS = MaybeRS.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(), 1u); ASSERT_EQ(RS.getStaticSamplersOffset(), 24u); ASSERT_EQ(RS.getFlags(), 17u); - auto Sampler = *RS.samplers().begin(); + auto MaybeSamplerView = RS.getSampler(0); + ASSERT_THAT_ERROR(MaybeSamplerView.takeError(), Succeeded()); + const auto &Sampler = *MaybeSamplerView; ASSERT_EQ(Sampler.Filter, 10u); ASSERT_EQ(Sampler.AddressU, 1u); >From 1d0cbd39875a84c983106678c8b857d8157bfa51 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Mon, 22 Sep 2025 10:28:12 -0700 Subject: [PATCH 05/19] adding samplers_iterator --- llvm/include/llvm/Object/DXContainer.h | 70 +++++++++++++++++------ llvm/lib/ObjectYAML/DXContainerYAML.cpp | 5 +- llvm/unittests/Object/DXContainerTest.cpp | 2 +- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h index e3e532f6635a4..e3913ece842bc 100644 --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -223,6 +223,28 @@ static Error parseFailed(const Twine &Msg) { class RootSignature { private: + struct samplers_iterator { + const RootSignature *Parent = nullptr; + uint32_t Index = 0; + + llvm::Expected<dxbc::RTS0::v3::StaticSampler> operator*() const { + return Parent->getSampler(Index); + } + + samplers_iterator &operator++() { + ++Index; + return *this; + } + + bool operator==(const samplers_iterator &Other) const { + return Parent == Other.Parent && Index == Other.Index; + } + + bool operator!=(const samplers_iterator &Other) const { + return !(*this == Other); + } + }; + uint32_t Version; uint32_t NumParameters; uint32_t RootParametersOffset; @@ -233,23 +255,6 @@ class RootSignature { StringRef PartData; ViewArray<dxbc::RTS0::v1::StaticSampler> StaticSamplers; - using param_header_iterator = - ViewArray<dxbc::RTS0::v1::RootParameterHeader>::iterator; - using samplers_iterator = ViewArray<dxbc::RTS0::v1::StaticSampler>::iterator; - -public: - RootSignature(StringRef PD) : PartData(PD) {} - - LLVM_ABI 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()); - } llvm::Expected<dxbc::RTS0::v3::StaticSampler> getSampler(uint32_t Loc) const { if (Loc >= getNumStaticSamplers()) return parseFailed("Static sampler index out of range"); @@ -271,6 +276,37 @@ class RootSignature { object_error::parse_failed); return readParameter<dxbc::RTS0::v3::StaticSampler>(Buff); } + + using param_header_iterator = + ViewArray<dxbc::RTS0::v1::RootParameterHeader>::iterator; + +public: + RootSignature(StringRef PD) : PartData(PD) {} + + LLVM_ABI 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(); } + + samplers_iterator samplers_begin() const { + return samplers_iterator{this, 0}; + } + + samplers_iterator samplers_end() const { + return samplers_iterator{this, getNumStaticSamplers()}; + } + + llvm::iterator_range<samplers_iterator> samplers() const { + return llvm::make_range(samplers_begin(), samplers_end()); + } + + 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> diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index 6f24b7d2573ec..91f86caaa4005 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -163,9 +163,8 @@ DXContainerYAML::RootSignatureYamlDesc::create( } } - for (uint32_t Loc = 0; Loc < Data.getNumStaticSamplers(); ++Loc) { - llvm::Expected<dxbc::RTS0::v3::StaticSampler> MaybeSampler = - Data.getSampler(Loc); + for (llvm::Expected<dxbc::RTS0::v3::StaticSampler> MaybeSampler : + Data.samplers()) { if (Error E = MaybeSampler.takeError()) return std::move(E); const llvm::dxbc::RTS0::v3::StaticSampler &S = *MaybeSampler; diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp index 923df70f44194..fe898c430b8a3 100644 --- a/llvm/unittests/Object/DXContainerTest.cpp +++ b/llvm/unittests/Object/DXContainerTest.cpp @@ -1184,7 +1184,7 @@ TEST(RootSignature, ParseStaticSamplers) { ASSERT_EQ(RS.getStaticSamplersOffset(), 24u); ASSERT_EQ(RS.getFlags(), 17u); - auto MaybeSamplerView = RS.getSampler(0); + auto MaybeSamplerView = *RS.samplers().begin(); ASSERT_THAT_ERROR(MaybeSamplerView.takeError(), Succeeded()); const auto &Sampler = *MaybeSamplerView; >From e530bcc1b81b300a12ada139c54553b84ab89a03 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Mon, 22 Sep 2025 11:29:55 -0700 Subject: [PATCH 06/19] this was easier than I thought --- llvm/include/llvm/Object/DXContainer.h | 62 ++--------------------- llvm/lib/Object/DXContainer.cpp | 13 +++-- llvm/lib/ObjectYAML/DXContainerYAML.cpp | 6 +-- llvm/unittests/Object/DXContainerTest.cpp | 49 ++++++++++++++++-- 4 files changed, 61 insertions(+), 69 deletions(-) diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h index e3913ece842bc..0bfc5cec48da4 100644 --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -223,28 +223,6 @@ static Error parseFailed(const Twine &Msg) { class RootSignature { private: - struct samplers_iterator { - const RootSignature *Parent = nullptr; - uint32_t Index = 0; - - llvm::Expected<dxbc::RTS0::v3::StaticSampler> operator*() const { - return Parent->getSampler(Index); - } - - samplers_iterator &operator++() { - ++Index; - return *this; - } - - bool operator==(const samplers_iterator &Other) const { - return Parent == Other.Parent && Index == Other.Index; - } - - bool operator!=(const samplers_iterator &Other) const { - return !(*this == Other); - } - }; - uint32_t Version; uint32_t NumParameters; uint32_t RootParametersOffset; @@ -253,32 +231,11 @@ class RootSignature { uint32_t Flags; ViewArray<dxbc::RTS0::v1::RootParameterHeader> ParametersHeaders; StringRef PartData; - ViewArray<dxbc::RTS0::v1::StaticSampler> StaticSamplers; - - llvm::Expected<dxbc::RTS0::v3::StaticSampler> getSampler(uint32_t Loc) const { - if (Loc >= getNumStaticSamplers()) - return parseFailed("Static sampler index out of range"); - - auto SamplerSize = (Version <= 2) ? sizeof(dxbc::RTS0::v1::StaticSampler) - : sizeof(dxbc::RTS0::v3::StaticSampler); - - StringRef Buff = PartData.substr(StaticSamplersOffset + (Loc * SamplerSize), - SamplerSize); - if (Version < 3) { - auto Sampler = readParameter<dxbc::RTS0::v1::StaticSampler>(Buff); - if (Error E = Sampler.takeError()) - return E; - return dxbc::RTS0::v3::StaticSampler(*Sampler); - } - if (Version != 3) - return make_error<GenericBinaryError>("Invalid Root Signature version: " + - Twine(Version), - object_error::parse_failed); - return readParameter<dxbc::RTS0::v3::StaticSampler>(Buff); - } + ViewArray<dxbc::RTS0::v3::StaticSampler> StaticSamplers; using param_header_iterator = ViewArray<dxbc::RTS0::v1::RootParameterHeader>::iterator; + using samplers_iterator = ViewArray<dxbc::RTS0::v3::StaticSampler>::iterator; public: RootSignature(StringRef PD) : PartData(PD) {} @@ -290,21 +247,12 @@ class RootSignature { uint32_t getNumStaticSamplers() const { return NumStaticSamplers; } uint32_t getStaticSamplersOffset() const { return StaticSamplersOffset; } uint32_t getNumRootParameters() const { return ParametersHeaders.size(); } - - samplers_iterator samplers_begin() const { - return samplers_iterator{this, 0}; - } - - samplers_iterator samplers_end() const { - return samplers_iterator{this, getNumStaticSamplers()}; + llvm::iterator_range<param_header_iterator> param_headers() const { + return llvm::make_range(ParametersHeaders.begin(), ParametersHeaders.end()); } llvm::iterator_range<samplers_iterator> samplers() const { - return llvm::make_range(samplers_begin(), samplers_end()); - } - - llvm::iterator_range<param_header_iterator> param_headers() const { - return llvm::make_range(ParametersHeaders.begin(), ParametersHeaders.end()); + return llvm::make_range(StaticSamplers.begin(), StaticSamplers.end()); } uint32_t getFlags() const { return Flags; } diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp index 031b9414f4c1a..b7da8316840f0 100644 --- a/llvm/lib/Object/DXContainer.cpp +++ b/llvm/lib/Object/DXContainer.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include <cstddef> + #include "llvm/Object/DXContainer.h" #include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Object/Error.h" @@ -276,10 +278,13 @@ Error DirectX::RootSignature::parse() { RootParametersOffset, NumParameters * sizeof(dxbc::RTS0::v1::RootParameterHeader)); - StaticSamplers.Stride = sizeof(dxbc::RTS0::v1::StaticSampler); - StaticSamplers.Data = PartData.substr( - StaticSamplersOffset, - NumStaticSamplers * sizeof(dxbc::RTS0::v1::StaticSampler)); + StaticSamplers.Stride = (Version <= 2) + ? sizeof(dxbc::RTS0::v1::StaticSampler) + : sizeof(dxbc::RTS0::v3::StaticSampler); + + StaticSamplers.Data = PartData.substr(StaticSamplersOffset, + static_cast<size_t>(NumStaticSamplers) * + StaticSamplers.Stride); return Error::success(); } diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index 91f86caaa4005..2fde1b86247f8 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -163,11 +163,7 @@ DXContainerYAML::RootSignatureYamlDesc::create( } } - for (llvm::Expected<dxbc::RTS0::v3::StaticSampler> MaybeSampler : - Data.samplers()) { - if (Error E = MaybeSampler.takeError()) - return std::move(E); - const llvm::dxbc::RTS0::v3::StaticSampler &S = *MaybeSampler; + for (const auto &S : Data.samplers()) { if (!dxbc::isValidSamplerFilter(S.Filter)) return createStringError(std::errc::invalid_argument, diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp index fe898c430b8a3..76b2aed5bb591 100644 --- a/llvm/unittests/Object/DXContainerTest.cpp +++ b/llvm/unittests/Object/DXContainerTest.cpp @@ -1184,9 +1184,7 @@ TEST(RootSignature, ParseStaticSamplers) { ASSERT_EQ(RS.getStaticSamplersOffset(), 24u); ASSERT_EQ(RS.getFlags(), 17u); - auto MaybeSamplerView = *RS.samplers().begin(); - ASSERT_THAT_ERROR(MaybeSamplerView.takeError(), Succeeded()); - const auto &Sampler = *MaybeSamplerView; + auto Sampler = *RS.samplers().begin(); ASSERT_EQ(Sampler.Filter, 10u); ASSERT_EQ(Sampler.AddressU, 1u); @@ -1202,4 +1200,49 @@ TEST(RootSignature, ParseStaticSamplers) { ASSERT_EQ(Sampler.RegisterSpace, 32u); ASSERT_EQ(Sampler.ShaderVisibility, 7u); } + { + uint8_t Buffer[] = { + 0x44, 0x58, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 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, + 0x52, 0x54, 0x53, 0x30, 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xa4, 0x70, 0x9d, 0x3f, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41, + 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00}; + DXContainer C = + llvm::cantFail(DXContainer::create(getMemoryBuffer<148>(Buffer))); + + auto MaybeRS = C.getRootSignature(); + ASSERT_TRUE(MaybeRS.has_value()); + const auto &RS = MaybeRS.value(); + ASSERT_EQ(RS.getVersion(), 3U); + ASSERT_EQ(RS.getNumParameters(), 0U); + ASSERT_EQ(RS.getRootParametersOffset(), 0U); + ASSERT_EQ(RS.getNumStaticSamplers(), 1U); + ASSERT_EQ(RS.getStaticSamplersOffset(), 24U); + ASSERT_EQ(RS.getFlags(), 17U); + + auto Sampler = *RS.samplers().begin(); + + ASSERT_EQ(Sampler.Filter, 10U); + ASSERT_EQ(Sampler.AddressU, 1U); + ASSERT_EQ(Sampler.AddressV, 2U); + ASSERT_EQ(Sampler.AddressW, 5U); + ASSERT_FLOAT_EQ(Sampler.MipLODBias, 1.23F); + ASSERT_EQ(Sampler.MaxAnisotropy, 20U); + ASSERT_EQ(Sampler.ComparisonFunc, 4U); + ASSERT_EQ(Sampler.BorderColor, 0U); + ASSERT_FLOAT_EQ(Sampler.MinLOD, 4.56F); + ASSERT_FLOAT_EQ(Sampler.MaxLOD, 8.9F); + ASSERT_EQ(Sampler.ShaderRegister, 31U); + ASSERT_EQ(Sampler.RegisterSpace, 32U); + ASSERT_EQ(Sampler.ShaderVisibility, 7U); + ASSERT_EQ(Sampler.Flags, 1U); + } } >From 79ea587527552aaf93110098b526a88edbce620b Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Mon, 22 Sep 2025 12:17:34 -0700 Subject: [PATCH 07/19] adding new test --- llvm/lib/ObjectYAML/DXContainerYAML.cpp | 2 - .../RootSignature-StaticSamplers1.3.yaml | 65 +++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 llvm/test/ObjectYAML/DXContainer/RootSignature-StaticSamplers1.3.yaml diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index 2fde1b86247f8..806722be0813d 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -211,12 +211,10 @@ DXContainerYAML::RootSignatureYamlDesc::create( NewS.ShaderVisibility = dxbc::ShaderVisibility(S.ShaderVisibility); if (Version > 2) { - if (Version > 1) { #define STATIC_SAMPLER_FLAG(Num, Enum, Flag) \ NewS.Enum = \ (S.Flags & llvm::to_underlying(dxbc::StaticSamplerFlags::Enum)) > 0; #include "llvm/BinaryFormat/DXContainerConstants.def" - } } RootSigDesc.StaticSamplers.push_back(NewS); } diff --git a/llvm/test/ObjectYAML/DXContainer/RootSignature-StaticSamplers1.3.yaml b/llvm/test/ObjectYAML/DXContainer/RootSignature-StaticSamplers1.3.yaml new file mode 100644 index 0000000000000..1623b05def009 --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/RootSignature-StaticSamplers1.3.yaml @@ -0,0 +1,65 @@ +# 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: 3 + NumRootParameters: 0 + RootParametersOffset: 24 + NumStaticSamplers: 1 + StaticSamplersOffset: 24 + Parameters: [] + Samplers: + - Filter: MinLinearMagMipPoint + AddressU: Wrap + AddressV: Mirror + AddressW: MirrorOnce + MipLODBias: 1.23 + MaxAnisotropy: 20 + ComparisonFunc: LessEqual + BorderColor: TransparentBlack + MinLOD: 4.56 + MaxLOD: 8.90 + ShaderRegister: 31 + RegisterSpace: 32 + ShaderVisibility: Mesh + SAMPLER_FLAG_UINT_BORDER_COLOR: true + AllowInputAssemblerInputLayout: true + DenyGeometryShaderRootAccess: true + +#CHECK: - Name: RTS0 +#CHECK-NEXT: Size: 80 +#CHECK-NEXT: RootSignature: +#CHECK-NEXT: Version: 3 +#CHECK-NEXT: NumRootParameters: 0 +#CHECK-NEXT: RootParametersOffset: 24 +#CHECK-NEXT: NumStaticSamplers: 1 +#CHECK-NEXT: StaticSamplersOffset: 24 +#CHECK-NEXT: Parameters: [] +#CHECK-NEXT: Samplers: +#CHECK-NEXT: - Filter: MinLinearMagMipPoint +#CHECK-NEXT: AddressU: Wrap +#CHECK-NEXT: AddressV: Mirror +#CHECK-NEXT: AddressW: MirrorOnce +#CHECK-NEXT: MipLODBias: 1.23 +#CHECK-NEXT: MaxAnisotropy: 20 +#CHECK-NEXT: ComparisonFunc: LessEqual +#CHECK-NEXT: BorderColor: TransparentBlack +#CHECK-NEXT: MinLOD: 4.56 +#CHECK-NEXT: MaxLOD: 8.9 +#CHECK-NEXT: ShaderRegister: 31 +#CHECK-NEXT: RegisterSpace: 32 +#CHECK-NEXT: ShaderVisibility: Mesh +#CHECK-NEXT: SAMPLER_FLAG_UINT_BORDER_COLOR: true +#CHECK-NEXT: AllowInputAssemblerInputLayout: true +#CHECK-NEXT: DenyGeometryShaderRootAccess: true >From 905d5d39d93e35a512537bec76566abefc79ce27 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Mon, 22 Sep 2025 12:32:25 -0700 Subject: [PATCH 08/19] clean up --- llvm/include/llvm/Object/DXContainer.h | 33 +++++++++++------------ llvm/lib/Object/DXContainer.cpp | 2 -- llvm/lib/ObjectYAML/DXContainerYAML.cpp | 1 - llvm/unittests/Object/DXContainerTest.cpp | 2 +- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h index 0bfc5cec48da4..6f10401dd2ba2 100644 --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -124,25 +124,25 @@ template <typename T> struct ViewArray { namespace DirectX { -template <typename T> Expected<T> readParameter(StringRef Data) { - T Struct; - if (sizeof(T) != Data.size()) - return make_error<GenericBinaryError>( - "Reading structure out of file bounds", object_error::parse_failed); - - memcpy(&Struct, Data.data(), sizeof(T)); - // DXContainer is always little endian - if (sys::IsBigEndianHost) - Struct.swapBytes(); - return Struct; -} - struct RootParameterView { const dxbc::RTS0::v1::RootParameterHeader &Header; StringRef ParamData; RootParameterView(const dxbc::RTS0::v1::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 { @@ -152,7 +152,7 @@ struct RootConstantView : RootParameterView { } llvm::Expected<dxbc::RTS0::v1::RootConstants> read() { - return readParameter<dxbc::RTS0::v1::RootConstants>(ParamData); + return readParameter<dxbc::RTS0::v1::RootConstants>(); } }; @@ -168,8 +168,7 @@ struct RootDescriptorView : RootParameterView { llvm::Expected<dxbc::RTS0::v2::RootDescriptor> read(uint32_t Version) { if (Version == 1) { - auto Descriptor = - readParameter<dxbc::RTS0::v1::RootDescriptor>(ParamData); + auto Descriptor = readParameter<dxbc::RTS0::v1::RootDescriptor>(); if (Error E = Descriptor.takeError()) return E; return dxbc::RTS0::v2::RootDescriptor(*Descriptor); @@ -178,7 +177,7 @@ struct RootDescriptorView : RootParameterView { return make_error<GenericBinaryError>("Invalid Root Signature version: " + Twine(Version), object_error::parse_failed); - return readParameter<dxbc::RTS0::v2::RootDescriptor>(ParamData); + return readParameter<dxbc::RTS0::v2::RootDescriptor>(); } }; diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp index b7da8316840f0..7b7b8d88c63fc 100644 --- a/llvm/lib/Object/DXContainer.cpp +++ b/llvm/lib/Object/DXContainer.cpp @@ -6,8 +6,6 @@ // //===----------------------------------------------------------------------===// -#include <cstddef> - #include "llvm/Object/DXContainer.h" #include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Object/Error.h" diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index 806722be0813d..bfb3837707f0a 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -164,7 +164,6 @@ DXContainerYAML::RootSignatureYamlDesc::create( } for (const auto &S : Data.samplers()) { - if (!dxbc::isValidSamplerFilter(S.Filter)) return createStringError(std::errc::invalid_argument, "Invalid value for static sampler filter"); diff --git a/llvm/unittests/Object/DXContainerTest.cpp b/llvm/unittests/Object/DXContainerTest.cpp index 76b2aed5bb591..7fec8addc8d52 100644 --- a/llvm/unittests/Object/DXContainerTest.cpp +++ b/llvm/unittests/Object/DXContainerTest.cpp @@ -1172,7 +1172,7 @@ TEST(RootSignature, ParseStaticSamplers) { 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0x91, 0x40, 0x66, 0x66, 0x0e, 0x41, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00}; DXContainer C = - llvm::cantFail(DXContainer::create(getMemoryBuffer<144>(Buffer))); + llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer))); auto MaybeRS = C.getRootSignature(); ASSERT_TRUE(MaybeRS.has_value()); >From b73bf248c1225498e6372d25f8e75ce6a03d5489 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Mon, 22 Sep 2025 12:33:59 -0700 Subject: [PATCH 09/19] clean up --- llvm/include/llvm/Object/DXContainer.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h index 6f10401dd2ba2..5a5a4dbaae2ad 100644 --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -123,7 +123,6 @@ template <typename T> struct ViewArray { }; namespace DirectX { - struct RootParameterView { const dxbc::RTS0::v1::RootParameterHeader &Header; StringRef ParamData; @@ -180,7 +179,6 @@ struct RootDescriptorView : RootParameterView { return readParameter<dxbc::RTS0::v2::RootDescriptor>(); } }; - template <typename T> struct DescriptorTable { uint32_t NumRanges; uint32_t RangesOffset; @@ -249,11 +247,9 @@ class RootSignature { llvm::iterator_range<param_header_iterator> param_headers() const { return llvm::make_range(ParametersHeaders.begin(), ParametersHeaders.end()); } - llvm::iterator_range<samplers_iterator> samplers() const { return llvm::make_range(StaticSamplers.begin(), StaticSamplers.end()); } - uint32_t getFlags() const { return Flags; } llvm::Expected<RootParameterView> >From bc393fda07547bbd8abc24701c8bfc3495db2e89 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Mon, 22 Sep 2025 16:49:12 -0700 Subject: [PATCH 10/19] adding flags to static sampler parser --- .../clang/Lex/HLSLRootSignatureTokenKinds.def | 8 +++ .../clang/Parse/ParseHLSLRootSignature.h | 3 + clang/lib/Parse/ParseHLSLRootSignature.cpp | 61 +++++++++++++++++++ .../Lex/LexHLSLRootSignatureTest.cpp | 3 + .../llvm/Frontend/HLSL/HLSLRootSignature.h | 1 + llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 2 +- 6 files changed, 77 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def index a5cfeb34b2b51..1d7f7adbe076f 100644 --- a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def +++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def @@ -65,6 +65,9 @@ #ifndef STATIC_BORDER_COLOR_ENUM #define STATIC_BORDER_COLOR_ENUM(NAME, LIT) ENUM(NAME, LIT) #endif +#ifndef STATIC_SAMPLER_FLAG_ENUM +#define STATIC_SAMPLER_FLAG_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif // General Tokens: TOK(invalid, "invalid identifier") @@ -228,6 +231,10 @@ STATIC_BORDER_COLOR_ENUM(OpaqueWhite, "STATIC_BORDER_COLOR_OPAQUE_WHITE") STATIC_BORDER_COLOR_ENUM(OpaqueBlackUint, "STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT") STATIC_BORDER_COLOR_ENUM(OpaqueWhiteUint, "STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT") +// Root Descriptor Flag Enums: +STATIC_SAMPLER_FLAG_ENUM(UintBorderColor, "UINT_BORDER_COLOR") +STATIC_SAMPLER_FLAG_ENUM(NonNormalizedCoordinates, "NON_NORMALIZED_COORDINATES") + #undef STATIC_BORDER_COLOR_ENUM #undef COMPARISON_FUNC_ENUM #undef TEXTURE_ADDRESS_MODE_ENUM @@ -237,6 +244,7 @@ STATIC_BORDER_COLOR_ENUM(OpaqueWhiteUint, "STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT #undef DESCRIPTOR_RANGE_FLAG_ENUM_OFF #undef DESCRIPTOR_RANGE_FLAG_ENUM_ON #undef ROOT_DESCRIPTOR_FLAG_ENUM +#undef STATIC_SAMPLER_FLAG_ENUM #undef ROOT_FLAG_ENUM #undef DESCRIPTOR_RANGE_OFFSET_ENUM #undef UNBOUNDED_ENUM diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index b06846fd83c09..8f91d7cd7b031 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -130,6 +130,7 @@ class RootSignatureParser { std::optional<float> MaxLOD; std::optional<uint32_t> Space; std::optional<llvm::dxbc::ShaderVisibility> Visibility; + std::optional<llvm::dxbc::StaticSamplerFlags> Flags; }; std::optional<ParsedStaticSamplerParams> parseStaticSamplerParams(); @@ -153,6 +154,8 @@ class RootSignatureParser { parseRootDescriptorFlags(RootSignatureToken::Kind Context); std::optional<llvm::dxbc::DescriptorRangeFlags> parseDescriptorRangeFlags(RootSignatureToken::Kind Context); + std::optional<llvm::dxbc::StaticSamplerFlags> + parseStaticSamplerFlags(RootSignatureToken::Kind Context); /// Use NumericLiteralParser to convert CurToken.NumSpelling into a unsigned /// 32-bit integer diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 3b16efb1f1199..5677365688413 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -485,6 +485,9 @@ std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() { if (Params->Visibility.has_value()) Sampler.Visibility = Params->Visibility.value(); + if (Params->Flags.has_value()) + Sampler.Flags = Params->Flags.value(); + return Sampler; } @@ -926,6 +929,20 @@ RootSignatureParser::parseStaticSamplerParams() { if (!Visibility.has_value()) return std::nullopt; Params.Visibility = Visibility; + } else if (tryConsumeExpectedToken(TokenKind::kw_flags)) { + // `flags` `=` UINT_BORDER_COLOR + if (Params.Flags.has_value()) { + reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind; + return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) + return std::nullopt; + + auto Flags = parseStaticSamplerFlags(TokenKind::kw_flags); + if (!Flags.has_value()) + return std::nullopt; + Params.Flags = Flags; } else { consumeNextToken(); // let diagnostic be at the start of invalid token reportDiag(diag::err_hlsl_invalid_token) @@ -1255,6 +1272,50 @@ RootSignatureParser::parseDescriptorRangeFlags(TokenKind Context) { return Flags; } +std::optional<llvm::dxbc::StaticSamplerFlags> +RootSignatureParser::parseStaticSamplerFlags(TokenKind Context) { + assert(CurToken.TokKind == TokenKind::pu_equal && + "Expects to only be invoked starting at given keyword"); + + // Handle the edge-case of '0' to specify no flags set + if (tryConsumeExpectedToken(TokenKind::int_literal)) { + if (!verifyZeroFlag()) { + reportDiag(diag::err_hlsl_rootsig_non_zero_flag); + return std::nullopt; + } + return llvm::dxbc::StaticSamplerFlags::None; + } + + TokenKind Expected[] = { +#define STATIC_SAMPLER_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME, +#include "clang/Lex/HLSLRootSignatureTokenKinds.def" + }; + + std::optional<llvm::dxbc::StaticSamplerFlags> Flags; + + do { + if (tryConsumeExpectedToken(Expected)) { + switch (CurToken.TokKind) { +#define STATIC_SAMPLER_FLAG_ENUM(NAME, LIT) \ + case TokenKind::en_##NAME: \ + Flags = maybeOrFlag<llvm::dxbc::StaticSamplerFlags>( \ + Flags, llvm::dxbc::StaticSamplerFlags::NAME); \ + break; +#include "clang/Lex/HLSLRootSignatureTokenKinds.def" + default: + llvm_unreachable("Switch for consumed enum token was not provided"); + } + } else { + consumeNextToken(); // consume token to point at invalid token + reportDiag(diag::err_hlsl_invalid_token) + << /*value=*/1 << /*value of*/ Context; + return std::nullopt; + } + } while (tryConsumeExpectedToken(TokenKind::pu_or)); + + return Flags; +} + std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() { // Parse the numeric value and do semantic checks on its specification clang::NumericLiteralParser Literal( diff --git a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp index 01f8d4f97b092..82f19686167da 100644 --- a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp +++ b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp @@ -226,6 +226,9 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) { STATIC_BORDER_COLOR_OPAQUE_WHITE STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT + + UINT_BORDER_COLOR + NON_NORMALIZED_COORDINATES )cc"; hlsl::RootSignatureLexer Lexer(Source); diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 87777fddc9157..37224d8a94527 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -131,6 +131,7 @@ struct StaticSampler { float MaxLOD = std::numeric_limits<float>::max(); uint32_t Space = 0; dxbc::ShaderVisibility Visibility = dxbc::ShaderVisibility::All; + dxbc::StaticSamplerFlags Flags = dxbc::StaticSamplerFlags::None; }; /// Models RootElement : RootFlags | RootConstants | RootParam diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index 92c62b83fadb0..f9129adb4a4f9 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -172,7 +172,7 @@ raw_ostream &operator<<(raw_ostream &OS, const StaticSampler &Sampler) { << ", borderColor = " << Sampler.BorderColor << ", minLOD = " << Sampler.MinLOD << ", maxLOD = " << Sampler.MaxLOD << ", space = " << Sampler.Space << ", visibility = " << Sampler.Visibility - << ")"; + << ", flags = " << Sampler.Flags << ")"; return OS; } >From e8f7b949d921c8d180d38a923fd307e70f55d711 Mon Sep 17 00:00:00 2001 From: joaosaffran <joao.saff...@microsoft.com> Date: Tue, 23 Sep 2025 18:34:39 +0000 Subject: [PATCH 11/19] add tests --- clang/test/CodeGenHLSL/RootSignature.hlsl | 5 +-- .../Parse/ParseHLSLRootSignatureTest.cpp | 34 ++++++++++++++++++- .../Frontend/HLSL/RootSignatureMetadata.cpp | 1 + 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index bc40bdd79ce59..eaff3a9e73305 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -82,8 +82,8 @@ void RootDescriptorsEntry() {} // checking minLOD, maxLOD // CHECK-SAME: float -1.280000e+02, float 1.280000e+02, -// checking register, space and visibility -// CHECK-SAME: i32 42, i32 0, i32 0} +// checking register, space, visibility and flag +// CHECK-SAME: i32 42, i32 0, i32 0, i32 1} #define SampleStaticSampler \ "StaticSampler(s42, " \ @@ -96,6 +96,7 @@ void RootDescriptorsEntry() {} " borderColor = STATIC_BORDER_COLOR_OPAQUE_WHITE, " \ " minLOD = -128.f, maxLOD = 128.f, " \ " space = 0, visibility = SHADER_VISIBILITY_ALL, " \ + " flags = UINT_BORDER_COLOR" \ ")" [shader("compute"), RootSignature(SampleStaticSampler)] [numthreads(1,1,1)] diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp index 9b9f5dd8a63bb..f7e9d2d32c3f4 100644 --- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp +++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp @@ -263,7 +263,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { filter = FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT, maxLOD = 9000, addressU = TEXTURE_ADDRESS_MIRROR, comparisonFunc = COMPARISON_NOT_EQUAL, - borderColor = STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT + borderColor = STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT, + flags = 0 ) )cc"; @@ -336,6 +337,37 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { ASSERT_TRUE(Consumer->isSatisfied()); } +TEST_F(ParseHLSLRootSignatureTest, ValidStaticSamplerFlagsTest) { + const llvm::StringLiteral Source = R"cc( + StaticSampler(s0, flags = UINT_BORDER_COLOR | NON_NORMALIZED_COORDINATES) + )cc"; + + auto Ctx = createMinimalASTContext(); + StringLiteral *Signature = wrapSource(Ctx, Source); + + TrivialModuleLoader ModLoader; + auto PP = createPP(Source, ModLoader); + + hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP); + + // Test no diagnostics produced + Consumer->setNoDiag(); + + ASSERT_FALSE(Parser.parse()); + + auto Elements = Parser.getElements(); + ASSERT_EQ(Elements.size(), 1u); + + RootElement Elem = Elements[0].getElement(); + ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem)); + auto ValidStaticSamplerFlags = + llvm::dxbc::StaticSamplerFlags::NonNormalizedCoordinates | + llvm::dxbc::StaticSamplerFlags::UintBorderColor; + ASSERT_EQ(std::get<StaticSampler>(Elem).Flags, ValidStaticSamplerFlags); + + ASSERT_TRUE(Consumer->isSatisfied()); +} + TEST_F(ParseHLSLRootSignatureTest, ValidParseFloatsTest) { const llvm::StringLiteral Source = R"cc( StaticSampler(s0, mipLODBias = 0), diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index f29f2c7602fc6..e2a1f242bfc8e 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -212,6 +212,7 @@ MDNode *MetadataBuilder::BuildStaticSampler(const StaticSampler &Sampler) { ConstantAsMetadata::get(Builder.getInt32(Sampler.Space)), ConstantAsMetadata::get( Builder.getInt32(to_underlying(Sampler.Visibility))), + ConstantAsMetadata::get(Builder.getInt32(to_underlying(Sampler.Flags))), }; return MDNode::get(Ctx, Operands); } >From 589668e1c87b45e4a551451c7ae0c745b8dad625 Mon Sep 17 00:00:00 2001 From: joaosaffran <joao.saff...@microsoft.com> Date: Wed, 24 Sep 2025 05:51:24 +0000 Subject: [PATCH 12/19] adding more test --- llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp index 1eb03f16527ec..abdd8a6a21112 100644 --- a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp +++ b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp @@ -266,7 +266,8 @@ TEST(HLSLRootSignatureTest, DefaultStaticSamplerDump) { "minLOD = 0.000000e+00, " "maxLOD = 3.402823e+38, " "space = 0, " - "visibility = All" + "visibility = All, " + "flags = 0x0" ")"; EXPECT_EQ(Out, Expected); } @@ -287,6 +288,7 @@ TEST(HLSLRootSignatureTest, DefinedStaticSamplerDump) { Sampler.MaxLOD = 32.0f; Sampler.Space = 7; Sampler.Visibility = llvm::dxbc::ShaderVisibility::Domain; + Sampler.Flags = llvm::dxbc::StaticSamplerFlags::NonNormalizedCoordinates; std::string Out; llvm::raw_string_ostream OS(Out); @@ -305,7 +307,8 @@ TEST(HLSLRootSignatureTest, DefinedStaticSamplerDump) { "minLOD = 1.000000e+00, " "maxLOD = 3.200000e+01, " "space = 7, " - "visibility = Domain" + "visibility = Domain, " + "flags = 0x2" ")"; EXPECT_EQ(Out, Expected); } >From e8b973fb9c0a3fccefc1299448c7c3bd322e52a2 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Thu, 25 Sep 2025 10:21:11 -0700 Subject: [PATCH 13/19] adding operator << to print StaticSamplerFlags --- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index f9129adb4a4f9..5dbec8063dd77 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -113,6 +113,14 @@ static raw_ostream &operator<<(raw_ostream &OS, return OS; } +static raw_ostream &operator<<(raw_ostream &OS, + const llvm::dxbc::StaticSamplerFlags &Flags) { + printFlags(OS, Flags, dxbc::getStaticSamplerFlags()); + + return OS; +} + + raw_ostream &operator<<(raw_ostream &OS, const dxbc::RootFlags &Flags) { OS << "RootFlags("; printFlags(OS, Flags, dxbc::getRootFlags()); >From 190cfcde07640fc9d6f06171dd4d8f8d5b664765 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Thu, 25 Sep 2025 10:21:35 -0700 Subject: [PATCH 14/19] updating comment with inbelic suggestion --- clang/lib/Parse/ParseHLSLRootSignature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 5677365688413..7be6eecc520b1 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -930,7 +930,7 @@ RootSignatureParser::parseStaticSamplerParams() { return std::nullopt; Params.Visibility = Visibility; } else if (tryConsumeExpectedToken(TokenKind::kw_flags)) { - // `flags` `=` UINT_BORDER_COLOR + // `flags` `=` STATIC_SAMPLE_FLAGS if (Params.Flags.has_value()) { reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind; return std::nullopt; >From 79e9564613c700c9f1dbee8e7aa2b052ab6ff72d Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Thu, 25 Sep 2025 10:21:52 -0700 Subject: [PATCH 15/19] format --- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index 5dbec8063dd77..2b33e560d74ac 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -120,7 +120,6 @@ static raw_ostream &operator<<(raw_ostream &OS, return OS; } - raw_ostream &operator<<(raw_ostream &OS, const dxbc::RootFlags &Flags) { OS << "RootFlags("; printFlags(OS, Flags, dxbc::getRootFlags()); >From 1b1c37dfb518f7d5d2a5180b73100e2d1326c3a0 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Thu, 25 Sep 2025 12:32:34 -0700 Subject: [PATCH 16/19] fix test --- llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp index abdd8a6a21112..451c376219c38 100644 --- a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp +++ b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp @@ -267,7 +267,7 @@ TEST(HLSLRootSignatureTest, DefaultStaticSamplerDump) { "maxLOD = 3.402823e+38, " "space = 0, " "visibility = All, " - "flags = 0x0" + "flags = None" ")"; EXPECT_EQ(Out, Expected); } @@ -308,7 +308,7 @@ TEST(HLSLRootSignatureTest, DefinedStaticSamplerDump) { "maxLOD = 3.200000e+01, " "space = 7, " "visibility = Domain, " - "flags = 0x2" + "flags = NonNormalizedCoordinates" ")"; EXPECT_EQ(Out, Expected); } >From daa5714d7506b8482a9c43247ccb9bbbf2820591 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Thu, 25 Sep 2025 12:33:20 -0700 Subject: [PATCH 17/19] update Root Signature Version flag --- clang/include/clang/Basic/LangOptions.h | 2 +- clang/include/clang/Driver/Options.td | 8 ++++---- clang/lib/AST/TextNodeDumper.cpp | 3 +++ clang/lib/Driver/ToolChains/HLSL.cpp | 2 +- clang/test/AST/HLSL/RootSignature-Target-AST.hlsl | 10 +++++++++- clang/test/AST/HLSL/RootSignatures-AST.hlsl | 10 +++++++++- clang/test/AST/HLSL/rootsignature-define-ast.hlsl | 6 +++--- clang/test/CodeGenHLSL/RootSignature-Target.hlsl | 2 +- clang/test/CodeGenHLSL/RootSignature.hlsl | 12 ++++++------ clang/test/Driver/dxc_rootsig-define.hlsl | 2 +- llvm/include/llvm/BinaryFormat/DXContainer.h | 1 + llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h | 4 ++-- llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp | 2 +- llvm/lib/ObjectYAML/DXContainerYAML.cpp | 2 +- 14 files changed, 43 insertions(+), 23 deletions(-) diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index a8943df5b39aa..280746fd4edeb 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -550,7 +550,7 @@ class LangOptions : public LangOptionsBase { /// The HLSL root signature version for dxil. llvm::dxbc::RootSignatureVersion HLSLRootSigVer = - llvm::dxbc::RootSignatureVersion::V1_1; + llvm::dxbc::RootSignatureVersion::V1_2; /// The HLSL root signature that will be used to overide the root signature /// used for the shader entry point. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 16e1c396fedbe..c1b8928cf0528 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -9456,7 +9456,7 @@ def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"<profile>">, "lib_6_3, lib_6_4, lib_6_5, lib_6_6, lib_6_7, lib_6_x," "ms_6_5, ms_6_6, ms_6_7," "as_6_5, as_6_6, as_6_7," - "rootsig_1_0, rootsig_1_1">; + "rootsig_1_0, rootsig_1_1, rootsig_1_2">; def emit_pristine_llvm : DXCFlag<"emit-pristine-llvm">, HelpText<"Emit pristine LLVM IR from the frontend by not running any LLVM passes at all." "Same as -S + -emit-llvm + -disable-llvm-passes.">; @@ -9469,10 +9469,10 @@ def fdx_rootsignature_version : Group<dxc_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Root Signature Version">, - Values<"rootsig_1_0,rootsig_1_1">, + Values<"rootsig_1_0,rootsig_1_1,rootsig_1_2">, NormalizedValuesScope<"llvm::dxbc::RootSignatureVersion">, - NormalizedValues<["V1_0", "V1_1"]>, - MarshallingInfoEnum<LangOpts<"HLSLRootSigVer">, "V1_1">; + NormalizedValues<["V1_0", "V1_1", "V1_2"]>, + MarshallingInfoEnum<LangOpts<"HLSLRootSigVer">, "V1_2">; def dxc_rootsig_ver : Separate<["/", "-"], "force-rootsig-ver">, Alias<fdx_rootsignature_version>, diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 8f7fe3bea4e8f..cf5e9147ad78b 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -3095,6 +3095,9 @@ void TextNodeDumper::VisitHLSLRootSignatureDecl( case llvm::dxbc::RootSignatureVersion::V1_1: OS << "1.1"; break; + case llvm::dxbc::RootSignatureVersion::V1_2: + OS << "1.2"; + break; } OS << ", "; llvm::hlsl::rootsig::dumpRootElements(OS, D->getRootElements()); diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index f4858e4c960de..2869549e6b3f0 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -64,7 +64,7 @@ bool isLegalShaderModel(Triple &T) { } break; case Triple::EnvironmentType::RootSignature: VersionTuple MinVer(1, 0); - VersionTuple MaxVer(1, 1); + VersionTuple MaxVer(1, 2); return MinVer <= Version && Version <= MaxVer; } return false; diff --git a/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl b/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl index 91441e32e047d..b5c71a86b7e48 100644 --- a/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl +++ b/clang/test/AST/HLSL/RootSignature-Target-AST.hlsl @@ -1,10 +1,16 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \ +// RUN: -fdx-rootsignature-version=rootsig_1_1 \ // RUN: -hlsl-entry EntryRootSig -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_1 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \ // RUN: -fdx-rootsignature-version=rootsig_1_0 \ // RUN: -hlsl-entry EntryRootSig -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_0 +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \ +// RUN: -fdx-rootsignature-version=rootsig_1_2 \ +// RUN: -hlsl-entry EntryRootSig -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_2 + + // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-rootsignature -ast-dump \ // RUN: -D CmdRS='"UAV(u0)"'\ // RUN: -hlsl-entry CmdRS -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CMD @@ -12,17 +18,19 @@ // CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[ENTRY_RS_DECL:__hlsl_rootsig_decl_\d*]] // CHECK-V1_0-SAME: version: 1.0, // CHECK-V1_1-SAME: version: 1.1, +// CHECK-V1_2-SAME: version: 1.2, // CHECK-SAME: RootElements{ // CHECK-SAME: RootCBV(b0, // CHECK-SAME: space = 0, visibility = All, // CHECK-V1_0-SAME: flags = DataVolatile // CHECK-V1_1-SAME: flags = DataStaticWhileSetAtExecute +// CHECK-V1_2-SAME: flags = DataStaticWhileSetAtExecute // CHECK-SAME: ) // CHECK-SAME: } #define EntryRootSig "CBV(b0)" // CMD: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[CMD_RS_DECL:__hlsl_rootsig_decl_\d*]] -// CMD-SAME: version: 1.1, +// CMD-SAME: version: 1.2, // CMD-SAME: RootElements{ // CMD-SAME: RootUAV(u0, space = 0, visibility = All, flags = DataVolatile) // CMD-SAME: } diff --git a/clang/test/AST/HLSL/RootSignatures-AST.hlsl b/clang/test/AST/HLSL/RootSignatures-AST.hlsl index 32da1f14853b0..f0c1a0d4ad58b 100644 --- a/clang/test/AST/HLSL/RootSignatures-AST.hlsl +++ b/clang/test/AST/HLSL/RootSignatures-AST.hlsl @@ -1,11 +1,14 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \ -// RUN: -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_1 +// RUN: -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_2 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \ // RUN: -fdx-rootsignature-version=rootsig_1_0 \ // RUN: -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_0 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \ // RUN: -fdx-rootsignature-version=rootsig_1_1 \ // RUN: -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_1 +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \ +// RUN: -fdx-rootsignature-version=rootsig_1_2 \ +// RUN: -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-V1_2 // This test ensures that the sample root signature is parsed without error and // the Attr AST Node is created succesfully. If an invalid root signature was @@ -31,6 +34,7 @@ // CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[SAMPLE_RS_DECL:__hlsl_rootsig_decl_\d*]] // CHECK-V1_0: version: 1.0, // CHECK-V1_1: version: 1.1, +// CHECK-V1_2: version: 1.2, // CHECK-SAME: RootElements{ // CHECK-SAME: RootFlags(AllowInputAssemblerInputLayout | DenyVertexShaderRootAccess), // CHECK-SAME: RootCBV(b0, @@ -62,6 +66,7 @@ // CHECK-SAME: s0, numDescriptors = 4, space = 1, offset = DescriptorTableOffsetAppend, // CHECK-V1_0-SAME: flags = DescriptorsVolatile // CHECK-V1_1-SAME: flags = None +// CHECK-V1_2-SAME: flags = None // CHECK-SAME: ), // CHECK-SAME: DescriptorTable( // CHECK-SAME: numClauses = 1, visibility = All @@ -73,6 +78,9 @@ // CHECK-SAME: s1, filter = Anisotropic, addressU = Wrap, addressV = Wrap, addressW = Wrap, // CHECK-SAME: mipLODBias = 0.000000e+00, maxAnisotropy = 16, comparisonFunc = LessEqual, // CHECK-SAME: borderColor = OpaqueWhite, minLOD = 0.000000e+00, maxLOD = 3.402823e+38, space = 0, visibility = All +// CHECK-V1_0-SAME: flags = None +// CHECK-V1_1-SAME: flags = None +// CHECK-V1_2-SAME: flags = None // CHECK-SAME: )} // CHECK: -RootSignatureAttr 0x{{.*}} {{.*}} [[SAMPLE_RS_DECL]] diff --git a/clang/test/AST/HLSL/rootsignature-define-ast.hlsl b/clang/test/AST/HLSL/rootsignature-define-ast.hlsl index 9c17cbc9ad2eb..508670175d1f5 100644 --- a/clang/test/AST/HLSL/rootsignature-define-ast.hlsl +++ b/clang/test/AST/HLSL/rootsignature-define-ast.hlsl @@ -21,13 +21,13 @@ #define SampleUAV "UAV(u0)" // CMD: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[CMD_DECL:__hlsl_rootsig_decl_\d*]] -// CMD-SAME: version: 1.1, RootElements{ +// CMD-SAME: version: 1.2, RootElements{ // CMD-SAME: RootSRV(t0, // CMD-SAME: space = 0, visibility = All, flags = DataStaticWhileSetAtExecute // CMD-SAME: )} // CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[CBV_DECL:__hlsl_rootsig_decl_\d*]] -// CHECK-SAME: version: 1.1, RootElements{ +// CHECK-SAME: version: 1.2, RootElements{ // CHECK-SAME: RootCBV(b0, // CHECK-SAME: space = 0, visibility = All, flags = DataStaticWhileSetAtExecute // CHECK-SAME: )} @@ -41,7 +41,7 @@ void cbv_main() {} // CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[UAV_DECL:__hlsl_rootsig_decl_\d*]] -// CHECK-SAME: version: 1.1, RootElements{ +// CHECK-SAME: version: 1.2, RootElements{ // CHECK-SAME: RootUAV(u0, // CHECK-SAME: space = 0, visibility = All, flags = DataVolatile // CHECK-SAME: )} diff --git a/clang/test/CodeGenHLSL/RootSignature-Target.hlsl b/clang/test/CodeGenHLSL/RootSignature-Target.hlsl index 50e6bae6786f0..b1b88081ded8c 100644 --- a/clang/test/CodeGenHLSL/RootSignature-Target.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature-Target.hlsl @@ -2,7 +2,7 @@ // RUN: -hlsl-entry EntryRS -emit-llvm -o - %s | FileCheck %s // CHECK: !dx.rootsignatures = !{![[#ENTRY:]]} -// CHECK: ![[#ENTRY]] = !{null, ![[#ENTRY_RS:]], i32 2} +// CHECK: ![[#ENTRY]] = !{null, ![[#ENTRY_RS:]], i32 3} // CHECK: ![[#ENTRY_RS]] = !{![[#ROOT_CBV:]]} // CHECK: ![[#ROOT_CBV]] = !{!"RootCBV", i32 0, i32 0, i32 0, i32 4} diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index eaff3a9e73305..da257ed9f5734 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -3,14 +3,14 @@ // CHECK: !dx.rootsignatures = !{![[#EMPTY_ENTRY:]], ![[#DT_ENTRY:]], // CHECK-SAME: ![[#RF_ENTRY:]], ![[#RC_ENTRY:]], ![[#RD_ENTRY:]], ![[#SS_ENTRY:]]} -// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]], i32 2} +// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]], i32 3} // CHECK: ![[#EMPTY]] = !{} [shader("compute"), RootSignature("")] [numthreads(1,1,1)] void EmptyEntry() {} -// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]], i32 2} +// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]], i32 3} // CHECK: ![[#DT_RS]] = !{![[#TABLE:]]} // CHECK: ![[#TABLE]] = !{!"DescriptorTable", i32 0, ![[#CBV:]], ![[#SRV:]]} // CHECK: ![[#CBV]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4} @@ -25,7 +25,7 @@ void EmptyEntry() {} [numthreads(1,1,1)] void DescriptorTableEntry() {} -// CHECK: ![[#RF_ENTRY]] = !{ptr @RootFlagsEntry, ![[#RF_RS:]], i32 2} +// CHECK: ![[#RF_ENTRY]] = !{ptr @RootFlagsEntry, ![[#RF_RS:]], i32 3} // CHECK: ![[#RF_RS]] = !{![[#ROOT_FLAGS:]]} // CHECK: ![[#ROOT_FLAGS]] = !{!"RootFlags", i32 2114} @@ -38,7 +38,7 @@ void DescriptorTableEntry() {} [numthreads(1,1,1)] void RootFlagsEntry() {} -// CHECK: ![[#RC_ENTRY]] = !{ptr @RootConstantsEntry, ![[#RC_RS:]], i32 2} +// CHECK: ![[#RC_ENTRY]] = !{ptr @RootConstantsEntry, ![[#RC_RS:]], i32 3} // CHECK: ![[#RC_RS]] = !{![[#ROOT_CONSTANTS:]]} // CHECK: ![[#ROOT_CONSTANTS]] = !{!"RootConstants", i32 5, i32 1, i32 2, i32 1} @@ -52,7 +52,7 @@ void RootFlagsEntry() {} [numthreads(1,1,1)] void RootConstantsEntry() {} -// CHECK: ![[#RD_ENTRY]] = !{ptr @RootDescriptorsEntry, ![[#RD_RS:]], i32 2} +// CHECK: ![[#RD_ENTRY]] = !{ptr @RootDescriptorsEntry, ![[#RD_RS:]], i32 3} // CHECK: ![[#RD_RS]] = !{![[#ROOT_CBV:]], ![[#ROOT_UAV:]], ![[#ROOT_SRV:]]} // CHECK: ![[#ROOT_CBV]] = !{!"RootCBV", i32 0, i32 0, i32 0, i32 4} // CHECK: ![[#ROOT_UAV]] = !{!"RootUAV", i32 0, i32 42, i32 3, i32 2} @@ -66,7 +66,7 @@ void RootConstantsEntry() {} [numthreads(1,1,1)] void RootDescriptorsEntry() {} -// CHECK: ![[#SS_ENTRY]] = !{ptr @StaticSamplerEntry, ![[#SS_RS:]], i32 2} +// CHECK: ![[#SS_ENTRY]] = !{ptr @StaticSamplerEntry, ![[#SS_RS:]], i32 3} // CHECK: ![[#SS_RS]] = !{![[#STATIC_SAMPLER:]]} // checking filter = 0x4 diff --git a/clang/test/Driver/dxc_rootsig-define.hlsl b/clang/test/Driver/dxc_rootsig-define.hlsl index 40c3e127f94d5..f9eb8c2e4c1ea 100644 --- a/clang/test/Driver/dxc_rootsig-define.hlsl +++ b/clang/test/Driver/dxc_rootsig-define.hlsl @@ -18,7 +18,7 @@ #define NotEmptyRS "CBV(b0)" // CHECK: !dx.rootsignatures = !{![[#ENTRY:]]} -// CHECK: ![[#ENTRY]] = !{ptr @main, ![[#RS:]], i32 2} +// CHECK: ![[#ENTRY]] = !{ptr @main, ![[#RS:]], i32 3} // REG: ![[#RS]] = !{![[#CBV:]]} // REG: ![[#CBV]] = !{!"RootCBV" diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index a08cfff4b4974..8b0f8fab24c66 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -843,6 +843,7 @@ struct StaticSampler : public v1::StaticSampler { enum class RootSignatureVersion { V1_0 = 0x1, V1_1 = 0x2, + V1_2 = 0x3, }; } // namespace dxbc diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 37224d8a94527..c5d89106a8537 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -56,7 +56,7 @@ struct RootDescriptor { return; } - assert(Version == llvm::dxbc::RootSignatureVersion::V1_1 && + assert((Version == llvm::dxbc::RootSignatureVersion::V1_1 || Version == llvm::dxbc::RootSignatureVersion::V1_2) && "Specified an invalid root signature version"); switch (Type) { case dxil::ResourceClass::CBuffer: @@ -100,7 +100,7 @@ struct DescriptorTableClause { return; } - assert(Version == dxbc::RootSignatureVersion::V1_1 && + assert((Version == dxbc::RootSignatureVersion::V1_1 || Version == dxbc::RootSignatureVersion::V1_2) && "Specified an invalid root signature version"); switch (Type) { case dxil::ResourceClass::CBuffer: diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 8c298f0685286..0ce2aaf51bfd6 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -40,7 +40,7 @@ bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal) { if (Version == 1) return Flags == FlagT::DataVolatile; - assert(Version == 2 && "Provided invalid root signature version"); + assert((Version == 2 || Version == 3) && "Provided invalid root signature version"); // The data-specific flags are mutually exclusive. FlagT DataFlags = FlagT::DataVolatile | FlagT::DataStatic | diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index bfb3837707f0a..f268aa85a705e 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -154,7 +154,7 @@ DXContainerYAML::RootSignatureYamlDesc::create( if (Error E = readDescriptorRanges<dxbc::RTS0::v1::DescriptorRange>( Header, RootSigDesc, DTV)) return std::move(E); - } else if (Version == 2) { + } else if (Version == 2 || Version == 3) { if (Error E = readDescriptorRanges<dxbc::RTS0::v2::DescriptorRange>( Header, RootSigDesc, DTV)) return std::move(E); >From 11770c5cefcddddb984e88029d06d9729e6ea7ff Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Thu, 25 Sep 2025 13:23:39 -0700 Subject: [PATCH 18/19] fix objcopy test --- clang/test/Driver/dxc_frs.hlsl | 2 +- clang/test/Driver/dxc_rootsignature_target.hlsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Driver/dxc_frs.hlsl b/clang/test/Driver/dxc_frs.hlsl index 767cab604c829..9fa568901db81 100644 --- a/clang/test/Driver/dxc_frs.hlsl +++ b/clang/test/Driver/dxc_frs.hlsl @@ -3,7 +3,7 @@ // Test to demonstrate extracting the root signature to the specified // output file with /Frs. -// CHECK: "{{.*}}llvm-objcopy{{(.exe)?}}" "{{.*}}.obj" "{{.*}}.dxo" "--extract-section=RTS0={{.*}}.rs.dxo" +// CHECK: "{{.*}}/llvm-objcopy{{(.exe)?}}" "{{.*}}.obj" "{{.*}}.{{(dxo|obj)}}" "--extract-section=RTS0={{.*}}.rs.dxo" [shader("compute"), RootSignature("")] [numthreads(1,1,1)] diff --git a/clang/test/Driver/dxc_rootsignature_target.hlsl b/clang/test/Driver/dxc_rootsignature_target.hlsl index 08cd1ab00089b..784523707746d 100644 --- a/clang/test/Driver/dxc_rootsignature_target.hlsl +++ b/clang/test/Driver/dxc_rootsignature_target.hlsl @@ -3,6 +3,6 @@ // CMDS: "{{.*}}clang{{.*}}" "-cc1" // CMDS-SAME: "-triple" "dxilv1.1-unknown-shadermodel1.1-rootsignature" // CMDS-SAME: "-hlsl-entry" "EntryRS" -// CMDS: "{{.*}}llvm-objcopy{{(.exe)?}}" "{{.*}}.dxo" "--only-section=RTS0" +// CMDS: "{{.*}}llvm-objcopy{{(.exe)?}}" "{{.*}}.{{(dxo|obj)}}" "--only-section=RTS0" #define EntryRS "UAV(u0)" >From c3746341bdf20e1c0bc803c9801291a7f0573ba3 Mon Sep 17 00:00:00 2001 From: Joao Saffran <joaosaffranl...@gmail.com> Date: Fri, 26 Sep 2025 11:10:02 -0700 Subject: [PATCH 19/19] foramt --- llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h | 6 ++++-- llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index c5d89106a8537..edee6a7dec6fc 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -56,7 +56,8 @@ struct RootDescriptor { return; } - assert((Version == llvm::dxbc::RootSignatureVersion::V1_1 || Version == llvm::dxbc::RootSignatureVersion::V1_2) && + assert((Version == llvm::dxbc::RootSignatureVersion::V1_1 || + Version == llvm::dxbc::RootSignatureVersion::V1_2) && "Specified an invalid root signature version"); switch (Type) { case dxil::ResourceClass::CBuffer: @@ -100,7 +101,8 @@ struct DescriptorTableClause { return; } - assert((Version == dxbc::RootSignatureVersion::V1_1 || Version == dxbc::RootSignatureVersion::V1_2) && + assert((Version == dxbc::RootSignatureVersion::V1_1 || + Version == dxbc::RootSignatureVersion::V1_2) && "Specified an invalid root signature version"); switch (Type) { case dxil::ResourceClass::CBuffer: diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 653305165cad5..8a2b03d9ede8b 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -40,7 +40,7 @@ bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal) { if (Version == 1) return Flags == FlagT::DataVolatile; - assert((Version == 2 || Version == 3) && "Provided invalid root signature version"); + assert((Version <= 3) && "Provided invalid root signature version"); // The data-specific flags are mutually exclusive. FlagT DataFlags = FlagT::DataVolatile | FlagT::DataStatic | _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits