Skip to content

Commit 542e7d6

Browse files
joaosaffranjoaosaffranJoao Saffranjoaosaffran-zz
authored andcommitted
Automerge: [DirectX] Validating Root flags are denying shader stage (#160919)
Root Signature Flags, allow flags to block compilation of certain shader stages. This PR implements a validation and notify the user if they compile a root signature that is denying such shader stage. Closes: llvm/llvm-project#153062 Previously approved: llvm/llvm-project#153287 --------- Co-authored-by: joaosaffran <[email protected]> Co-authored-by: Joao Saffran <{ID}+{username}@users.noreply.github.com> Co-authored-by: Joao Saffran <[email protected]>
2 parents d234955 + e28a559 commit 542e7d6

6 files changed

+157
-12
lines changed

llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,41 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) {
160160
}
161161
}
162162

163+
static void reportIfDeniedShaderStageAccess(Module &M,
164+
const dxbc::RootFlags &Flags,
165+
const dxbc::RootFlags &Mask) {
166+
if ((Flags & Mask) != Mask)
167+
return;
168+
169+
SmallString<128> Message;
170+
raw_svector_ostream OS(Message);
171+
OS << "Shader has root bindings but root signature uses a DENY flag to "
172+
"disallow root binding access to the shader stage.";
173+
M.getContext().diagnose(DiagnosticInfoGeneric(Message));
174+
}
175+
176+
static std::optional<dxbc::RootFlags>
177+
getEnvironmentDenyFlagMask(Triple::EnvironmentType ShaderProfile) {
178+
switch (ShaderProfile) {
179+
case Triple::Pixel:
180+
return dxbc::RootFlags::DenyPixelShaderRootAccess;
181+
case Triple::Vertex:
182+
return dxbc::RootFlags::DenyVertexShaderRootAccess;
183+
case Triple::Geometry:
184+
return dxbc::RootFlags::DenyGeometryShaderRootAccess;
185+
case Triple::Hull:
186+
return dxbc::RootFlags::DenyHullShaderRootAccess;
187+
case Triple::Domain:
188+
return dxbc::RootFlags::DenyDomainShaderRootAccess;
189+
case Triple::Mesh:
190+
return dxbc::RootFlags::DenyMeshShaderRootAccess;
191+
case Triple::Amplification:
192+
return dxbc::RootFlags::DenyAmplificationShaderRootAccess;
193+
default:
194+
return std::nullopt;
195+
}
196+
}
197+
163198
static void validateRootSignature(Module &M,
164199
const mcdxbc::RootSignatureDesc &RSD,
165200
dxil::ModuleMetadataInfo &MMI,
@@ -225,7 +260,9 @@ static void validateRootSignature(Module &M,
225260
Builder.findOverlapping(ReportedBinding);
226261
reportOverlappingRegisters(M, ReportedBinding, Overlaping);
227262
});
263+
228264
const hlsl::BoundRegs &BoundRegs = Builder.takeBoundRegs();
265+
bool HasBindings = false;
229266
for (const ResourceInfo &RI : DRM) {
230267
const ResourceInfo::ResourceBinding &Binding = RI.getBinding();
231268
const dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
@@ -236,22 +273,33 @@ static void validateRootSignature(Module &M,
236273
BoundRegs.findBoundReg(RC, Binding.Space, Binding.LowerBound,
237274
Binding.LowerBound + Binding.Size - 1);
238275

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;
276+
if (!Reg) {
277+
reportRegNotBound(M, RC, Binding);
278+
continue;
279+
}
245280

246-
if (ParamInfo->Type == dxbc::RootParameterType::DescriptorTable)
247-
continue;
281+
const auto *ParamInfo =
282+
static_cast<const mcdxbc::RootParameterInfo *>(Reg->Cookie);
248283

249-
if (RK != ResourceKind::RawBuffer && RK != ResourceKind::StructuredBuffer)
250-
reportInvalidHandleTyError(M, RC, Binding);
251-
} else {
252-
reportRegNotBound(M, RC, Binding);
284+
bool IsSRVOrUAV = RC == ResourceClass::SRV || RC == ResourceClass::UAV;
285+
bool IsDescriptorTable =
286+
ParamInfo->Type == dxbc::RootParameterType::DescriptorTable;
287+
bool IsRawOrStructuredBuffer =
288+
RK != ResourceKind::RawBuffer && RK != ResourceKind::StructuredBuffer;
289+
if (IsSRVOrUAV && !IsDescriptorTable && IsRawOrStructuredBuffer) {
290+
reportInvalidHandleTyError(M, RC, Binding);
291+
continue;
253292
}
293+
294+
HasBindings = true;
254295
}
296+
297+
if (!HasBindings)
298+
return;
299+
300+
if (std::optional<dxbc::RootFlags> Mask =
301+
getEnvironmentDenyFlagMask(MMI.ShaderProfile))
302+
reportIfDeniedShaderStageAccess(M, dxbc::RootFlags(RSD.Flags), *Mask);
255303
}
256304

