Skip to content

Commit 0b8a997

Browse files
committed
Merge branch 'validation/check-descriptors-are-bound' into validation/textures-not-bind-root-signatures
2 parents fe24637 + 11b9fb2 commit 0b8a997

9 files changed

+74
-55
lines changed

llvm/include/llvm/Frontend/HLSL/HLSLBinding.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,16 @@ class BindingInfo {
5858
}
5959
// Size == -1 means unbounded array
6060
LLVM_ABI std::optional<uint32_t> findAvailableBinding(int32_t Size);
61-
LLVM_ABI bool isBound(BindingRange B);
61+
LLVM_ABI bool isBound(const BindingRange &Range) const;
6262
};
6363

6464
struct BindingSpaces {
6565
dxil::ResourceClass RC;
6666
llvm::SmallVector<RegisterSpace> Spaces;
6767
BindingSpaces(dxil::ResourceClass RC) : RC(RC) {}
6868
LLVM_ABI RegisterSpace &getOrInsertSpace(uint32_t Space);
69+
LLVM_ABI std::optional<const BindingInfo::RegisterSpace *>
70+
contains(uint32_t Space) const;
6971
};
7072

7173
private:
@@ -97,7 +99,8 @@ class BindingInfo {
9799
LLVM_ABI std::optional<uint32_t>
98100
findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size);
99101

100-
LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space, BindingRange B);
102+
LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space,
103+
const BindingRange &Range) const;
101104

102105
friend class BindingInfoBuilder;
103106
};

llvm/lib/Frontend/HLSL/HLSLBinding.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "llvm/Frontend/HLSL/HLSLBinding.h"
1010
#include "llvm/ADT/STLExtras.h"
11+
#include "llvm/Support/Error.h"
12+
#include <optional>
1113

1214
using namespace llvm;
1315
using namespace hlsl;
@@ -32,6 +34,18 @@ BindingInfo::BindingSpaces::getOrInsertSpace(uint32_t Space) {
3234
return Spaces.emplace_back(Space);
3335
}
3436

37+
std::optional<const BindingInfo::RegisterSpace *>
38+
BindingInfo::BindingSpaces::contains(uint32_t Space) const {
39+
const BindingInfo::RegisterSpace *It = Spaces.begin();
40+
for (auto *End = Spaces.end(); It != End; ++It) {
41+
if (It->Space == Space)
42+
break;
43+
}
44+
if (It == Spaces.end())
45+
return std::nullopt;
46+
return It;
47+
}
48+
3549
std::optional<uint32_t>
3650
BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) {
3751
assert((Size == -1 || Size > 0) && "invalid size");
@@ -66,24 +80,27 @@ BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) {
6680
return std::nullopt;
6781
}
6882

