xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- RootSignatureValidations.h - HLSL Root Signature helpers -----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file This file contains helper obejcts for working with HLSL Root
10 /// Signatures.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_FRONTEND_HLSL_ROOTSIGNATUREVALIDATIONS_H
15 #define LLVM_FRONTEND_HLSL_ROOTSIGNATUREVALIDATIONS_H
16 
17 #include "llvm/ADT/IntervalMap.h"
18 #include "llvm/Frontend/HLSL/HLSLRootSignature.h"
19 #include "llvm/Support/Compiler.h"
20 
21 namespace llvm {
22 namespace hlsl {
23 namespace rootsig {
24 
25 // Basic verification of RootElements
26 
27 LLVM_ABI bool verifyRootFlag(uint32_t Flags);
28 LLVM_ABI bool verifyVersion(uint32_t Version);
29 LLVM_ABI bool verifyRegisterValue(uint32_t RegisterValue);
30 LLVM_ABI bool verifyRegisterSpace(uint32_t RegisterSpace);
31 LLVM_ABI bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal);
32 LLVM_ABI bool verifyRangeType(uint32_t Type);
33 LLVM_ABI bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
34                                         uint32_t FlagsVal);
35 LLVM_ABI bool verifyNumDescriptors(uint32_t NumDescriptors);
36 LLVM_ABI bool verifySamplerFilter(uint32_t Value);
37 LLVM_ABI bool verifyAddress(uint32_t Address);
38 LLVM_ABI bool verifyMipLODBias(float MipLODBias);
39 LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy);
40 LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc);
41 LLVM_ABI bool verifyBorderColor(uint32_t BorderColor);
42 LLVM_ABI bool verifyLOD(float LOD);
43 
44 struct RangeInfo {
45   const static uint32_t Unbounded = ~0u;
46 
47   // Interval information
48   uint32_t LowerBound;
49   uint32_t UpperBound;
50 
51   // Information retained for determining overlap
52   llvm::dxil::ResourceClass Class;
53   uint32_t Space;
54   llvm::dxbc::ShaderVisibility Visibility;
55 
56   bool operator==(const RangeInfo &RHS) const {
57     return std::tie(LowerBound, UpperBound, Class, Space, Visibility) ==
58            std::tie(RHS.LowerBound, RHS.UpperBound, RHS.Class, RHS.Space,
59                     RHS.Visibility);
60   }
61 
62   bool operator<(const RangeInfo &RHS) const {
63     return std::tie(Class, Space, LowerBound, UpperBound, Visibility) <
64            std::tie(RHS.Class, RHS.Space, RHS.LowerBound, RHS.UpperBound,
65                     RHS.Visibility);
66   }
67 };
68 
69 class ResourceRange {
70 public:
71   using MapT = llvm::IntervalMap<uint32_t, const RangeInfo *, 16,
72                                  llvm::IntervalMapInfo<uint32_t>>;
73 
74 private:
75   MapT Intervals;
76 
77 public:
ResourceRange(MapT::Allocator & Allocator)78   ResourceRange(MapT::Allocator &Allocator) : Intervals(MapT(Allocator)) {}
79 
80   // Returns a reference to the first RangeInfo that overlaps with
81   // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
82   LLVM_ABI std::optional<const RangeInfo *>
83   getOverlapping(const RangeInfo &Info) const;
84 
85   // Return the mapped RangeInfo at X or nullptr if no mapping exists
86   LLVM_ABI const RangeInfo *lookup(uint32_t X) const;
87 
88   // Removes all entries of the ResourceRange
89   LLVM_ABI void clear();
90 
91   // Insert the required (sub-)intervals such that the interval of [a;b] =
92   // [Info.LowerBound, Info.UpperBound] is covered and points to a valid
93   // RangeInfo &.
94   //
95   // For instance consider the following chain of inserting RangeInfos with the
96   // intervals denoting the Lower/Upper-bounds:
97   //
98   // A = [0;2]
99   //   insert(A) -> false
100   //   intervals: [0;2] -> &A
101   // B = [5;7]
102   //   insert(B) -> false
103   //   intervals: [0;2] -> &A, [5;7] -> &B
104   // C = [4;7]
105   //   insert(C) -> true
106   //   intervals: [0;2] -> &A, [4;7] -> &C
107   // D = [1;5]
108   //   insert(D) -> true
109   //   intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C
110   // E = [0;unbounded]
111   //   insert(E) -> true
112   //   intervals: [0;unbounded] -> E
113   //
114   // Returns a reference to the first RangeInfo that overlaps with
115   // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
116   // (equivalent to getOverlapping)
117   LLVM_ABI std::optional<const RangeInfo *> insert(const RangeInfo &Info);
118 };
119 
120 struct OverlappingRanges {
121   const RangeInfo *A;
122   const RangeInfo *B;
123 
OverlappingRangesOverlappingRanges124   OverlappingRanges(const RangeInfo *A, const RangeInfo *B) : A(A), B(B) {}
125 };
126 
127 /// The following conducts analysis on resource ranges to detect and report
128 /// any overlaps in resource ranges.
129 ///
130 /// A resource range overlaps with another resource range if they have:
131 /// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
132 /// - equivalent resource space
133 /// - overlapping visbility
134 ///
135 /// The algorithm is implemented in the following steps:
136 ///
137 /// 1. The user will collect RangeInfo from relevant RootElements:
138 ///   - RangeInfo will retain the interval, ResourceClass, Space and Visibility
139 ///   - It will also contain an index so that it can be associated to
140 /// additional diagnostic information
141 /// 2. The user is required to sort the RangeInfo's such that they are grouped
142 /// together by ResourceClass and Space
143 /// 3. Iterate through the collected RangeInfos by their groups
144 ///   - For each group we will have a ResourceRange for each visibility
145 ///   - As we iterate through we will:
146 ///      A: Insert the current RangeInfo into the corresponding Visibility
147 ///   ResourceRange
148 ///      B: Check for overlap with any overlapping Visibility ResourceRange
149 LLVM_ABI llvm::SmallVector<OverlappingRanges>
150 findOverlappingRanges(ArrayRef<RangeInfo> Infos);
151 
152 } // namespace rootsig
153 } // namespace hlsl
154 } // namespace llvm
155 
156 #endif // LLVM_FRONTEND_HLSL_ROOTSIGNATUREVALIDATIONS_H
157