Skip to content

Commit 09d0104

Browse files
committed
wip: Extract HLSLBinding out of DXILResource
TODO: - Move unit tests - Slim API
1 parent 8e9a0fc commit 09d0104

File tree

9 files changed

+545
-212
lines changed

9 files changed

+545
-212
lines changed

llvm/include/llvm/Analysis/DXILResource.h

Lines changed: 13 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "llvm/ADT/MapVector.h"
1313
#include "llvm/ADT/SmallVector.h"
1414
#include "llvm/ADT/StringRef.h"
15+
#include "llvm/Frontend/HLSL/HLSLBinding.h"
1516
#include "llvm/IR/DerivedTypes.h"
1617
#include "llvm/IR/GlobalVariable.h"
1718
#include "llvm/IR/PassManager.h"
@@ -633,86 +634,29 @@ LLVM_ABI ModulePass *createDXILResourceWrapperPassPass();
633634
// register slots to resources with implicit bindings, and in a
634635
// post-optimization validation pass that will raise diagnostic about
635636
// overlapping bindings.
636-
//
637-
// For example for these resource bindings:
638-
//
639-
// RWBuffer<float> A[10] : register(u3);
640-
// RWBuffer<float> B[] : register(u5, space2)
641-
//
642-
// The analysis result for UAV binding type will look like this:
643-
//
644-
// UAVSpaces {
645-
// ResClass = ResourceClass::UAV,
646-
// Spaces = {
647-
// { Space = 0, FreeRanges = {{ 0, 2 }, { 13, UINT32_MAX }} },
648-
// { Space = 2, FreeRanges = {{ 0, 4 }} }
649-
// }
650-
// }
651-
//
652637
class DXILResourceBindingInfo {
653-
public:
654-
struct BindingRange {
655-
uint32_t LowerBound;
656-
uint32_t UpperBound;
657-
BindingRange(uint32_t LB, uint32_t UB) : LowerBound(LB), UpperBound(UB) {}
658-
};
659-
660-
struct RegisterSpace {
661-
uint32_t Space;
662-
SmallVector<BindingRange> FreeRanges;
663-
RegisterSpace(uint32_t Space) : Space(Space) {
664-
FreeRanges.emplace_back(0, UINT32_MAX);
665-
}
666-
// Size == -1 means unbounded array
667-
LLVM_ABI std::optional<uint32_t> findAvailableBinding(int32_t Size);
668-
};
669-
670-
struct BindingSpaces {
671-
dxil::ResourceClass RC;
672-
llvm::SmallVector<RegisterSpace> Spaces;
673-
BindingSpaces(dxil::ResourceClass RC) : RC(RC) {}
674-
LLVM_ABI RegisterSpace &getOrInsertSpace(uint32_t Space);
675-
};
676-
677-
private:
678-
BindingSpaces SRVSpaces, UAVSpaces, CBufferSpaces, SamplerSpaces;
679-
bool ImplicitBinding;
680-
bool OverlappingBinding;
638+
hlsl::BindingInfo Bindings;
639+
bool HasImplicitBinding = false;
640+
bool HasOverlappingBinding = false;
681641

682642
// Populate the resource binding info given explicit resource binding calls
683643
// in the module.
684644
void populate(Module &M, DXILResourceTypeMap &DRTM);
685645

686646
public:
687-
DXILResourceBindingInfo()
688-
: SRVSpaces(dxil::ResourceClass::SRV),
689-
UAVSpaces(dxil::ResourceClass::UAV),
690-
CBufferSpaces(dxil::ResourceClass::CBuffer),
691-
SamplerSpaces(dxil::ResourceClass::Sampler), ImplicitBinding(false),
692-
OverlappingBinding(false) {}
693-
694-
bool hasImplicitBinding() const { return ImplicitBinding; }
695-
void setHasImplicitBinding(bool Value) { ImplicitBinding = Value; }
696-
bool hasOverlappingBinding() const { return OverlappingBinding; }
697-
698-
BindingSpaces &getBindingSpaces(dxil::ResourceClass RC) {
699-
switch (RC) {
700-
case dxil::ResourceClass::SRV:
701-
return SRVSpaces;
702-
case dxil::ResourceClass::UAV:
703-
return UAVSpaces;
704-
case dxil::ResourceClass::CBuffer:
705-
return CBufferSpaces;
706-
case dxil::ResourceClass::Sampler:
707-
return SamplerSpaces;
708-
}
647+
bool hasImplicitBinding() const { return HasImplicitBinding; }
648+
void setHasImplicitBinding(bool Value) { HasImplicitBinding = Value; }
649+
bool hasOverlappingBinding() const { return HasOverlappingBinding; }
650+
void setHasOverlappingBinding(bool Value) { HasOverlappingBinding = Value; }
709651

710-
llvm_unreachable("Invalid resource class");
652+
hlsl::BindingInfo::BindingSpaces &getBindingSpaces(dxil::ResourceClass RC) {
653+
return Bindings.getBindingSpaces(RC);
711654
}
712655

713-
// Size == -1 means unbounded array
714656
LLVM_ABI std::optional<uint32_t>
715-
findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size);
657+
findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size) {
658+
return Bindings.findAvailableBinding(RC, Space, Size);
659+
}
716660

