Skip to content

Commit 9179d3f

Browse files
joaosaffranjoaosaffranJoao Saffranjoaosaffran-zz
authored
[DirectX] Validate if Textures/TypedBuffers are being bound in Root Signatures (#147573)
DXC doesn't allow Textures/TypedBuffers to bind with root signature descriptors, this implements the same check. Closes: #126647 --------- Co-authored-by: joaosaffran <[email protected]> Co-authored-by: Joao Saffran <{ID}+{username}@users.noreply.github.com> Co-authored-by: Joao Saffran <[email protected]>
1 parent f869d7a commit 9179d3f

File tree

6 files changed

+106
-8
lines changed

6 files changed

+106
-8
lines changed

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,17 +133,19 @@ class BoundRegs {
133133
public:
134134
BoundRegs(SmallVector<Binding> &&Bindings) : Bindings(std::move(Bindings)) {}
135135

136-
bool isBound(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound,
137-
uint32_t UpperBound) const {
136+
const Binding *findBoundReg(dxil::ResourceClass RC, uint32_t Space,
137+
uint32_t LowerBound, uint32_t UpperBound) const {
138138
// UpperBound and Cookie are given dummy values, since they aren't
139139
// interesting for operator<
140140
const Binding *It =
141141
llvm::upper_bound(Bindings, Binding{RC, Space, LowerBound, 0, nullptr});
142142
if (It == Bindings.begin())
143-
return false;
143+
return nullptr;
144144
--It;
145-
return It->RC == RC && It->Space == Space && It->LowerBound <= LowerBound &&
146-
It->UpperBound >= UpperBound;
145+
if (It->RC == RC && It->Space == Space && It->LowerBound <= LowerBound &&
146+
It->UpperBound >= UpperBound)
147+
return It;
148+
return nullptr;
147149
}
148150
};
149151

llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,17 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
103103
"true, yet no overlapping binding was found");
104104
}
105105

106+
static void reportInvalidHandleTyError(Module &M, ResourceClass RC,
107+
ResourceInfo::ResourceBinding Binding) {
108+
SmallString<160> Message;
109+
raw_svector_ostream OS(Message);
110+
StringRef RCName = getResourceClassName(RC);
111+
OS << RCName << " at register " << Binding.LowerBound << " and space "
112+
<< Binding.Space << " is bound to a texture or typed buffer. " << RCName
113+
<< " root descriptors can only be Raw or Structured buffers.";
114+
M.getContext().diagnose(DiagnosticInfoGeneric(Message));
115+
}
116+
106117
static void reportOverlappingRegisters(Module &M, const llvm::hlsl::Binding &R1,
107118
const llvm::hlsl::Binding &R2) {
108119
SmallString<128> Message;
@@ -217,10 +228,29 @@ static void validateRootSignature(Module &M,
217228
const hlsl::BoundRegs &BoundRegs = Builder.takeBoundRegs();
218229
for (const ResourceInfo &RI : DRM) {
219230
const ResourceInfo::ResourceBinding &Binding = RI.getBinding();
220-
ResourceClass RC = DRTM[RI.getHandleTy()].getResourceClass();
221-
if (!BoundRegs.isBound(RC, Binding.Space, Binding.LowerBound,
222-
Binding.LowerBound + Binding.Size - 1))
231+
const dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
232+
dxil::ResourceClass RC = RTI.getResourceClass();
233+
dxil::ResourceKind RK = RTI.getResourceKind();
234+
235+
const llvm::hlsl::Binding *Reg =
236+
BoundRegs.findBoundReg(RC, Binding.Space, Binding.LowerBound,
237+
Binding.LowerBound + Binding.Size - 1);
238+
239+
if (Reg != nullptr) {
240+
const auto *ParamInfo =
241+
static_cast<const mcdxbc::RootParameterInfo *>(Reg->Cookie);
242+
243+
if (RC != ResourceClass::SRV && RC != ResourceClass::UAV)
244+
continue;
245+
246+
if (ParamInfo->Type == dxbc::RootParameterType::DescriptorTable)
247+
continue;
248+
249+
if (RK != ResourceKind::RawBuffer && RK != ResourceKind::StructuredBuffer)
250+
reportInvalidHandleTyError(M, RC, Binding);
251+
} else {
223252
reportRegNotBound(M, RC, Binding);
253+
}
224254
}
225255
}
226256

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s
2+
; "This is a valid root signature with a texture/typed buffer resource"
3+
4+
@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
5+
6+
define void @CSMain() "hlsl.shader"="compute" {
7+
entry:
8+
%TB = tail call target("dx.Texture", <4 x float>, 1, 0, 0, 4) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str)
9+
ret void
10+
}
11+
12+
!dx.rootsignatures = !{!0}
13+
14+
!0 = !{ptr @CSMain, !1, i32 2}
15+
!1 = !{!3}
16+
!3 = !{!"DescriptorTable", i32 0, !4}
17+
!4 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1
2+
; This is a valid root signature with a texture/typed buffer resource
3+
4+
@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
5+
6+
define void @CSMain() "hlsl.shader"="compute" {
7+
entry:
8+
%TB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str)
9+
ret void
10+
}
11+
12+
!dx.rootsignatures = !{!0}
13+
14+
!0 = !{ptr @CSMain, !1, i32 2}
15+
!1 = !{!3}
16+
!3 = !{!"DescriptorTable", i32 0, !4}
17+
!4 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
2+
; CHECK: error: UAV at register 0 and space 0 is bound to a texture or typed buffer.
3+
4+
@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
5+
6+
define void @CSMain() "hlsl.shader"="compute" {
7+
entry:
8+
%TB = tail call target("dx.Texture", float, 1, 0, 0, 4) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str)
9+
ret void
10+
}
11+
12+
!dx.rootsignatures = !{!0}
13+
14+
!0 = !{ptr @CSMain, !1, i32 2}
15+
!1 = !{!2}
16+
!2 = !{!"RootUAV", i32 0, i32 0, i32 0, i32 4}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
2+
; CHECK: error: UAV at register 0 and space 0 is bound to a texture or typed buffer.
3+
4+
@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
5+
6+
define void @CSMain() "hlsl.shader"="compute" {
7+
entry:
8+
%TB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str)
9+
ret void
10+
}
11+
12+
!dx.rootsignatures = !{!0}
13+
14+
!0 = !{ptr @CSMain, !1, i32 2}
15+
!1 = !{!2}
16+
!2 = !{!"RootUAV", i32 0, i32 0, i32 0, i32 4}

0 commit comments

Comments
 (0)