[clang] [llvm] [HLSL][RootSignature] Plug-in serialization and add full sample testcase (PR #144769)
Finn Plummer via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 23 11:08:41 PDT 2025
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/144769
>From 3761e5204d2d435cc09f392fd2e53c2125fac0ed Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 6 Jun 2025 20:46:10 +0000
Subject: [PATCH 1/3] [HLSL][RootSignature] Plug-in serialization and add full
sample testcase
---
clang/test/AST/HLSL/RootSignatures-AST.hlsl | 97 +++++++++++++------
.../Frontend/HLSL/HLSLRootSignatureUtils.cpp | 54 +++++++----
2 files changed, 105 insertions(+), 46 deletions(-)
diff --git a/clang/test/AST/HLSL/RootSignatures-AST.hlsl b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
index c700174da764d..1356dcc2fc87b 100644
--- a/clang/test/AST/HLSL/RootSignatures-AST.hlsl
+++ b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
@@ -5,29 +5,61 @@
// the Attr AST Node is created succesfully. If an invalid root signature was
// passed in then we would exit out of Sema before the Attr is created.
-#define SampleRS \
- "DescriptorTable( " \
- " CBV(b1), " \
- " SRV(t1, numDescriptors = 8, " \
- " flags = DESCRIPTORS_VOLATILE), " \
- " UAV(u1, numDescriptors = 0, " \
- " flags = DESCRIPTORS_VOLATILE) " \
- "), " \
- "DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
+#define SampleRS "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
+ "DENY_VERTEX_SHADER_ROOT_ACCESS), " \
+ "CBV(b0, space = 1, flags = DATA_STATIC), " \
+ "SRV(t0), " \
+ "UAV(u0), " \
+ "DescriptorTable( CBV(b1), " \
+ "SRV(t1, numDescriptors = 8, " \
+ " flags = DESCRIPTORS_VOLATILE), " \
+ "UAV(u1, numDescriptors = unbounded, " \
+ " flags = DESCRIPTORS_VOLATILE)), " \
+ "DescriptorTable(Sampler(s0, space=1, numDescriptors = 4)), " \
+ "RootConstants(num32BitConstants=3, b10), " \
+ "StaticSampler(s1)," \
+ "StaticSampler(s2, " \
+ "addressU = TEXTURE_ADDRESS_CLAMP, " \
+ "filter = FILTER_MIN_MAG_MIP_LINEAR )"
// CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[SAMPLE_RS_DECL:__hlsl_rootsig_decl_\d*]]
// CHECK-SAME: RootElements{
-// CHECK-SAME: CBV(b1, numDescriptors = 1, space = 0,
-// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = DataStaticWhileSetAtExecute),
-// CHECK-SAME: SRV(t1, numDescriptors = 8, space = 0,
-// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile),
-// CHECK-SAME: UAV(u1, numDescriptors = 0, space = 0,
-// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile),
-// CHECK-SAME: DescriptorTable(numClauses = 3, visibility = All),
-// CHECK-SAME: Sampler(s0, numDescriptors = 4, space = 1,
-// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = None),
-// CHECK-SAME: DescriptorTable(numClauses = 1, visibility = All)
-// CHECK-SAME: }
+// CHECK-SAME: RootFlags(AllowInputAssemblerInputLayout | DenyVertexShaderRootAccess),
+// CHECK-SAME: RootCBV(b0,
+// CHECK-SAME: space = 1, visibility = All, flags = DataStatic
+// CHECK-SAME: ),
+// CHECK-SAME: RootSRV(t0,
+// CHECK-SAME: space = 0, visibility = All, flags = DataStaticWhileSetAtExecute
+// CHECK-SAME: ),
+// CHECK-SAME: RootUAV(
+// CHECK-SAME: u0, space = 0, visibility = All, flags = DataVolatile
+// CHECK-SAME: ),
+// CHECK-SAME: CBV(
+// CHECK-SAME: b1, numDescriptors = 1, space = 0, offset = DescriptorTableOffsetAppend, flags = DataStaticWhileSetAtExecute
+// CHECK-SAME: ),
+// CHECK-SAME: SRV(
+// CHECK-SAME: t1, numDescriptors = 8, space = 0, offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile
+// CHECK-SAME: ),
+// CHECK-SAME: UAV(
+// CHECK-SAME: u1, numDescriptors = 4294967295, space = 0, offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile
+// CHECK-SAME: ),
+// CHECK-SAME: DescriptorTable(
+// CHECK-SAME: numClauses = 3, visibility = All
+// CHECK-SAME: ),
+// CHECK-SAME: Sampler(
+// CHECK-SAME: s0, numDescriptors = 4, space = 1, offset = DescriptorTableOffsetAppend, flags = None
+// CHECK-SAME: ),
+// CHECK-SAME: DescriptorTable(
+// CHECK-SAME: numClauses = 1, visibility = All
+// CHECK-SAME: ),
+// CHECK-SAME: RootConstants(
+// CHECK-SAME: num32BitConstants = 3, b10, space = 0, visibility = All
+// CHECK-SAME: ),
+// CHECK-SAME: StaticSampler(
+// 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-SAME: )}
// CHECK: -RootSignatureAttr 0x{{.*}} {{.*}} [[SAMPLE_RS_DECL]]
[RootSignature(SampleRS)]
@@ -44,14 +76,23 @@ void same_rs_main() {}
// link to the same root signature declaration
#define SampleSameRS \
- "DescriptorTable( " \
- " CBV(b1), " \
- " SRV(t1, numDescriptors = 8, " \
- " flags = DESCRIPTORS_VOLATILE), " \
- " UAV(u1, numDescriptors = 0, " \
- " flags = DESCRIPTORS_VOLATILE) " \
- "), " \
- "DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
+ "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
+ "DENY_VERTEX_SHADER_ROOT_ACCESS), " \
+ "CBV(b0, space = 1, flags = DATA_STATIC), " \
+ "SRV(t0), " \
+ "UAV(u0), " \
+ "DescriptorTable( CBV(b1), " \
+ "SRV(t1, numDescriptors = 8, " \
+ " flags = DESCRIPTORS_VOLATILE), " \
+ "UAV(u1, numDescriptors = unbounded, " \
+ " flags = DESCRIPTORS_VOLATILE)), " \
+ "DescriptorTable(Sampler(s0, space=1, numDescriptors = 4)), " \
+ "RootConstants(num32BitConstants=3, b10), " \
+ "StaticSampler(s1)," \
+ "StaticSampler(s2, " \
+ "addressU = TEXTURE_ADDRESS_CLAMP, " \
+ "filter = FILTER_MIN_MAG_MIP_LINEAR )"
+
// CHECK: -RootSignatureAttr 0x{{.*}} {{.*}} [[SAMPLE_RS_DECL]]
[RootSignature(SampleSameRS)]
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp
index a1ddb318055be..bb0c527b01706 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp
@@ -324,36 +324,54 @@ raw_ostream &operator<<(raw_ostream &OS, const StaticSampler &Sampler) {
return OS;
}
+namespace {
+
+// We use the OverloadVisit with std::visit to ensure the compiler catches if a
+// new RootElement variant type is added but it's operator<< or metadata
+// generation isn't handled.
+template <class... Ts> struct OverloadedVisit : Ts... {
+ using Ts::operator()...;
+};
+template <class... Ts> OverloadedVisit(Ts...) -> OverloadedVisit<Ts...>;
+
+} // namespace
+
void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
- OS << "RootElements{";
+ const auto Visitor = OverloadedVisit{
+ [&OS](const RootFlags &Flags) -> raw_ostream& {
+ return OS << Flags;
+ },
+ [&OS](const RootConstants &Constants) -> raw_ostream& {
+ return OS << Constants;
+ },
+ [&OS](const RootDescriptor &Descriptor) -> raw_ostream& {
+ return OS << Descriptor;
+ },
+ [&OS](const DescriptorTableClause &Clause) -> raw_ostream& {
+ return OS << Clause;
+ },
+ [&OS](const DescriptorTable &Table) -> raw_ostream& {
+ return OS << Table;
+ },
+ [&OS](const StaticSampler &Sampler) -> raw_ostream& {
+ return OS << Sampler;
+ },
+ };
+
+ OS << " RootElements{";
bool First = true;
for (const RootElement &Element : Elements) {
if (!First)
OS << ",";
OS << " ";
- if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element))
- OS << *Clause;
- if (const auto &Table = std::get_if<DescriptorTable>(&Element))
- OS << *Table;
+ std::visit(Visitor, Element);
First = false;
}
OS << "}";
}
-namespace {
-
-// We use the OverloadBuild with std::visit to ensure the compiler catches if a
-// new RootElement variant type is added but it's metadata generation isn't
-// handled.
-template <class... Ts> struct OverloadedBuild : Ts... {
- using Ts::operator()...;
-};
-template <class... Ts> OverloadedBuild(Ts...) -> OverloadedBuild<Ts...>;
-
-} // namespace
-
MDNode *MetadataBuilder::BuildRootSignature() {
- const auto Visitor = OverloadedBuild{
+ const auto Visitor = OverloadedVisit{
[this](const RootFlags &Flags) -> MDNode * {
return BuildRootFlags(Flags);
},
>From d9714beb915204f1a255b3521b0464083e664a89 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 18 Jun 2025 17:27:32 +0000
Subject: [PATCH 2/3] self-review: remove redundant return
---
.../Frontend/HLSL/HLSLRootSignatureUtils.cpp | 24 +++++--------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp
index bb0c527b01706..52801741f351f 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp
@@ -338,24 +338,12 @@ template <class... Ts> OverloadedVisit(Ts...) -> OverloadedVisit<Ts...>;
void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
const auto Visitor = OverloadedVisit{
- [&OS](const RootFlags &Flags) -> raw_ostream& {
- return OS << Flags;
- },
- [&OS](const RootConstants &Constants) -> raw_ostream& {
- return OS << Constants;
- },
- [&OS](const RootDescriptor &Descriptor) -> raw_ostream& {
- return OS << Descriptor;
- },
- [&OS](const DescriptorTableClause &Clause) -> raw_ostream& {
- return OS << Clause;
- },
- [&OS](const DescriptorTable &Table) -> raw_ostream& {
- return OS << Table;
- },
- [&OS](const StaticSampler &Sampler) -> raw_ostream& {
- return OS << Sampler;
- },
+ [&OS](const RootFlags &Flags) { OS << Flags; },
+ [&OS](const RootConstants &Constants) { OS << Constants; },
+ [&OS](const RootDescriptor &Descriptor) { OS << Descriptor; },
+ [&OS](const DescriptorTableClause &Clause) { OS << Clause; },
+ [&OS](const DescriptorTable &Table) { OS << Table; },
+ [&OS](const StaticSampler &Sampler) { OS << Sampler; },
};
OS << " RootElements{";
>From c148ac974dc2ea6617417900dc60fe2d67a0d0b0 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Mon, 23 Jun 2025 18:06:06 +0000
Subject: [PATCH 3/3] self-review: output unbounded instead of UINT_MAX for
numDescriptors
---
clang/test/AST/HLSL/RootSignatures-AST.hlsl | 2 +-
llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp | 8 ++++++--
llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp | 4 ++--
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/clang/test/AST/HLSL/RootSignatures-AST.hlsl b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
index 1356dcc2fc87b..157d90aee7ee2 100644
--- a/clang/test/AST/HLSL/RootSignatures-AST.hlsl
+++ b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
@@ -41,7 +41,7 @@
// CHECK-SAME: t1, numDescriptors = 8, space = 0, offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile
// CHECK-SAME: ),
// CHECK-SAME: UAV(
-// CHECK-SAME: u1, numDescriptors = 4294967295, space = 0, offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile
+// CHECK-SAME: u1, numDescriptors = unbounded, space = 0, offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile
// CHECK-SAME: ),
// CHECK-SAME: DescriptorTable(
// CHECK-SAME: numClauses = 3, visibility = All
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp
index 52801741f351f..acf5d7f706a78 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp
@@ -288,8 +288,12 @@ raw_ostream &operator<<(raw_ostream &OS, const DescriptorTable &Table) {
raw_ostream &operator<<(raw_ostream &OS, const DescriptorTableClause &Clause) {
OS << Clause.Type << "(" << Clause.Reg
- << ", numDescriptors = " << Clause.NumDescriptors
- << ", space = " << Clause.Space << ", offset = ";
+ << ", numDescriptors = ";
+ if (Clause.NumDescriptors == NumDescriptorsUnbounded)
+ OS << "unbounded";
+ else
+ OS << Clause.NumDescriptors;
+ OS << ", space = " << Clause.Space << ", offset = ";
if (Clause.Offset == DescriptorTableOffsetAppend)
OS << "DescriptorTableOffsetAppend";
else
diff --git a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
index 1c37ee709e098..600038fab4b23 100644
--- a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
+++ b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
@@ -34,7 +34,7 @@ TEST(HLSLRootSignatureTest, DescriptorSRVClauseDump) {
DescriptorTableClause Clause;
Clause.Type = ClauseType::SRV;
Clause.Reg = {RegisterType::TReg, 0};
- Clause.NumDescriptors = 2;
+ Clause.NumDescriptors = NumDescriptorsUnbounded;
Clause.Space = 42;
Clause.Offset = 3;
Clause.Flags = DescriptorRangeFlags::None;
@@ -45,7 +45,7 @@ TEST(HLSLRootSignatureTest, DescriptorSRVClauseDump) {
OS.flush();
std::string Expected =
- "SRV(t0, numDescriptors = 2, space = 42, offset = 3, flags = None)";
+ "SRV(t0, numDescriptors = unbounded, space = 42, offset = 3, flags = None)";
EXPECT_EQ(Out, Expected);
}
More information about the cfe-commits
mailing list