From d772a08662bafb438c90e401efecfbecc1b7852e Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Thu, 29 May 2025 10:31:08 -0700 Subject: [PATCH 1/4] [HLSL][RootSignature] Implement serialization of `RootConstants` and `RootFlags` (#141130) - Implements serialization of the currently completely defined `RootElement`s, namely `RootConstants` and `RootFlags` - Adds unit testing for the serialization methods Resolves: https://github.com/llvm/llvm-project/issues/138190 and https://github.com/llvm/llvm-project/issues/138192 --- .../llvm/Frontend/HLSL/HLSLRootSignature.h | 4 + .../Frontend/HLSL/HLSLRootSignatureUtils.cpp | 73 +++++++++++++++++++ .../Frontend/HLSLRootSignatureDumpTest.cpp | 69 ++++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 2f028817b45b6..c70ef508ea73e 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -44,6 +44,8 @@ enum class RootFlags : uint32_t { ValidFlags = 0x00000fff }; +raw_ostream &operator<<(raw_ostream &OS, const RootFlags &Flags); + enum class RootDescriptorFlags : unsigned { None = 0, DataVolatile = 0x2, @@ -159,6 +161,8 @@ struct RootConstants { ShaderVisibility Visibility = ShaderVisibility::All; }; +raw_ostream &operator<<(raw_ostream &OS, const RootConstants &Constants); + enum class DescriptorType : uint8_t { SRV = 0, UAV, CBuffer }; // Models RootDescriptor : CBV | SRV | UAV, by collecting like parameters struct RootDescriptor { diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp index 7d744781da04f..11b41b023bda3 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp @@ -129,6 +129,79 @@ static raw_ostream &operator<<(raw_ostream &OS, return OS; } +raw_ostream &operator<<(raw_ostream &OS, const RootFlags &Flags) { + OS << "RootFlags("; + bool FlagSet = false; + unsigned Remaining = llvm::to_underlying(Flags); + while (Remaining) { + unsigned Bit = 1u << llvm::countr_zero(Remaining); + if (Remaining & Bit) { + if (FlagSet) + OS << " | "; + + switch (static_cast(Bit)) { + case RootFlags::AllowInputAssemblerInputLayout: + OS << "AllowInputAssemblerInputLayout"; + break; + case RootFlags::DenyVertexShaderRootAccess: + OS << "DenyVertexShaderRootAccess"; + break; + case RootFlags::DenyHullShaderRootAccess: + OS << "DenyHullShaderRootAccess"; + break; + case RootFlags::DenyDomainShaderRootAccess: + OS << "DenyDomainShaderRootAccess"; + break; + case RootFlags::DenyGeometryShaderRootAccess: + OS << "DenyGeometryShaderRootAccess"; + break; + case RootFlags::DenyPixelShaderRootAccess: + OS << "DenyPixelShaderRootAccess"; + break; + case RootFlags::AllowStreamOutput: + OS << "AllowStreamOutput"; + break; + case RootFlags::LocalRootSignature: + OS << "LocalRootSignature"; + break; + case RootFlags::DenyAmplificationShaderRootAccess: + OS << "DenyAmplificationShaderRootAccess"; + break; + case RootFlags::DenyMeshShaderRootAccess: + OS << "DenyMeshShaderRootAccess"; + break; + case RootFlags::CBVSRVUAVHeapDirectlyIndexed: + OS << "CBVSRVUAVHeapDirectlyIndexed"; + break; + case RootFlags::SamplerHeapDirectlyIndexed: + OS << "SamplerHeapDirectlyIndexed"; + break; + default: + OS << "invalid: " << Bit; + break; + } + + FlagSet = true; + } + Remaining &= ~Bit; + } + + if (!FlagSet) + OS << "None"; + + OS << ")"; + + return OS; +} + +raw_ostream &operator<<(raw_ostream &OS, const RootConstants &Constants) { + OS << "RootConstants(num32BitConstants = " << Constants.Num32BitConstants + << ", " << Constants.Reg << ", space = " << Constants.Space + << ", visibility = " << Constants.Visibility << ")"; + + return OS; +} + raw_ostream &operator<<(raw_ostream &OS, const DescriptorTable &Table) { OS << "DescriptorTable(numClauses = " << Table.NumClauses << ", visibility = " << Table.Visibility << ")"; diff --git a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp index 90e6cd0a80d6b..1a0c8e2a16396 100644 --- a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp +++ b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp @@ -108,4 +108,73 @@ TEST(HLSLRootSignatureTest, DescriptorTableDump) { EXPECT_EQ(Out, Expected); } +TEST(HLSLRootSignatureTest, DefaultRootConstantsDump) { + RootConstants Constants; + Constants.Num32BitConstants = 1; + Constants.Reg = {RegisterType::BReg, 3}; + + std::string Out; + llvm::raw_string_ostream OS(Out); + OS << Constants; + OS.flush(); + + std::string Expected = "RootConstants(num32BitConstants = 1, b3, space = 0, " + "visibility = All)"; + EXPECT_EQ(Out, Expected); +} + +TEST(HLSLRootSignatureTest, SetRootConstantsDump) { + RootConstants Constants; + Constants.Num32BitConstants = 983; + Constants.Reg = {RegisterType::BReg, 34593}; + Constants.Space = 7; + Constants.Visibility = ShaderVisibility::Pixel; + + std::string Out; + llvm::raw_string_ostream OS(Out); + OS << Constants; + OS.flush(); + + std::string Expected = "RootConstants(num32BitConstants = 983, b34593, " + "space = 7, visibility = Pixel)"; + EXPECT_EQ(Out, Expected); +} + +TEST(HLSLRootSignatureTest, NoneRootFlagsDump) { + RootFlags Flags = RootFlags::None; + + std::string Out; + llvm::raw_string_ostream OS(Out); + OS << Flags; + OS.flush(); + + std::string Expected = "RootFlags(None)"; + EXPECT_EQ(Out, Expected); +} + +TEST(HLSLRootSignatureTest, AllRootFlagsDump) { + RootFlags Flags = RootFlags::ValidFlags; + + std::string Out; + llvm::raw_string_ostream OS(Out); + OS << Flags; + OS.flush(); + + std::string Expected = "RootFlags(" + "AllowInputAssemblerInputLayout | " + "DenyVertexShaderRootAccess | " + "DenyHullShaderRootAccess | " + "DenyDomainShaderRootAccess | " + "DenyGeometryShaderRootAccess | " + "DenyPixelShaderRootAccess | " + "AllowStreamOutput | " + "LocalRootSignature | " + "DenyAmplificationShaderRootAccess | " + "DenyMeshShaderRootAccess | " + "CBVSRVUAVHeapDirectlyIndexed | " + "SamplerHeapDirectlyIndexed)"; + + EXPECT_EQ(Out, Expected); +} + } // namespace From cca438a228c4c09cd1ff0d1e308c6bbf66822c11 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Thu, 5 Jun 2025 18:34:44 +0000 Subject: [PATCH 2/4] reland-fix: link missing FrontendHLSL lib This relands https://github.com/llvm/llvm-project/pull/141130. The initial commit uncovered that we are missing the correct linking of FrontendHLSL into clang/lib/Parse and clang/lib/unittests/Parse. This change addreses this my linking them accordingly. It was also checked and ensured that the LexHLSLRootSignature libraries do not depend on FrontendHLSL and so we are not required to link there. Resolves: https://github.com/llvm/llvm-project/issues/138190 and https://github.com/llvm/llvm-project/issues/138192 --- clang/lib/Parse/CMakeLists.txt | 1 + clang/unittests/Parse/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/clang/lib/Parse/CMakeLists.txt b/clang/lib/Parse/CMakeLists.txt index 00fde537bb9c6..e6cbf3b868b7d 100644 --- a/clang/lib/Parse/CMakeLists.txt +++ b/clang/lib/Parse/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + FrontendHLSL FrontendOpenMP MC MCParser diff --git a/clang/unittests/Parse/CMakeLists.txt b/clang/unittests/Parse/CMakeLists.txt index 6859efed294c8..2ed43a83b8782 100644 --- a/clang/unittests/Parse/CMakeLists.txt +++ b/clang/unittests/Parse/CMakeLists.txt @@ -11,5 +11,6 @@ add_clang_unittest(ParseTests LLVMTestingSupport clangTesting LLVM_COMPONENTS + FrontendHLSL Support ) From 02f98fa46c6c325e5edb671e661b51d4bcfe5067 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Thu, 5 Jun 2025 21:38:10 +0000 Subject: [PATCH 3/4] rebase changes: update onto changes from main --- llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h | 4 ---- llvm/include/llvm/Frontend/HLSL/HLSLRootSignatureUtils.h | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index c70ef508ea73e..2f028817b45b6 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -44,8 +44,6 @@ enum class RootFlags : uint32_t { ValidFlags = 0x00000fff }; -raw_ostream &operator<<(raw_ostream &OS, const RootFlags &Flags); - enum class RootDescriptorFlags : unsigned { None = 0, DataVolatile = 0x2, @@ -161,8 +159,6 @@ struct RootConstants { ShaderVisibility Visibility = ShaderVisibility::All; }; -raw_ostream &operator<<(raw_ostream &OS, const RootConstants &Constants); - enum class DescriptorType : uint8_t { SRV = 0, UAV, CBuffer }; // Models RootDescriptor : CBV | SRV | UAV, by collecting like parameters struct RootDescriptor { diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignatureUtils.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignatureUtils.h index 6d959ad5bdc7f..ca20e6719f3a4 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignatureUtils.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignatureUtils.h @@ -27,6 +27,11 @@ class Metadata; namespace hlsl { namespace rootsig { +LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const RootFlags &Flags); + +LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, + const RootConstants &Constants); + LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const DescriptorTableClause &Clause); From e19435154afd0950ec03213dfbacac61c8c69a82 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Mon, 16 Jun 2025 19:55:09 +0000 Subject: [PATCH 4/4] nfc, rebase-changes: update to new printFlags calling convention --- .../Frontend/HLSL/HLSLRootSignatureUtils.cpp | 76 +++++-------------- 1 file changed, 18 insertions(+), 58 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp index 11b41b023bda3..5bae72a3986f8 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp @@ -129,66 +129,26 @@ static raw_ostream &operator<<(raw_ostream &OS, return OS; } +static const EnumEntry RootFlagNames[] = { + {"AllowInputAssemblerInputLayout", + RootFlags::AllowInputAssemblerInputLayout}, + {"DenyVertexShaderRootAccess", RootFlags::DenyVertexShaderRootAccess}, + {"DenyHullShaderRootAccess", RootFlags::DenyHullShaderRootAccess}, + {"DenyDomainShaderRootAccess", RootFlags::DenyDomainShaderRootAccess}, + {"DenyGeometryShaderRootAccess", RootFlags::DenyGeometryShaderRootAccess}, + {"DenyPixelShaderRootAccess", RootFlags::DenyPixelShaderRootAccess}, + {"AllowStreamOutput", RootFlags::AllowStreamOutput}, + {"LocalRootSignature", RootFlags::LocalRootSignature}, + {"DenyAmplificationShaderRootAccess", + RootFlags::DenyAmplificationShaderRootAccess}, + {"DenyMeshShaderRootAccess", RootFlags::DenyMeshShaderRootAccess}, + {"CBVSRVUAVHeapDirectlyIndexed", RootFlags::CBVSRVUAVHeapDirectlyIndexed}, + {"SamplerHeapDirectlyIndexed", RootFlags::SamplerHeapDirectlyIndexed}, +}; + raw_ostream &operator<<(raw_ostream &OS, const RootFlags &Flags) { OS << "RootFlags("; - bool FlagSet = false; - unsigned Remaining = llvm::to_underlying(Flags); - while (Remaining) { - unsigned Bit = 1u << llvm::countr_zero(Remaining); - if (Remaining & Bit) { - if (FlagSet) - OS << " | "; - - switch (static_cast(Bit)) { - case RootFlags::AllowInputAssemblerInputLayout: - OS << "AllowInputAssemblerInputLayout"; - break; - case RootFlags::DenyVertexShaderRootAccess: - OS << "DenyVertexShaderRootAccess"; - break; - case RootFlags::DenyHullShaderRootAccess: - OS << "DenyHullShaderRootAccess"; - break; - case RootFlags::DenyDomainShaderRootAccess: - OS << "DenyDomainShaderRootAccess"; - break; - case RootFlags::DenyGeometryShaderRootAccess: - OS << "DenyGeometryShaderRootAccess"; - break; - case RootFlags::DenyPixelShaderRootAccess: - OS << "DenyPixelShaderRootAccess"; - break; - case RootFlags::AllowStreamOutput: - OS << "AllowStreamOutput"; - break; - case RootFlags::LocalRootSignature: - OS << "LocalRootSignature"; - break; - case RootFlags::DenyAmplificationShaderRootAccess: - OS << "DenyAmplificationShaderRootAccess"; - break; - case RootFlags::DenyMeshShaderRootAccess: - OS << "DenyMeshShaderRootAccess"; - break; - case RootFlags::CBVSRVUAVHeapDirectlyIndexed: - OS << "CBVSRVUAVHeapDirectlyIndexed"; - break; - case RootFlags::SamplerHeapDirectlyIndexed: - OS << "SamplerHeapDirectlyIndexed"; - break; - default: - OS << "invalid: " << Bit; - break; - } - - FlagSet = true; - } - Remaining &= ~Bit; - } - - if (!FlagSet) - OS << "None"; - + printFlags(OS, Flags, ArrayRef(RootFlagNames)); OS << ")"; return OS;