[llvm-branch-commits] [clang] [llvm] [NFC][HLSL] Move resource range logic from `SemaHLSL` to `RootSignatureValidations` (PR #147117)
Finn Plummer via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Jul 4 16:12:26 PDT 2025
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/147117
>From d66a67d9660ab1114d55f75ef2ad5a9cfd35f8f6 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 4 Jul 2025 22:17:37 +0000
Subject: [PATCH 1/2] self-review: remove unused Loc
---
clang/include/clang/Sema/SemaHLSL.h | 3 +--
clang/lib/Sema/SemaHLSL.cpp | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 910e0e640796b..42abd29b01ea7 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -155,8 +155,7 @@ class SemaHLSL : public SemaBase {
// Returns true when D is invalid and a diagnostic was produced
bool
- handleRootSignatureElements(ArrayRef<hlsl::RootSignatureElement> Elements,
- SourceLocation Loc);
+ handleRootSignatureElements(ArrayRef<hlsl::RootSignatureElement> Elements);
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL);
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index f490f957f9667..3feb27ac44bd6 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1082,7 +1082,7 @@ void SemaHLSL::ActOnFinishRootSignatureDecl(
}
bool SemaHLSL::handleRootSignatureElements(
- ArrayRef<hlsl::RootSignatureElement> Elements, SourceLocation Loc) {
+ ArrayRef<hlsl::RootSignatureElement> Elements) {
// The following conducts analysis on resource ranges to detect and report
// any overlaps in resource ranges.
//
>From 969f316004ae500d707be081e6f2f4abc669fff3 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 27 Jun 2025 19:58:15 +0000
Subject: [PATCH 2/2] nfc: move collection of overlaps to
`RootSignatureValidations`
---
clang/lib/Sema/SemaHLSL.cpp | 101 ++----------------
.../Frontend/HLSL/RootSignatureValidations.h | 32 ++++++
.../HLSL/RootSignatureValidations.cpp | 73 +++++++++++++
3 files changed, 115 insertions(+), 91 deletions(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 3feb27ac44bd6..18b84c33b39c8 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1083,29 +1083,8 @@ void SemaHLSL::ActOnFinishRootSignatureDecl(
bool SemaHLSL::handleRootSignatureElements(
ArrayRef<hlsl::RootSignatureElement> Elements) {
- // The following conducts analysis on resource ranges to detect and report
- // any overlaps in resource ranges.
- //
- // A resource range overlaps with another resource range if they have:
- // - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
- // - equivalent resource space
- // - overlapping visbility
- //
- // The following algorithm is implemented in the following steps:
- //
- // 1. Collect RangeInfo from relevant RootElements:
- // - RangeInfo will retain the interval, ResourceClass, Space and Visibility
- // 2. Sort the RangeInfo's such that they are grouped together by
- // ResourceClass and Space (GroupT defined below)
- // 3. Iterate through the collected RangeInfos by their groups
- // - For each group we will have a ResourceRange for each visibility
- // - As we iterate through we will:
- // A: Insert the current RangeInfo into the corresponding Visibility
- // ResourceRange
- // B: Check for overlap with any overlapping Visibility ResourceRange
using RangeInfo = llvm::hlsl::rootsig::RangeInfo;
- using ResourceRange = llvm::hlsl::rootsig::ResourceRange;
- using GroupT = std::pair<ResourceClass, /*Space*/ uint32_t>;
+ using OverlappingRanges = llvm::hlsl::rootsig::OverlappingRanges;
// Introduce a mapping from the collected RangeInfos back to the
// RootSignatureElement that will retain its diagnostics info
@@ -1188,40 +1167,10 @@ bool SemaHLSL::handleRootSignatureElements(
}
}
- // 2. Sort the RangeInfo's by their GroupT to form groupings
- std::sort(Infos.begin(), Infos.end(), [](RangeInfo A, RangeInfo B) {
- return std::tie(A.Class, A.Space) < std::tie(B.Class, B.Space);
- });
-
- // 3. First we will init our state to track:
- if (Infos.size() == 0)
- return false; // No ranges to overlap
- GroupT CurGroup = {Infos[0].Class, Infos[0].Space};
- bool HadOverlap = false;
-
- // Create a ResourceRange for each Visibility
- ResourceRange::MapT::Allocator Allocator;
- std::array<ResourceRange, 8> Ranges = {
- ResourceRange(Allocator), // All
- ResourceRange(Allocator), // Vertex
- ResourceRange(Allocator), // Hull
- ResourceRange(Allocator), // Domain
- ResourceRange(Allocator), // Geometry
- ResourceRange(Allocator), // Pixel
- ResourceRange(Allocator), // Amplification
- ResourceRange(Allocator), // Mesh
- };
-
- // Reset the ResourceRanges for when we iterate through a new group
- auto ClearRanges = [&Ranges]() {
- for (ResourceRange &Range : Ranges)
- Range.clear();
- };
-
// Helper to report diagnostics
- auto ReportOverlap = [this, InfoIndexMap, &HadOverlap](
- const RangeInfo *Info, const RangeInfo *OInfo) {
- HadOverlap = true;
+ auto ReportOverlap = [this, InfoIndexMap](OverlappingRanges Overlap) {
+ const RangeInfo *Info = Overlap.A;
+ const RangeInfo *OInfo = Overlap.B;
auto CommonVis = Info->Visibility == llvm::dxbc::ShaderVisibility::All
? OInfo->Visibility
: Info->Visibility;
@@ -1240,42 +1189,12 @@ bool SemaHLSL::handleRootSignatureElements(
this->Diag(OInfoLoc, diag::note_hlsl_resource_range_here);
};
- // 3: Iterate through collected RangeInfos
- for (const RangeInfo &Info : Infos) {
- GroupT InfoGroup = {Info.Class, Info.Space};
- // Reset our ResourceRanges when we enter a new group
- if (CurGroup != InfoGroup) {
- ClearRanges();
- CurGroup = InfoGroup;
- }
-
- // 3A: Insert range info into corresponding Visibility ResourceRange
- ResourceRange &VisRange = Ranges[llvm::to_underlying(Info.Visibility)];
- if (std::optional<const RangeInfo *> Overlapping = VisRange.insert(Info))
- ReportOverlap(&Info, Overlapping.value());
-
- // 3B: Check for overlap in all overlapping Visibility ResourceRanges
- //
- // If the range that we are inserting has ShaderVisiblity::All it needs to
- // check for an overlap in all other visibility types as well.
- // Otherwise, the range that is inserted needs to check that it does not
- // overlap with ShaderVisibility::All.
- //
- // OverlapRanges will be an ArrayRef to all non-all visibility
- // ResourceRanges in the former case and it will be an ArrayRef to just the
- // all visiblity ResourceRange in the latter case.
- ArrayRef<ResourceRange> OverlapRanges =
- Info.Visibility == llvm::dxbc::ShaderVisibility::All
- ? ArrayRef<ResourceRange>{Ranges}.drop_front()
- : ArrayRef<ResourceRange>{Ranges}.take_front();
-
- for (const ResourceRange &Range : OverlapRanges)
- if (std::optional<const RangeInfo *> Overlapping =
- Range.getOverlapping(Info))
- ReportOverlap(&Info, Overlapping.value());
- }
-
- return HadOverlap;
+ llvm::SmallVector<OverlappingRanges> Overlaps =
+ llvm::hlsl::rootsig::findOverlappingRanges(Infos);
+ for (OverlappingRanges Overlap : Overlaps)
+ ReportOverlap(Overlap);
+
+ return Overlaps.size() != 0;
}
void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {
diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h
index 6bb59027a4cac..0f35850c3922f 100644
--- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h
+++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h
@@ -88,6 +88,38 @@ class ResourceRange {
LLVM_ABI std::optional<const RangeInfo *> insert(const RangeInfo &Info);
};
+struct OverlappingRanges {
+ const RangeInfo *A;
+ const RangeInfo *B;
+
+ OverlappingRanges(const RangeInfo *A, const RangeInfo *B) : A(A), B(B) {}
+};
+
+/// The following conducts analysis on resource ranges to detect and report
+/// any overlaps in resource ranges.
+///
+/// A resource range overlaps with another resource range if they have:
+/// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
+/// - equivalent resource space
+/// - overlapping visbility
+///
+/// The algorithm is implemented in the following steps:
+///
+/// 1. The user will collect RangeInfo from relevant RootElements:
+/// - RangeInfo will retain the interval, ResourceClass, Space and Visibility
+/// - It will also contain an index so that it can be associated to
+/// additional diagnostic information
+/// 2. Sort the RangeInfo's such that they are grouped together by
+/// ResourceClass and Space
+/// 3. Iterate through the collected RangeInfos by their groups
+/// - For each group we will have a ResourceRange for each visibility
+/// - As we iterate through we will:
+/// A: Insert the current RangeInfo into the corresponding Visibility
+/// ResourceRange
+/// B: Check for overlap with any overlapping Visibility ResourceRange
+llvm::SmallVector<OverlappingRanges>
+findOverlappingRanges(llvm::SmallVector<RangeInfo> &Infos);
+
} // namespace rootsig
} // namespace hlsl
} // namespace llvm
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
index 9825946d59690..118b570538f9e 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
@@ -79,6 +79,79 @@ std::optional<const RangeInfo *> ResourceRange::insert(const RangeInfo &Info) {
return Res;
}
+llvm::SmallVector<OverlappingRanges>
+findOverlappingRanges(llvm::SmallVector<RangeInfo> &Infos) {
+ // 1. The user has provided the corresponding range information
+ llvm::SmallVector<OverlappingRanges> Overlaps;
+ using GroupT = std::pair<dxil::ResourceClass, /*Space*/ uint32_t>;
+
+ // 2. Sort the RangeInfo's by their GroupT to form groupings
+ std::sort(Infos.begin(), Infos.end(), [](RangeInfo A, RangeInfo B) {
+ return std::tie(A.Class, A.Space) < std::tie(B.Class, B.Space);
+ });
+
+ // 3. First we will init our state to track:
+ if (Infos.size() == 0)
+ return Overlaps; // No ranges to overlap
+ GroupT CurGroup = {Infos[0].Class, Infos[0].Space};
+
+ // Create a ResourceRange for each Visibility
+ ResourceRange::MapT::Allocator Allocator;
+ std::array<ResourceRange, 8> Ranges = {
+ ResourceRange(Allocator), // All
+ ResourceRange(Allocator), // Vertex
+ ResourceRange(Allocator), // Hull
+ ResourceRange(Allocator), // Domain
+ ResourceRange(Allocator), // Geometry
+ ResourceRange(Allocator), // Pixel
+ ResourceRange(Allocator), // Amplification
+ ResourceRange(Allocator), // Mesh
+ };
+
+ // Reset the ResourceRanges for when we iterate through a new group
+ auto ClearRanges = [&Ranges]() {
+ for (ResourceRange &Range : Ranges)
+ Range.clear();
+ };
+
+ // 3: Iterate through collected RangeInfos
+ for (const RangeInfo &Info : Infos) {
+ GroupT InfoGroup = {Info.Class, Info.Space};
+ // Reset our ResourceRanges when we enter a new group
+ if (CurGroup != InfoGroup) {
+ ClearRanges();
+ CurGroup = InfoGroup;
+ }
+
+ // 3A: Insert range info into corresponding Visibility ResourceRange
+ ResourceRange &VisRange = Ranges[llvm::to_underlying(Info.Visibility)];
+ if (std::optional<const RangeInfo *> Overlapping = VisRange.insert(Info))
+ Overlaps.push_back(OverlappingRanges(&Info, Overlapping.value()));
+
+ // 3B: Check for overlap in all overlapping Visibility ResourceRanges
+ //
+ // If the range that we are inserting has ShaderVisiblity::All it needs to
+ // check for an overlap in all other visibility types as well.
+ // Otherwise, the range that is inserted needs to check that it does not
+ // overlap with ShaderVisibility::All.
+ //
+ // OverlapRanges will be an ArrayRef to all non-all visibility
+ // ResourceRanges in the former case and it will be an ArrayRef to just the
+ // all visiblity ResourceRange in the latter case.
+ ArrayRef<ResourceRange> OverlapRanges =
+ Info.Visibility == llvm::dxbc::ShaderVisibility::All
+ ? ArrayRef<ResourceRange>{Ranges}.drop_front()
+ : ArrayRef<ResourceRange>{Ranges}.take_front();
+
+ for (const ResourceRange &Range : OverlapRanges)
+ if (std::optional<const RangeInfo *> Overlapping =
+ Range.getOverlapping(Info))
+ Overlaps.push_back(OverlappingRanges(&Info, Overlapping.value()));
+ }
+
+ return Overlaps;
+}
+
} // namespace rootsig
} // namespace hlsl
} // namespace llvm
More information about the llvm-branch-commits
mailing list