[clang] [HLSL][RootSignature] Enable resource range analysis for remaining `RootElement`s (PR #145109)
Finn Plummer via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 20 16:08:39 PDT 2025
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/145109
>From 447dca922263f5a4abec27d8e32302dc1b7a1b5b Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 20 Jun 2025 18:45:55 +0000
Subject: [PATCH 1/8] add collection of RootConstants
---
clang/lib/Sema/SemaHLSL.cpp | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index d003967a522a1..6b8889d1addc8 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1117,6 +1117,17 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
Info.Visibility = Descriptor->Visibility;
Infos.push_back(Info);
}
+ if (const auto *Constants =
+ std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
+ RangeInfo Info;
+ Info.LowerBound = Constants->Reg.Number;
+ Info.UpperBound = Info.LowerBound; // use inclusive ranges []
+
+ Info.Class = llvm::dxil::ResourceClass::CBuffer;
+ Info.Space = Constants->Space;
+ Info.Visibility = Constants->Visibility;
+ Infos.push_back(Info);
+ }
}
// 2. Sort the RangeInfo's by their GroupT to form groupings
>From cb6c7c46407fc6b5f6411ea5af5ab99ea4db2ec6 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 20 Jun 2025 18:48:54 +0000
Subject: [PATCH 2/8] add collection of StaticSamplers
---
clang/lib/Sema/SemaHLSL.cpp | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 6b8889d1addc8..3dcce38a59947 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1128,6 +1128,17 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
Info.Visibility = Constants->Visibility;
Infos.push_back(Info);
}
+ if (const auto *Sampler =
+ std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
+ RangeInfo Info;
+ Info.LowerBound = Sampler->Reg.Number;
+ Info.UpperBound = Info.LowerBound; // use inclusive ranges []
+
+ Info.Class = llvm::dxil::ResourceClass::Sampler;
+ Info.Space = Sampler->Space;
+ Info.Visibility = Sampler->Visibility;
+ Infos.push_back(Info);
+ }
}
// 2. Sort the RangeInfo's by their GroupT to form groupings
>From 3e54c9d3113464ffd2edc508756f5b42922a7a8e Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 20 Jun 2025 19:28:45 +0000
Subject: [PATCH 3/8] add colleciton of DescriptorTables
---
clang/lib/Sema/SemaHLSL.cpp | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 3dcce38a59947..3498b99c89397 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1139,6 +1139,32 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
Info.Visibility = Sampler->Visibility;
Infos.push_back(Info);
}
+ if (const auto *Clause =
+ std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(&Elem)) {
+ RangeInfo Info;
+ Info.LowerBound = Clause->Reg.Number;
+ assert(0 < Clause->NumDescriptors && "Verified as part of TODO(#129940)");
+ Info.UpperBound =
+ Clause->NumDescriptors == RangeInfo::Unbounded
+ ? RangeInfo::Unbounded
+ : Info.LowerBound + Clause->NumDescriptors - 1; // use inclusive ranges []
+
+ Info.Class = Clause->Type;
+ Info.Space = Clause->Space;
+ // Note: Clause does not hold the visibility this will need to
+ Infos.push_back(Info);
+ }
+ if (const auto *Table =
+ std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
+ // Table holds the Visibility of all owned Clauses in Table, so iterate
+ // owned Clauses and update their corresponding RangeInfo
+ assert(Table->NumClauses <= Infos.size() && "RootElement");
+ // The last Table->NumClauses elements of Infos are the owned Clauses
+ // generated RangeInfo
+ auto TableInfos = MutableArrayRef<RangeInfo>(Infos).take_back(Table->NumClauses);
+ for (RangeInfo &Info : TableInfos)
+ Info.Visibility = Table->Visibility;
+ }
}
// 2. Sort the RangeInfo's by their GroupT to form groupings
>From 2ce85d76981c4a6f680bf131ebd8bf47e36d1f67 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 20 Jun 2025 20:39:33 +0000
Subject: [PATCH 4/8] add plethora of tests
---
.../RootSignature-resource-ranges-err.hlsl | 43 +++++++++++++++++++
.../RootSignature-resource-ranges.hlsl | 9 ++++
2 files changed, 52 insertions(+)
diff --git a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
index e5152e72d4806..a632277fbb76a 100644
--- a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
@@ -19,3 +19,46 @@ void bad_root_signature_3() {}
// expected-error at +1 {{resource ranges u[0;0] and u[0;0] overlap within space = 0 and visibility = Pixel}}
[RootSignature("UAV(u0, visibility = SHADER_VISIBILITY_PIXEL), UAV(u0, visibility = SHADER_VISIBILITY_ALL)")]
void bad_root_signature_4() {}
+
+// expected-error at +1 {{resource ranges b[0;0] and b[0;0] overlap within space = 0 and visibility = All}}
+[RootSignature("RootConstants(num32BitConstants=4, b0), RootConstants(num32BitConstants=2, b0)")]
+void bad_root_signature_5() {}
+
+// expected-error at +1 {{resource ranges s[3;3] and s[3;3] overlap within space = 0 and visibility = All}}
+[RootSignature("StaticSampler(s3), StaticSampler(s3)")]
+void bad_root_signature_6() {}
+
+// expected-error at +1 {{resource ranges t[2;5] and t[0;3] overlap within space = 0 and visibility = All}}
+[RootSignature("DescriptorTable(SRV(t0, numDescriptors=4), SRV(t2, numDescriptors=4))")]
+void bad_root_signature_7() {}
+
+// expected-error at +1 {{resource ranges u[2;5] and u[0;4294967295] overlap within space = 0 and visibility = Hull}}
+[RootSignature("DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), DescriptorTable(UAV(u2, numDescriptors=4))")]
+void bad_root_signature_8() {}
+
+// expected-error at +1 {{resource ranges b[0;2] and b[2;2] overlap within space = 0 and visibility = All}}
+[RootSignature("RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b0, numDescriptors=3))")]
+void bad_root_signature_9() {}
+
+// expected-error at +1 {{resource ranges s[4;4294967295] and s[17;17] overlap within space = 0 and visibility = All}}
+[RootSignature("StaticSampler(s17), DescriptorTable(Sampler(s0, numDescriptors=3),Sampler(s4, numDescriptors=unbounded))")]
+void bad_root_signature_10() {}
+
+// expected-error at +1 {{resource ranges b[45;45] and b[4;4294967295] overlap within space = 0 and visibility = Geometry}}
+[RootSignature("DescriptorTable(CBV(b4, numDescriptors=unbounded)), CBV(b45, visibility = SHADER_VISIBILITY_GEOMETRY)")]
+void bad_root_signature_11() {}
+
+#define ReportFirstOverlap \
+ "DescriptorTable( " \
+ " CBV(b4, numDescriptors = 4), " \
+ " CBV(b1, numDescriptors = 2), " \
+ " CBV(b0, numDescriptors = 8), " \
+ ")"
+
+// expected-error at +1 {{resource ranges b[0;7] and b[1;2] overlap within space = 0 and visibility = All}}
+[RootSignature(ReportFirstOverlap)]
+void bad_root_signature_12() {}
+
+// expected-error at +1 {{resource ranges s[2;2] and s[2;2] overlap within space = 0 and visibility = Vertex}}
+[RootSignature("StaticSampler(s2, visibility=SHADER_VISIBILITY_ALL), DescriptorTable(Sampler(s2), visibility=SHADER_VISIBILITY_VERTEX)")]
+void valid_root_signature_13() {}
diff --git a/clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl b/clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl
index 5778fb2ae4eb9..09a1110b0fbc1 100644
--- a/clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl
@@ -13,3 +13,12 @@ void valid_root_signature_2() {}
[RootSignature("CBV(b0), SRV(t0)")]
void valid_root_signature_3() {}
+
+[RootSignature("RootConstants(num32BitConstants=4, b0, space=0), DescriptorTable(CBV(b0, space=1))")]
+void valid_root_signature_4() {}
+
+[RootSignature("StaticSampler(s2, visibility=SHADER_VISIBILITY_PIXEL), DescriptorTable(Sampler(s2), visibility=SHADER_VISIBILITY_VERTEX)")]
+void valid_root_signature_5() {}
+
+[RootSignature("DescriptorTable(SRV(t5), UAV(u5, numDescriptors=2))")]
+void valid_root_signature_6() {}
>From c59e66637e54262e4f610e675c4bc0c755f3c09e Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 20 Jun 2025 21:16:13 +0000
Subject: [PATCH 5/8] improve diag for unbounded
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 9 ++++++---
clang/lib/Sema/SemaHLSL.cpp | 5 ++++-
.../test/SemaHLSL/RootSignature-resource-ranges-err.hlsl | 6 +++---
3 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f2f2152b8bbbe..9392cbb39c021 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13054,10 +13054,13 @@ def err_invalid_hlsl_resource_type: Error<
def err_hlsl_spirv_only: Error<"%0 is only available for the SPIR-V target">;
def err_hlsl_vk_literal_must_contain_constant: Error<"the argument to vk::Literal must be a vk::integral_constant">;
+def subst_hlsl_format_ranges: TextSubstitution<
+ "%select{t|u|b|s}0[%1;%select{%3]|unbounded)}2">;
+
def err_hlsl_resource_range_overlap: Error<
- "resource ranges %select{t|u|b|s}0[%1;%2] and %select{t|u|b|s}3[%4;%5] "
- "overlap within space = %6 and visibility = "
- "%select{All|Vertex|Hull|Domain|Geometry|Pixel|Amplification|Mesh}7">;
+ "resource ranges %sub{subst_hlsl_format_ranges}0,1,2,3 and %sub{subst_hlsl_format_ranges}4,5,6,7 "
+ "overlap within space = %8 and visibility = "
+ "%select{All|Vertex|Hull|Domain|Geometry|Pixel|Amplification|Mesh}9">;
// Layout randomization diagnostics.
def err_non_designated_init_used : Error<
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 3498b99c89397..0b3f7fca682c0 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1207,8 +1207,11 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
: Info->Visibility;
this->Diag(Loc, diag::err_hlsl_resource_range_overlap)
<< llvm::to_underlying(Info->Class) << Info->LowerBound
+ << /*unbounded=*/(Info->UpperBound == RangeInfo::Unbounded)
<< Info->UpperBound << llvm::to_underlying(OInfo->Class)
- << OInfo->LowerBound << OInfo->UpperBound << Info->Space << CommonVis;
+ << OInfo->LowerBound
+ << /*unbounded=*/(OInfo->UpperBound == RangeInfo::Unbounded)
+ << OInfo->UpperBound << Info->Space << CommonVis;
};
// 3: Iterate through collected RangeInfos
diff --git a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
index a632277fbb76a..4b3579d51818a 100644
--- a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
@@ -32,7 +32,7 @@ void bad_root_signature_6() {}
[RootSignature("DescriptorTable(SRV(t0, numDescriptors=4), SRV(t2, numDescriptors=4))")]
void bad_root_signature_7() {}
-// expected-error at +1 {{resource ranges u[2;5] and u[0;4294967295] overlap within space = 0 and visibility = Hull}}
+// expected-error at +1 {{resource ranges u[2;5] and u[0;unbounded) overlap within space = 0 and visibility = Hull}}
[RootSignature("DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), DescriptorTable(UAV(u2, numDescriptors=4))")]
void bad_root_signature_8() {}
@@ -40,11 +40,11 @@ void bad_root_signature_8() {}
[RootSignature("RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b0, numDescriptors=3))")]
void bad_root_signature_9() {}
-// expected-error at +1 {{resource ranges s[4;4294967295] and s[17;17] overlap within space = 0 and visibility = All}}
+// expected-error at +1 {{resource ranges s[4;unbounded) and s[17;17] overlap within space = 0 and visibility = All}}
[RootSignature("StaticSampler(s17), DescriptorTable(Sampler(s0, numDescriptors=3),Sampler(s4, numDescriptors=unbounded))")]
void bad_root_signature_10() {}
-// expected-error at +1 {{resource ranges b[45;45] and b[4;4294967295] overlap within space = 0 and visibility = Geometry}}
+// expected-error at +1 {{resource ranges b[45;45] and b[4;unbounded) overlap within space = 0 and visibility = Geometry}}
[RootSignature("DescriptorTable(CBV(b4, numDescriptors=unbounded)), CBV(b45, visibility = SHADER_VISIBILITY_GEOMETRY)")]
void bad_root_signature_11() {}
>From 4c95fa8d84a7eb8ff4d02351e9f1869641906d67 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 20 Jun 2025 22:06:23 +0000
Subject: [PATCH 6/8] self-review: use else if
---
clang/lib/Sema/SemaHLSL.cpp | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 0b3f7fca682c0..73f8bdf59abbb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1116,9 +1116,8 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
Info.Space = Descriptor->Space;
Info.Visibility = Descriptor->Visibility;
Infos.push_back(Info);
- }
- if (const auto *Constants =
- std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
+ } else if (const auto *Constants =
+ std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {
RangeInfo Info;
Info.LowerBound = Constants->Reg.Number;
Info.UpperBound = Info.LowerBound; // use inclusive ranges []
@@ -1127,9 +1126,8 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
Info.Space = Constants->Space;
Info.Visibility = Constants->Visibility;
Infos.push_back(Info);
- }
- if (const auto *Sampler =
- std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
+ } else if (const auto *Sampler =
+ std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {
RangeInfo Info;
Info.LowerBound = Sampler->Reg.Number;
Info.UpperBound = Info.LowerBound; // use inclusive ranges []
@@ -1138,9 +1136,9 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
Info.Space = Sampler->Space;
Info.Visibility = Sampler->Visibility;
Infos.push_back(Info);
- }
- if (const auto *Clause =
- std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(&Elem)) {
+ } else if (const auto *Clause =
+ std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(
+ &Elem)) {
RangeInfo Info;
Info.LowerBound = Clause->Reg.Number;
assert(0 < Clause->NumDescriptors && "Verified as part of TODO(#129940)");
@@ -1153,9 +1151,8 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
Info.Space = Clause->Space;
// Note: Clause does not hold the visibility this will need to
Infos.push_back(Info);
- }
- if (const auto *Table =
- std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
+ } else if (const auto *Table =
+ std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {
// Table holds the Visibility of all owned Clauses in Table, so iterate
// owned Clauses and update their corresponding RangeInfo
assert(Table->NumClauses <= Infos.size() && "RootElement");
>From cc144648e9f6f84468466da2ac25d2ba52f864e6 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 20 Jun 2025 22:20:34 +0000
Subject: [PATCH 7/8] clang format
---
clang/lib/Sema/SemaHLSL.cpp | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 73f8bdf59abbb..f6d01de2810ef 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1142,10 +1142,10 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
RangeInfo Info;
Info.LowerBound = Clause->Reg.Number;
assert(0 < Clause->NumDescriptors && "Verified as part of TODO(#129940)");
- Info.UpperBound =
- Clause->NumDescriptors == RangeInfo::Unbounded
- ? RangeInfo::Unbounded
- : Info.LowerBound + Clause->NumDescriptors - 1; // use inclusive ranges []
+ Info.UpperBound = Clause->NumDescriptors == RangeInfo::Unbounded
+ ? RangeInfo::Unbounded
+ : Info.LowerBound + Clause->NumDescriptors -
+ 1; // use inclusive ranges []
Info.Class = Clause->Type;
Info.Space = Clause->Space;
@@ -1158,7 +1158,8 @@ bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
assert(Table->NumClauses <= Infos.size() && "RootElement");
// The last Table->NumClauses elements of Infos are the owned Clauses
// generated RangeInfo
- auto TableInfos = MutableArrayRef<RangeInfo>(Infos).take_back(Table->NumClauses);
+ auto TableInfos =
+ MutableArrayRef<RangeInfo>(Infos).take_back(Table->NumClauses);
for (RangeInfo &Info : TableInfos)
Info.Visibility = Table->Visibility;
}
>From e924ef99c88b94e25827172e652c3549b8b7c57a Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 20 Jun 2025 23:07:41 +0000
Subject: [PATCH 8/8] self-review: fix invalid root signature in test
---
clang/test/AST/HLSL/RootSignatures-AST.hlsl | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/test/AST/HLSL/RootSignatures-AST.hlsl b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
index c700174da764d..3977542d04323 100644
--- a/clang/test/AST/HLSL/RootSignatures-AST.hlsl
+++ b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
@@ -10,7 +10,7 @@
" CBV(b1), " \
" SRV(t1, numDescriptors = 8, " \
" flags = DESCRIPTORS_VOLATILE), " \
- " UAV(u1, numDescriptors = 0, " \
+ " UAV(u1, numDescriptors = 1, " \
" flags = DESCRIPTORS_VOLATILE) " \
"), " \
"DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
@@ -21,7 +21,7 @@
// 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: UAV(u1, numDescriptors = 1, space = 0,
// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile),
// CHECK-SAME: DescriptorTable(numClauses = 3, visibility = All),
// CHECK-SAME: Sampler(s0, numDescriptors = 4, space = 1,
@@ -48,7 +48,7 @@ void same_rs_main() {}
" CBV(b1), " \
" SRV(t1, numDescriptors = 8, " \
" flags = DESCRIPTORS_VOLATILE), " \
- " UAV(u1, numDescriptors = 0, " \
+ " UAV(u1, numDescriptors = 1, " \
" flags = DESCRIPTORS_VOLATILE) " \
"), " \
"DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
More information about the cfe-commits
mailing list