Skip to content

Commit 969f316

Browse files
committed
nfc: move collection of overlaps to RootSignatureValidations
1 parent d66a67d commit 969f316

File tree

3 files changed

+115
-91
lines changed

3 files changed

+115
-91
lines changed

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 10 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,29 +1083,8 @@ void SemaHLSL::ActOnFinishRootSignatureDecl(
10831083

10841084
bool SemaHLSL::handleRootSignatureElements(
10851085
ArrayRef<hlsl::RootSignatureElement> Elements) {
1086-
// The following conducts analysis on resource ranges to detect and report
1087-
// any overlaps in resource ranges.
1088-
//
1089-
// A resource range overlaps with another resource range if they have:
1090-
// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
1091-
// - equivalent resource space
1092-
// - overlapping visbility
1093-
//
1094-
// The following algorithm is implemented in the following steps:
1095-
//
1096-
// 1. Collect RangeInfo from relevant RootElements:
1097-
// - RangeInfo will retain the interval, ResourceClass, Space and Visibility
1098-
// 2. Sort the RangeInfo's such that they are grouped together by
1099-
// ResourceClass and Space (GroupT defined below)
1100-
// 3. Iterate through the collected RangeInfos by their groups
1101-
// - For each group we will have a ResourceRange for each visibility
1102-
// - As we iterate through we will:
1103-
// A: Insert the current RangeInfo into the corresponding Visibility
1104-
// ResourceRange
1105-
// B: Check for overlap with any overlapping Visibility ResourceRange
11061086
using RangeInfo = llvm::hlsl::rootsig::RangeInfo;
1107-
using ResourceRange = llvm::hlsl::rootsig::ResourceRange;
1108-
using GroupT = std::pair<ResourceClass, /*Space*/ uint32_t>;
1087+
using OverlappingRanges = llvm::hlsl::rootsig::OverlappingRanges;
11091088

11101089
// Introduce a mapping from the collected RangeInfos back to the
11111090
// RootSignatureElement that will retain its diagnostics info
@@ -1188,40 +1167,10 @@ bool SemaHLSL::handleRootSignatureElements(
11881167
}
11891168
}
11901169

1191-
// 2. Sort the RangeInfo's by their GroupT to form groupings
1192-
std::sort(Infos.begin(), Infos.end(), [](RangeInfo A, RangeInfo B) {
1193-
return std::tie(A.Class, A.Space) < std::tie(B.Class, B.Space);
1194-
});
1195-
1196-
// 3. First we will init our state to track:
1197-
if (Infos.size() == 0)
1198-
return false; // No ranges to overlap
1199-
GroupT CurGroup = {Infos[0].Class, Infos[0].Space};
1200-
bool HadOverlap = false;
1201-
1202-
// Create a ResourceRange for each Visibility
1203-
ResourceRange::MapT::Allocator Allocator;
1204-
std::array<ResourceRange, 8> Ranges = {
1205-
ResourceRange(Allocator), // All
1206-
ResourceRange(Allocator), // Vertex
1207-
ResourceRange(Allocator), // Hull
1208-
ResourceRange(Allocator), // Domain
1209-
ResourceRange(Allocator), // Geometry
1210-
ResourceRange(Allocator), // Pixel
1211-
ResourceRange(Allocator), // Amplification
1212-
ResourceRange(Allocator), // Mesh
1213-
};
1214-
1215-
// Reset the ResourceRanges for when we iterate through a new group
1216-
auto ClearRanges = [&Ranges]() {
1217-
for (ResourceRange &Range : Ranges)
1218-
Range.clear();
1219-
};
1220-
12211170
// Helper to report diagnostics
1222-
auto ReportOverlap = [this, InfoIndexMap, &HadOverlap](
1223-
const RangeInfo *Info, const RangeInfo *OInfo) {
1224-
HadOverlap = true;
1171+
auto ReportOverlap = [this, InfoIndexMap](OverlappingRanges Overlap) {
1172+
const RangeInfo *Info = Overlap.A;
1173+
const RangeInfo *OInfo = Overlap.B;
12251174
auto CommonVis = Info->Visibility == llvm::dxbc::ShaderVisibility::All
12261175
? OInfo->Visibility
12271176
: Info->Visibility;
@@ -1240,42 +1189,12 @@ bool SemaHLSL::handleRootSignatureElements(
12401189
this->Diag(OInfoLoc, diag::note_hlsl_resource_range_here);
12411190
};
12421191

1243-
// 3: Iterate through collected RangeInfos
1244-
for (const RangeInfo &Info : Infos) {
1245-
GroupT InfoGroup = {Info.Class, Info.Space};
1246-
// Reset our ResourceRanges when we enter a new group
1247-
if (CurGroup != InfoGroup) {
1248-
ClearRanges();
1249-
CurGroup = InfoGroup;
1250-
}
1251-
1252-
// 3A: Insert range info into corresponding Visibility ResourceRange
1253-
ResourceRange &VisRange = Ranges[llvm::to_underlying(Info.Visibility)];
1254-
if (std::optional<const RangeInfo *> Overlapping = VisRange.insert(Info))
1255-
ReportOverlap(&Info, Overlapping.value());
1256-
1257-
// 3B: Check for overlap in all overlapping Visibility ResourceRanges
1258-
//
1259-
// If the range that we are inserting has ShaderVisiblity::All it needs to
1260-
// check for an overlap in all other visibility types as well.
1261-
// Otherwise, the range that is inserted needs to check that it does not
1262-
// overlap with ShaderVisibility::All.
1263-
//
1264-
// OverlapRanges will be an ArrayRef to all non-all visibility
1265-
// ResourceRanges in the former case and it will be an ArrayRef to just the
1266-
// all visiblity ResourceRange in the latter case.
1267-
ArrayRef<ResourceRange> OverlapRanges =
1268-
Info.Visibility == llvm::dxbc::ShaderVisibility::All
1269-
? ArrayRef<ResourceRange>{Ranges}.drop_front()
1270-
: ArrayRef<ResourceRange>{Ranges}.take_front();
1271-
1272-
for (const ResourceRange &Range : OverlapRanges)
1273-
if (std::optional<const RangeInfo *> Overlapping =
1274-
Range.getOverlapping(Info))
1275-
ReportOverlap(&Info, Overlapping.value());
1276-
}
1277-
1278-
return HadOverlap;
1192+
llvm::SmallVector<OverlappingRanges> Overlaps =
1193+
llvm::hlsl::rootsig::findOverlappingRanges(Infos);
1194+
for (OverlappingRanges Overlap : Overlaps)
1195+
ReportOverlap(Overlap);
1196+
1197+
return Overlaps.size() != 0;
12791198
}
12801199

12811200
void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {

llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,38 @@ class ResourceRange {
8888
LLVM_ABI std::optional<const RangeInfo *> insert(const RangeInfo &Info);
8989
};
9090

91+
struct OverlappingRanges {
92+
const RangeInfo *A;
93+
const RangeInfo *B;
94+
95+
OverlappingRanges(const RangeInfo *A, const RangeInfo *B) : A(A), B(B) {}
96+
};
97+
98+
/// The following conducts analysis on resource ranges to detect and report
99+
/// any overlaps in resource ranges.
100+
///
101+
/// A resource range overlaps with another resource range if they have:
102+
/// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
103+
/// - equivalent resource space
104+
/// - overlapping visbility
105+
///
106+
/// The algorithm is implemented in the following steps:
107+
///
108+
/// 1. The user will collect RangeInfo from relevant RootElements:
109+
/// - RangeInfo will retain the interval, ResourceClass, Space and Visibility
110+
/// - It will also contain an index so that it can be associated to
111+
/// additional diagnostic information
112+
/// 2. Sort the RangeInfo's such that they are grouped together by
113+
/// ResourceClass and Space
114+
/// 3. Iterate through the collected RangeInfos by their groups
115+
/// - For each group we will have a ResourceRange for each visibility
116+
/// - As we iterate through we will:
117+
/// A: Insert the current RangeInfo into the corresponding Visibility
118+
/// ResourceRange
119+
/// B: Check for overlap with any overlapping Visibility ResourceRange
120+
llvm::SmallVector<OverlappingRanges>
121+
findOverlappingRanges(llvm::SmallVector<RangeInfo> &Infos);
122+
91123
} // namespace rootsig
92124
} // namespace hlsl
93125
} // namespace llvm

llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,79 @@ std::optional<const RangeInfo *> ResourceRange::insert(const RangeInfo &Info) {
7979
return Res;
8080
}
8181

82+
llvm::SmallVector<OverlappingRanges>
83+
findOverlappingRanges(llvm::SmallVector<RangeInfo> &Infos) {
84+
// 1. The user has provided the corresponding range information
85+
llvm::SmallVector<OverlappingRanges> Overlaps;
86+
using GroupT = std::pair<dxil::ResourceClass, /*Space*/ uint32_t>;
87+
88+
// 2. Sort the RangeInfo's by their GroupT to form groupings
89+
std::sort(Infos.begin(), Infos.end(), [](RangeInfo A, RangeInfo B) {
90+
return std::tie(A.Class, A.Space) < std::tie(B.Class, B.Space);
91+
});
92+
93+
// 3. First we will init our state to track:
94+
if (Infos.size() == 0)
95+
return Overlaps; // No ranges to overlap
96+
GroupT CurGroup = {Infos[0].Class, Infos[0].Space};
97+
98+
// Create a ResourceRange for each Visibility
99+
ResourceRange::MapT::Allocator Allocator;
100+
std::array<ResourceRange, 8> Ranges = {
101+
ResourceRange(Allocator), // All
102+
ResourceRange(Allocator), // Vertex
103+
ResourceRange(Allocator), // Hull
104+
ResourceRange(Allocator), // Domain
105+
ResourceRange(Allocator), // Geometry
106+
ResourceRange(Allocator), // Pixel
107+
ResourceRange(Allocator), // Amplification
108+
ResourceRange(Allocator), // Mesh
109+
};
110+
111+
// Reset the ResourceRanges for when we iterate through a new group
112+
auto ClearRanges = [&Ranges]() {
113+
for (ResourceRange &Range : Ranges)
114+
Range.clear();
115+
};
116+
117+
// 3: Iterate through collected RangeInfos
118+
for (const RangeInfo &Info : Infos) {
119+
GroupT InfoGroup = {Info.Class, Info.Space};
120+
// Reset our ResourceRanges when we enter a new group
121+
if (CurGroup != InfoGroup) {
122+
ClearRanges();
123+
CurGroup = InfoGroup;
124+
}
125+
126+
// 3A: Insert range info into corresponding Visibility ResourceRange
127+
ResourceRange &VisRange = Ranges[llvm::to_underlying(Info.Visibility)];
128+
if (std::optional<const RangeInfo *> Overlapping = VisRange.insert(Info))
129+
Overlaps.push_back(OverlappingRanges(&Info, Overlapping.value()));
130+
131+
// 3B: Check for overlap in all overlapping Visibility ResourceRanges
132+
//
133+
// If the range that we are inserting has ShaderVisiblity::All it needs to
134+
// check for an overlap in all other visibility types as well.
135+
// Otherwise, the range that is inserted needs to check that it does not
136+
// overlap with ShaderVisibility::All.
137+
//
138+
// OverlapRanges will be an ArrayRef to all non-all visibility
139+
// ResourceRanges in the former case and it will be an ArrayRef to just the
140+
// all visiblity ResourceRange in the latter case.
141+
ArrayRef<ResourceRange> OverlapRanges =
142+
Info.Visibility == llvm::dxbc::ShaderVisibility::All
143+
? ArrayRef<ResourceRange>{Ranges}.drop_front()
144+
: ArrayRef<ResourceRange>{Ranges}.take_front();
145+
146+
for (const ResourceRange &Range : OverlapRanges)
147+
if (std::optional<const RangeInfo *> Overlapping =
148+
Range.getOverlapping(Info))
149+
Overlaps.push_back(OverlappingRanges(&Info, Overlapping.value()));
150+
}
151+
152+
return Overlaps;
153+
}
154+
82155
} // namespace rootsig
83156
} // namespace hlsl
84157
} // namespace llvm

0 commit comments

Comments
 (0)