69-
bool BindingInfo::RegisterSpace::isBound(BindingRange B) {
70-
BindingRange *It = llvm::lower_bound(
71-
FreeRanges, B.LowerBound,
83+
bool BindingInfo::RegisterSpace::isBound(const BindingRange &Range) const {
84+
const BindingRange *It = llvm::lower_bound(
85+
FreeRanges, Range.LowerBound,
7286
[](const BindingRange &R, uint32_t Val) { return R.UpperBound <= Val; });
7387

7488
if (It != FreeRanges.end()) {
7589
// Check if B is fully contained in the found range
76-
if (B.LowerBound >= It->LowerBound && B.UpperBound <= It->UpperBound)
90+
if (Range.LowerBound >= It->LowerBound &&
91+
Range.UpperBound <= It->UpperBound)
7792
return false;
7893
}
7994
return true;
8095
}
8196

8297
bool BindingInfo::isBound(dxil::ResourceClass RC, uint32_t Space,
83-
BindingRange B) {
84-
BindingSpaces &BS = getBindingSpaces(RC);
85-
RegisterSpace &RS = BS.getOrInsertSpace(Space);
86-
return RS.isBound(B);
98+
const BindingRange &Range) const {
99+
const BindingSpaces &BS = getBindingSpaces(RC);
100+
std::optional<const BindingInfo::RegisterSpace *> RS = BS.contains(Space);
101+
if (!RS)
102+
return false;
103+
return RS.value()->isBound(Range);
87104
}
88105

89106
BindingInfo BindingInfoBuilder::calculateBindingInfo(

llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,8 @@ static void reportInvalidHandleTyError(Module &M, Twine Type,
122122
ResourceInfo::ResourceBinding Binding) {
123123
SmallString<128> Message;
124124
raw_svector_ostream OS(Message);
125-
OS << "resource " << Type << " at register (space=" << Binding.Space
126-
<< ", register=" << Binding.LowerBound << ")"
127-
<< " is bound to a texture or typed buffer.";
125+
OS << Type << " at register " << Binding.LowerBound << " and space "
126+
<< Binding.Space << " is bound to a texture or typed buffer.";
128127
M.getContext().diagnose(DiagnosticInfoGeneric(Message));
129128
}
130129

@@ -145,31 +144,24 @@ reportOverlappingRegisters(Module &M,
145144

146145
static void
147146
reportRegNotBound(Module &M, ResourceClass Class,
148-
llvm::dxil::ResourceInfo::ResourceBinding Unbound) {
147+
const llvm::dxil::ResourceInfo::ResourceBinding &Unbound) {
149148
SmallString<128> Message;
150149
raw_svector_ostream OS(Message);
151-
OS << "register " << getResourceClassName(Class)
152-
<< " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound
153-
<< ")"
150+
OS << getResourceClassName(Class) << " register " << Unbound.LowerBound
151+
<< " in space " << Unbound.Space
154152
<< " does not have a binding in the Root Signature";
155153
M.getContext().diagnose(DiagnosticInfoGeneric(Message));
156154
}
157155

158156
static void checkInvalidHandleTy(
159157
Module &M, const llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding> &RDs,
160-
const iterator_range<SmallVectorImpl<dxil::ResourceInfo>::iterator>
161-
&Resources) {
162-
for (auto Res = Resources.begin(), End = Resources.end(); Res != End; Res++) {
163-
llvm::dxil::ResourceInfo::ResourceBinding Binding = Res->getBinding();
164-
for (const auto &RD : RDs) {
165-
if (Binding.overlapsWith(RD)) {
166-
TargetExtType *Handle = Res->getHandleTy();
167-
auto *TypedBuffer = dyn_cast_or_null<TypedBufferExtType>(Handle);
168-
auto *Texture = dyn_cast_or_null<TextureExtType>(Handle);
169-
170-
if (TypedBuffer != nullptr || Texture != nullptr)
171-
reportInvalidHandleTyError(M, Res->getName(), Res->getBinding());
172-
}
158+
const llvm::dxil::ResourceInfo::ResourceBinding &Binding,
159+
const ResourceKind &Kind, const dxil::ResourceClass &RC) {
160+
for (const auto &RD : RDs) {
161+
if (Binding.overlapsWith(RD)) {
162+
163+
if (Kind != ResourceKind::RawBuffer)
164+
reportInvalidHandleTyError(M, getResourceClassName(RC), Binding);
173165
}
174166
}
175167
}
@@ -239,7 +231,8 @@ getRootDescriptorsBindingInfo(const mcdxbc::RootSignatureDesc &RSD,
239231
static void validateRootSignature(Module &M,
240232
const mcdxbc::RootSignatureDesc &RSD,
241233
dxil::ModuleMetadataInfo &MMI,
242-
DXILResourceMap &DRM) {
234+
DXILResourceMap &DRM,
235+
DXILResourceTypeMap &DRTM) {
243236

244237
hlsl::BindingInfoBuilder Builder;
245238
dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile);
@@ -305,22 +298,20 @@ static void validateRootSignature(Module &M,
305298
Builder.findOverlapping(ReportedBinding);
306299
reportOverlappingRegisters(M, ReportedBinding, Overlaping);
307300
});
301+
308302
SmallVector<ResourceInfo::ResourceBinding> RDs =
309303
getRootDescriptorsBindingInfo(RSD, Visibility);
310-
for (const auto &ResList :
311-
{std::make_pair(ResourceClass::SRV, DRM.srvs()),
312-
std::make_pair(ResourceClass::UAV, DRM.uavs()),
313-
std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()),
314-
std::make_pair(ResourceClass::Sampler, DRM.samplers())}) {
315-
for (auto Res : ResList.second) {
316-
llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding();
317-
llvm::hlsl::BindingInfo::BindingRange ResRange(
318-
ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size);
319-
320-
if (!Info.isBound(ResList.first, ResBinding.Space, ResRange))
321-
reportRegNotBound(M, ResList.first, ResBinding);
322-
}
323-
checkInvalidHandleTy(M, RDs, ResList.second);
304+
305+
for (const ResourceInfo &RI : DRM) {
306+
const ResourceInfo::ResourceBinding &Binding = RI.getBinding();
307+
dxil::ResourceTypeInfo RTI = DRTM[RI.getHandleTy()];
308+
dxil::ResourceClass RC = RTI.getResourceClass();
309+
310+
if (!Info.isBound(RC, Binding.Space,
311+
{Binding.LowerBound, Binding.LowerBound + Binding.Size}))
312+
reportRegNotBound(M, RC, Binding);
313+
314+
checkInvalidHandleTy(M, RDs, Binding, RTI.getResourceKind(), RC);
324315
}
325316
}
326317

@@ -335,7 +326,8 @@ getRootSignature(RootSignatureBindingInfo &RSBI,
335326
static void reportErrors(Module &M, DXILResourceMap &DRM,
336327
DXILResourceBindingInfo &DRBI,
337328
RootSignatureBindingInfo &RSBI,
338-
dxil::ModuleMetadataInfo &MMI) {
329+
dxil::ModuleMetadataInfo &MMI,
330+
DXILResourceTypeMap &DRTM) {
339331
if (DRM.hasInvalidCounterDirection())
340332
reportInvalidDirection(M, DRM);
341333

@@ -346,7 +338,7 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
346338
"DXILResourceImplicitBinding pass");
347339

348340
if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI))
349-
validateRootSignature(M, *RSD, MMI, DRM);
341+
validateRootSignature(M, *RSD, MMI, DRM, DRTM);
350342
}
351343

352344
PreservedAnalyses
@@ -355,8 +347,9 @@ DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
355347
DXILResourceBindingInfo &DRBI = MAM.getResult<DXILResourceBindingAnalysis>(M);
356348
RootSignatureBindingInfo &RSBI = MAM.getResult<RootSignatureAnalysis>(M);
357349
ModuleMetadataInfo &MMI = MAM.getResult<DXILMetadataAnalysis>(M);
350+
DXILResourceTypeMap &DRTM = MAM.getResult<DXILResourceTypeAnalysis>(M);
358351

359-
reportErrors(M, DRM, DRBI, RSBI, MMI);
352+
reportErrors(M, DRM, DRBI, RSBI, MMI, DRTM);
360353
return PreservedAnalyses::all();
361354
}
362355

@@ -372,8 +365,10 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
372365
getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
373366
dxil::ModuleMetadataInfo &MMI =
374367
getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
368+
DXILResourceTypeMap &DRTM =
369+
getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
375370

376-
reportErrors(M, DRM, DRBI, RSBI, MMI);
371+
reportErrors(M, DRM, DRBI, RSBI, MMI, DRTM);
377372
return false;
378373
}
379374
StringRef getPassName() const override {
@@ -383,15 +378,18 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
383378

384379
static char ID; // Pass identification.
385380
void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
381+
386382
AU.addRequired<DXILResourceWrapperPass>();
387383
AU.addRequired<DXILResourceBindingWrapperPass>();
388384
AU.addRequired<DXILMetadataAnalysisWrapperPass>();
389385
AU.addRequired<RootSignatureAnalysisWrapper>();
386+
AU.addRequired<DXILResourceTypeWrapperPass>();
390387
AU.addPreserved<DXILResourceWrapperPass>();
391388
AU.addPreserved<DXILResourceBindingWrapperPass>();
392389
AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
393390
AU.addPreserved<ShaderFlagsAnalysisWrapper>();
394391
AU.addPreserved<RootSignatureAnalysisWrapper>();
392+
AU.addPreserved<DXILResourceTypeWrapperPass>();
395393
}
396394
};
397395
char DXILPostOptimizationValidationLegacy::ID = 0;
@@ -404,6 +402,7 @@ INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
404402
INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
405403
INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass)
406404
INITIALIZE_PASS_DEPENDENCY(RootSignatureAnalysisWrapper)
405+
INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
407406
INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
408407
"DXIL Post Optimization Validation", false, false)
409408

llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbv-binding.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
2-
; CHECK: error: register CBV (space=666, register=2) does not have a binding in the Root Signature
2+
; CHECK: error: CBV register 2 in space 666 does not have a binding in the Root Signature
33

44
%__cblayout_CB = type <{ float }>
55

llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-binding.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
2-
; CHECK: error: register Sampler (space=2, register=3) does not have a binding in the Root Signature
2+
; CHECK: error: Sampler register 3 in space 2 does not have a binding in the Root Signature
33

44
@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1
55

llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv-binding.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
2-
; CHECK: error: register SRV (space=0, register=0) does not have a binding in the Root Signature
2+
; CHECK: error: SRV register 0 in space 0 does not have a binding in the Root Signature
33

44
@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1
55

llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav-binding.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
2-
; CHECK: error: register UAV (space=0, register=4294967294) does not have a binding in the Root Signature
2+
; CHECK: error: UAV register 4294967294 in space 0 does not have a binding in the Root Signature
33

44
@RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1
55

llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
2-
; CHECK: error: resource TB at register (space=0, register=0) is bound to a texture or typed buffer.
2+
; CHECK: error: UAV at register 0 and space 0 is bound to a texture or typed buffer.
33

44
@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
55

llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
2-
; CHECK: error: resource TB at register (space=0, register=0) is bound to a texture or typed buffer.
2+
; CHECK: error: UAV at register 0 and space 0 is bound to a texture or typed buffer.
33

44
@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
55

0 commit comments

Comments
 (0)