717661
friend class DXILResourceBindingAnalysis;
718662
friend class DXILResourceBindingWrapperPass;
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
//===- HLSLBinding.h - Representation for resource bindings in HLSL -------===//
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 objects to represent resource bindings.
10+
///
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_FRONTEND_HLSL_HLSLBINDING_H
14+
#define LLVM_FRONTEND_HLSL_HLSLBINDING_H
15+
16+
#include "llvm/ADT/STLFunctionalExtras.h"
17+
#include "llvm/ADT/SmallVector.h"
18+
#include "llvm/Support/DXILABI.h"
19+
#include "llvm/Support/ErrorHandling.h"
20+
21+
namespace llvm {
22+
namespace hlsl {
23+
24+
/// BindingInfo represents the ranges of bindings and free space for each
25+
/// `dxil::ResourceClass`. This can represent HLSL-level bindings as well as
26+
/// bindings described in root signatures, and can be used for analysis of
27+
/// overlapping or missing bindings as well as for finding space for implicit
28+
/// bindings.
29+
///
30+
/// As an example, given these resource bindings:
31+
///
32+
/// RWBuffer<float> A[10] : register(u3);
33+
/// RWBuffer<float> B[] : register(u5, space2)
34+
///
35+
/// The binding info for UAV bindings should look like this:
36+
///
37+
/// UAVSpaces {
38+
/// ResClass = ResourceClass::UAV,
39+
/// Spaces = {
40+
/// { Space = 0, FreeRanges = {{ 0, 2 }, { 13, UINT32_MAX }} },
41+
/// { Space = 2, FreeRanges = {{ 0, 4 }} }
42+
/// }
43+
/// }
44+
class BindingInfo {
45+
public:
46+
struct BindingRange {
47+
uint32_t LowerBound;
48+
uint32_t UpperBound;
49+
BindingRange(uint32_t LB, uint32_t UB) : LowerBound(LB), UpperBound(UB) {}
50+
};
51+
52+
struct RegisterSpace {
53+
uint32_t Space;
54+
SmallVector<BindingRange> FreeRanges;
55+
RegisterSpace(uint32_t Space) : Space(Space) {
56+
FreeRanges.emplace_back(0, UINT32_MAX);
57+
}
58+
// Size == -1 means unbounded array
59+
LLVM_ABI std::optional<uint32_t> findAvailableBinding(int32_t Size);
60+
};
61+
62+
struct BindingSpaces {
63+
dxil::ResourceClass RC;
64+
llvm::SmallVector<RegisterSpace> Spaces;
65+
BindingSpaces(dxil::ResourceClass RC) : RC(RC) {}
66+
LLVM_ABI RegisterSpace &getOrInsertSpace(uint32_t Space);
67+
};
68+
69+
private:
70+
BindingSpaces SRVSpaces{dxil::ResourceClass::SRV};
71+
BindingSpaces UAVSpaces{dxil::ResourceClass::UAV};
72+
BindingSpaces CBufferSpaces{dxil::ResourceClass::CBuffer};
73+
BindingSpaces SamplerSpaces{dxil::ResourceClass::Sampler};
74+
75+
public:
76+
BindingSpaces &getBindingSpaces(dxil::ResourceClass RC) {
77+
switch (RC) {
78+
case dxil::ResourceClass::SRV:
79+
return SRVSpaces;
80+
case dxil::ResourceClass::UAV:
81+
return UAVSpaces;
82+
case dxil::ResourceClass::CBuffer:
83+
return CBufferSpaces;
84+
case dxil::ResourceClass::Sampler:
85+
return SamplerSpaces;
86+
}
87+
88+
llvm_unreachable("Invalid resource class");
89+
}
90+
const BindingSpaces &getBindingSpaces(dxil::ResourceClass RC) const {
91+
return const_cast<BindingInfo *>(this)->getBindingSpaces(RC);
92+
}
93+
94+
// Size == -1 means unbounded array
95+
LLVM_ABI std::optional<uint32_t>
96+
findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size);
97+
98+
friend class BindingInfoBuilder;
99+
};
100+
101+
/// Builder class for creating a /c BindingInfo.
102+
class BindingInfoBuilder {
103+
public:
104+
struct Binding {
105+
dxil::ResourceClass RC;
106+
uint32_t Space;
107+
uint32_t LowerBound;
108+
uint32_t UpperBound;
109+
const void *Cookie;
110+
111+
Binding(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound,
112+
uint32_t UpperBound, const void *Cookie)
113+
: RC(RC), Space(Space), LowerBound(LowerBound), UpperBound(UpperBound),
114+
Cookie(Cookie) {}
115+
116+
bool isUnbounded() const { return UpperBound == ~0U; }
117+
118+
bool operator==(const Binding &RHS) const {
119+
return std::tie(RC, Space, LowerBound, UpperBound, Cookie) ==
120+
std::tie(RHS.RC, RHS.Space, RHS.LowerBound, RHS.UpperBound,
121+
RHS.Cookie);
122+
}
123+
bool operator!=(const Binding &RHS) const { return !(*this == RHS); }
124+
125+
bool operator<(const Binding &RHS) const {
126+
return std::tie(RC, Space, LowerBound) <
127+
std::tie(RHS.RC, RHS.Space, RHS.LowerBound);
128+
}
129+
};
130+
131+
private:
132+
SmallVector<Binding> Bindings;
133+
134+
public:
135+
void trackBinding(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound,
136+
uint32_t UpperBound, const void *Cookie) {
137+
Bindings.emplace_back(RC, Space, LowerBound, UpperBound, Cookie);
138+
}
139+
/// Calculate the binding info - \c ReportOverlap will be called once for each
140+
/// overlapping binding.
141+
BindingInfo calculateBindingInfo(
142+
llvm::function_ref<void(const BindingInfoBuilder &Builder,
143+
const Binding &Overlapping)>
144+
ReportOverlap);
145+
146+
/// Calculate the binding info - \c HasOverlap will be set to indicate whether
147+
/// there are any overlapping bindings.
148+
BindingInfo calculateBindingInfo(bool &HasOverlap) {
149+
HasOverlap = false;
150+
return calculateBindingInfo(
151+
[&HasOverlap](auto, auto) { HasOverlap = true; });
152+
}
153+
154+
/// For use in the \c ReportOverlap callback of \c calculateBindingInfo -
155+
/// finds a binding that the \c ReportedBinding overlaps with.
156+
const Binding &findOverlapping(const Binding &ReportedBinding) const;
157+
};
158+
159+
} // namespace hlsl
160+
} // namespace llvm
161+
162+
#endif // LLVM_FRONTEND_HLSL_HLSLBINDING_H

llvm/lib/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ add_llvm_component_library(LLVMAnalysis
175175
LINK_COMPONENTS
176176
BinaryFormat
177177
Core
178+
FrontendHLSL
178179
Object
179180
ProfileData
180181
Support

0 commit comments

Comments
 (0)