1313#ifndef LLVM_FRONTEND_HLSL_HLSLBINDING_H
1414#define LLVM_FRONTEND_HLSL_HLSLBINDING_H
1515
16+ #include " llvm/ADT/STLExtras.h"
1617#include " llvm/ADT/STLFunctionalExtras.h"
1718#include " llvm/ADT/SmallVector.h"
1819#include " llvm/Support/Compiler.h"
2223namespace llvm {
2324namespace hlsl {
2425
25- struct BindingRange {
26- uint32_t LowerBound;
27- uint32_t UpperBound;
28- BindingRange (uint32_t LB, uint32_t UB) : LowerBound(LB), UpperBound(UB) {}
29-
30- bool overlapsWith (const BindingRange &Other) const {
31- return !(
32- (Other.LowerBound < LowerBound && Other.UpperBound <= LowerBound) ||
33- (Other.LowerBound >= UpperBound && Other.UpperBound > UpperBound));
34- }
35- };
36-
37- struct BaseRegisterSpace {
38- protected:
39- uint32_t Space;
40- SmallVector<BindingRange> Ranges;
41- BaseRegisterSpace (uint32_t Space) : Space(Space) {}
42- public:
43- bool operator ==(const BaseRegisterSpace &Other) const {
44- return Space == Other.Space ;
45- }
46- };
47-
48- struct FreeRegisterSpace : public BaseRegisterSpace {
49- using BaseRegisterSpace::BaseRegisterSpace;
50-
51- FreeRegisterSpace (uint32_t Space) : BaseRegisterSpace(Space) {
52- Ranges.emplace_back (0 , ~0u );
53- }
54- // Size == -1 means unbounded array
55- LLVM_ABI std::optional<uint32_t > findAvailableBinding (int32_t Size);
56- };
57-
58- struct BusyRegisterSpace : public BaseRegisterSpace {
59- using BaseRegisterSpace::BaseRegisterSpace;
60-
61- BusyRegisterSpace (uint32_t Space) : BaseRegisterSpace(Space) {}
62-
63- LLVM_ABI bool isBound (const BindingRange &Range) const ;
64- };
65-
66- template <typename T> struct BindingSpaces {
67- dxil::ResourceClass RC;
68- llvm::SmallVector<T> Spaces;
69- BindingSpaces (dxil::ResourceClass RC) : RC(RC) {}
70- LLVM_ABI T &getOrInsertSpace (uint32_t Space);
71- LLVM_ABI std::optional<const T *> contains (uint32_t Space) const ;
72- };
73-
7426// / BindingInfo represents the ranges of bindings and free space for each
7527// / `dxil::ResourceClass`. This can represent HLSL-level bindings as well as
7628// / bindings described in root signatures, and can be used for analysis of
@@ -92,48 +44,45 @@ template <typename T> struct BindingSpaces {
9244// / }
9345// / }
9446class BindingInfo {
95- private:
96- BindingSpaces<FreeRegisterSpace> SRVSpaces{dxil::ResourceClass::SRV};
97- BindingSpaces<FreeRegisterSpace> UAVSpaces{dxil::ResourceClass::UAV};
98- BindingSpaces<FreeRegisterSpace> CBufferSpaces{dxil::ResourceClass::CBuffer};
99- BindingSpaces<FreeRegisterSpace> SamplerSpaces{dxil::ResourceClass::Sampler};
100-
10147public:
102- BindingSpaces<FreeRegisterSpace> &getBindingSpaces (dxil::ResourceClass RC) {
103- switch (RC) {
104- case dxil::ResourceClass::SRV:
105- return SRVSpaces;
106- case dxil::ResourceClass::UAV:
107- return UAVSpaces;
108- case dxil::ResourceClass::CBuffer:
109- return CBufferSpaces;
110- case dxil::ResourceClass::Sampler:
111- return SamplerSpaces;
112- }
48+ struct BindingRange {
49+ uint32_t LowerBound;
50+ uint32_t UpperBound;
51+ BindingRange (uint32_t LB, uint32_t UB) : LowerBound(LB), UpperBound(UB) {}
52+ };
11353
114- llvm_unreachable (" Invalid resource class" );
115- }
116- const BindingSpaces<FreeRegisterSpace> &
117- getBindingSpaces (dxil::ResourceClass RC) const {
118- return const_cast <BindingInfo *>(this )->getBindingSpaces (RC);
119- }
54+ struct RegisterSpace {
55+ uint32_t Space;
56+ SmallVector<BindingRange> FreeRanges;
57+ RegisterSpace (uint32_t Space) : Space(Space) {
58+ FreeRanges.emplace_back (0 , ~0u );
59+ }
60+ // Size == -1 means unbounded array
61+ LLVM_ABI std::optional<uint32_t > findAvailableBinding (int32_t Size);
62+ LLVM_ABI bool isBound (const BindingRange &Range) const ;
12063
121- // Size == -1 means unbounded array
122- LLVM_ABI std::optional<uint32_t >
123- findAvailableBinding (dxil::ResourceClass RC, uint32_t Space, int32_t Size);
64+ bool operator ==(const RegisterSpace &Other) const {
65+ return Space == Other.Space ;
66+ }
67+ };
12468
125- friend class BindingInfoBuilder ;
126- };
69+ struct BindingSpaces {
70+ dxil::ResourceClass RC;
71+ llvm::SmallVector<RegisterSpace> Spaces;
72+ BindingSpaces (dxil::ResourceClass RC) : RC(RC) {}
73+ LLVM_ABI RegisterSpace &getOrInsertSpace (uint32_t Space);
74+ LLVM_ABI std::optional<const BindingInfo::RegisterSpace *>
75+ contains (uint32_t Space) const ;
76+ };
12777
128- class BusyBindingInfo {
12978private:
130- BindingSpaces<BusyRegisterSpace> SRVSpaces{dxil::ResourceClass::SRV};
131- BindingSpaces<BusyRegisterSpace> UAVSpaces{dxil::ResourceClass::UAV};
132- BindingSpaces<BusyRegisterSpace> CBufferSpaces{dxil::ResourceClass::CBuffer};
133- BindingSpaces<BusyRegisterSpace> SamplerSpaces{dxil::ResourceClass::Sampler};
79+ BindingSpaces SRVSpaces{dxil::ResourceClass::SRV};
80+ BindingSpaces UAVSpaces{dxil::ResourceClass::UAV};
81+ BindingSpaces CBufferSpaces{dxil::ResourceClass::CBuffer};
82+ BindingSpaces SamplerSpaces{dxil::ResourceClass::Sampler};
13483
13584public:
136- BindingSpaces<BusyRegisterSpace> &getBindingSpaces (dxil::ResourceClass RC) {
85+ BindingSpaces &getBindingSpaces (dxil::ResourceClass RC) {
13786 switch (RC) {
13887 case dxil::ResourceClass::SRV:
13988 return SRVSpaces;
@@ -147,20 +96,19 @@ class BusyBindingInfo {
14796
14897 llvm_unreachable (" Invalid resource class" );
14998 }
150- const BindingSpaces<BusyRegisterSpace> &
151- getBindingSpaces (dxil::ResourceClass RC) const {
152- return const_cast <BusyBindingInfo *>(this )->getBindingSpaces (RC);
99+ const BindingSpaces &getBindingSpaces (dxil::ResourceClass RC) const {
100+ return const_cast <BindingInfo *>(this )->getBindingSpaces (RC);
153101 }
154102
103+ // Size == -1 means unbounded array
104+ LLVM_ABI std::optional<uint32_t >
105+ findAvailableBinding (dxil::ResourceClass RC, uint32_t Space, int32_t Size);
106+
155107 LLVM_ABI bool isBound (dxil::ResourceClass RC, uint32_t Space,
156108 const BindingRange &Range) const ;
157109
158110 friend class BindingInfoBuilder ;
159111};
160-
161- // / Builder class for creating a /c BindingInfo.
162- class BindingInfoBuilder {
163- public:
164112 struct Binding {
165113 dxil::ResourceClass RC;
166114 uint32_t Space;
@@ -187,39 +135,62 @@ class BindingInfoBuilder {
187135 std::tie (RHS.RC , RHS.Space , RHS.LowerBound );
188136 }
189137 };
138+ class BoundRegs {
139+ SmallVector<Binding> Bindings;
190140
191- private:
192- SmallVector<Binding> Bindings;
141+ public:
142+ BoundRegs (SmallVector<Binding> &&Bindings)
143+ : Bindings(std::move(Bindings)) {}
144+
145+ bool isBound (dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound,
146+ uint32_t UpperBound) const {
147+ const Binding *It = llvm::upper_bound (
148+ Bindings, Binding{RC, Space, LowerBound, 0 , nullptr });
149+ if (It == Bindings.begin ())
150+ return false ;
151+ --It;
152+ return It->RC == RC && It->Space == Space &&
153+ It->LowerBound <= LowerBound && It->UpperBound >= UpperBound;
154+ }
155+ };
193156
194- public:
195- void trackBinding (dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound,
196- uint32_t UpperBound, const void *Cookie) {
197- Bindings.emplace_back (RC, Space, LowerBound, UpperBound, Cookie);
198- }
199- // / Calculate the binding info - \c ReportOverlap will be called once for each
200- // / overlapping binding.
201- LLVM_ABI BindingInfo calculateBindingInfo (
202- llvm::function_ref<void (const BindingInfoBuilder &Builder,
203- const Binding &Overlapping)>
204- ReportOverlap);
205-
206- // / Calculate the binding info - \c HasOverlap will be set to indicate whether
207- // / there are any overlapping bindings.
208- BindingInfo calculateBindingInfo (bool &HasOverlap) {
209- HasOverlap = false ;
210- return calculateBindingInfo (
211- [&HasOverlap](auto , auto ) { HasOverlap = true ; });
212- }
157+ // / Builder class for creating a /c BindingInfo.
158+ class BindingInfoBuilder {
159+ public:
160+ private:
161+ SmallVector<Binding> Bindings;
162+
163+ public:
164+ void trackBinding (dxil::ResourceClass RC, uint32_t Space,
165+ uint32_t LowerBound, uint32_t UpperBound,
166+ const void *Cookie) {
167+ Bindings.emplace_back (RC, Space, LowerBound, UpperBound, Cookie);
168+ }
169+ // / Calculate the binding info - \c ReportOverlap will be called once for
170+ // / each overlapping binding.
171+ LLVM_ABI BindingInfo calculateBindingInfo (
172+ llvm::function_ref<void (const BindingInfoBuilder &Builder,
173+ const Binding &Overlapping)>
174+ ReportOverlap);
175+
176+ // / Calculate the binding info - \c HasOverlap will be set to indicate
177+ // / whether there are any overlapping bindings.
178+ BindingInfo calculateBindingInfo (bool &HasOverlap) {
179+ HasOverlap = false ;
180+ return calculateBindingInfo (
181+ [&HasOverlap](auto , auto ) { HasOverlap = true ; });
182+ }
213183
214- LLVM_ABI BusyBindingInfo calculateBusyBindingInfo (
215- llvm::function_ref<void (const BindingInfoBuilder &Builder,
216- const Binding &Overlapping)>
217- ReportOverlap);
184+ BoundRegs calculateBoundRegs (
185+ llvm::function_ref<void (const BindingInfoBuilder &Builder,
186+ const Binding &Overlapping)>
187+ ReportOverlap);
218188
219- // / For use in the \c ReportOverlap callback of \c calculateBindingInfo -
220- // / finds a binding that the \c ReportedBinding overlaps with.
221- LLVM_ABI const Binding &findOverlapping (const Binding &ReportedBinding) const ;
222- };
189+ // / For use in the \c ReportOverlap callback of \c calculateBindingInfo -
190+ // / finds a binding that the \c ReportedBinding overlaps with.
191+ LLVM_ABI const Binding &
192+ findOverlapping (const Binding &ReportedBinding) const ;
193+ };
223194
224195} // namespace hlsl
225196} // namespace llvm
0 commit comments