257305
static mcdxbc::RootSignatureDesc *
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' %s
2+
; This is a valid case where no resource is being used
3+
target triple = "dxil-pc-shadermodel6.6-pixel"
4+
5+
define void @CSMain() #0 {
6+
entry:
7+
ret void
8+
}
9+
attributes #0 = { noinline nounwind "exp-shader"="cs" "hlsl.numthreads"="1,2,1" "hlsl.shader"="geometry" }
10+
11+
!dx.rootsignatures = !{!0}
12+
13+
!0 = !{ptr @CSMain, !1, i32 2}
14+
!1 = !{!2, !3, !4}
15+
!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
16+
!3 = !{ !"RootFlags", i32 294 } ; 294 = deny_pixel/hull/vertex/amplification_shader_root_access
17+
!4 = !{ !"RootSRV", i32 0, i32 1, i32 0, i32 0 }
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: not opt -S -passes='dxil-post-optimization-validation' %s 2>&1 | FileCheck %s
2+
; CHECK: error: Shader has root bindings but root signature uses a DENY flag to disallow root binding access to the shader stage.
3+
target triple = "dxil-pc-shadermodel6.6-pixel"
4+
5+
%__cblayout_CB = type <{ float }>
6+
7+
@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
8+
9+
define void @CSMain() "hlsl.shader"="compute" {
10+
entry:
11+
%CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 0, i32 2, i32 1, i32 0, ptr nonnull @CB.str)
12+
ret void
13+
}
14+
15+
!dx.rootsignatures = !{!0}
16+
17+
!0 = !{ptr @CSMain, !1, i32 2}
18+
!1 = !{!2, !3}
19+
!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
20+
!3 = !{!"RootFlags", i32 294} ; 294 = deny_pixel/hull/vertex/amplification_shader_root_access
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: not opt -S -passes='dxil-post-optimization-validation' %s 2>&1 | FileCheck %s
2+
3+
; CHECK: error: Shader has root bindings but root signature uses a DENY flag to disallow root binding access to the shader stage.
4+
target triple = "dxil-pc-shadermodel6.6-pixel"
5+
6+
@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1
7+
8+
define void @CSMain() "hlsl.shader"="pixel" {
9+
entry:
10+
%SB = tail call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @SB.str)
11+
ret void
12+
}
13+
14+
!dx.rootsignatures = !{!0}
15+
16+
!0 = !{ptr @CSMain, !1, i32 2}
17+
!1 = !{!2, !3}
18+
!2 = !{!"DescriptorTable", i32 0, !4}
19+
!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
20+
!3 = !{!"RootFlags", i32 32} ; 32 = deny_pixel_shader_root_access
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
; RUN: not opt -S -passes='dxil-post-optimization-validation' %s 2>&1 | FileCheck %s
2+
3+
; CHECK: error: Shader has root bindings but root signature uses a DENY flag to disallow root binding access to the shader stage.
4+
target triple = "dxil-pc-shadermodel6.6-pixel"
5+
6+
@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1
7+
8+
define void @CSMain() "hlsl.shader"="pixel" {
9+
entry:
10+
%SB = tail call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @SB.str)
11+
ret void
12+
}
13+
14+
!dx.rootsignatures = !{!0}
15+
16+
!0 = !{ptr @CSMain, !1, i32 2}
17+
!1 = !{!2, !3}
18+
!2 = !{!"RootSRV", i32 0, i32 0, i32 0, i32 4}
19+
!3 = !{!"RootFlags", i32 32} ; 32 = deny_pixel_shader_root_access
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; RUN: opt -S -passes='dxil-post-optimization-validation' %s
2+
; Valid scenario where shader stage is not blocked from accessing root bindings
3+
target triple = "dxil-pc-shadermodel6.6-geometry"
4+
5+
%__cblayout_CB = type <{ float }>
6+
7+
@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
8+
9+
define void @CSMain() "hlsl.shader"="geometry" {
10+
entry:
11+
%CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 0, i32 2, i32 1, i32 0, ptr nonnull @CB.str)
12+
ret void
13+
}
14+
attributes #0 = { noinline nounwind "exp-shader"="cs" "hlsl.numthreads"="1,2,1" "hlsl.shader"="geometry" }
15+
16+
!dx.rootsignatures = !{!0}
17+
18+
!0 = !{ptr @CSMain, !1, i32 2}
19+
!1 = !{!2, !3}
20+
!2 = !{ !"RootFlags", i32 294 } ; 294 = deny_pixel/hull/vertex/amplification_shader_root_access
21+
!3 = !{ !"RootCBV", i32 0, i32 2, i32 0, i32 0 }

0 commit comments

Comments
 (0)