[clang] [llvm] [HLSL][RootSignature] Implement validation of resource ranges for `RootDescriptors` (PR #140962)
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 19 16:03:43 PDT 2025
================
@@ -1068,10 +1069,139 @@ void SemaHLSL::ActOnFinishRootSignatureDecl(
SemaRef.getASTContext(), /*DeclContext=*/SemaRef.CurContext, Loc,
DeclIdent, Elements);
+ // Perform validation of constructs here
+ if (handleRootSignatureDecl(SignatureDecl, Loc))
+ return;
+
SignatureDecl->setImplicit();
SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope());
}
+bool SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
+ SourceLocation Loc) {
+ auto Elements = D->getRootElements();
+
+ // 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>;
+
+ // 1. Collect RangeInfos
+ llvm::SmallVector<RangeInfo> Infos;
+ for (const auto &Elem : Elements) {
+ if (const auto *Descriptor =
+ std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {
+ RangeInfo Info;
+ Info.LowerBound = Descriptor->Reg.Number;
+ Info.UpperBound = Info.LowerBound; // use inclusive ranges []
+
+ Info.Class =
+ llvm::dxil::ResourceClass(llvm::to_underlying(Descriptor->Type));
+ Info.Space = Descriptor->Space;
+ Info.Vis = Descriptor->Visibility;
+ Infos.push_back(Info);
+ }
+ }
+
+ // 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;
+ SmallVector<ResourceRange, 8> Ranges = {
----------------
bogner wrote:
This has a fixed size, you can just use `std::array`.
```suggestion
std::array<ResourceRange, 8> Ranges = {
```
https://github.com/llvm/llvm-project/pull/140962
More information about the llvm-commits
mailing list