[llvm] e28a559 - [DirectX] Validating Root flags are denying shader stage (#160919)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 26 10:44:02 PDT 2025
Author: joaosaffran
Date: 2025-09-26T13:43:58-04:00
New Revision: e28a5596966d586525e8719e5c58afc7cf48a5d9
URL: https://github.com/llvm/llvm-project/commit/e28a5596966d586525e8719e5c58afc7cf48a5d9
DIFF: https://github.com/llvm/llvm-project/commit/e28a5596966d586525e8719e5c58afc7cf48a5d9.diff
LOG: [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: https://github.com/llvm/llvm-project/issues/153062
Previously approved: https://github.com/llvm/llvm-project/pull/153287
---------
Co-authored-by: joaosaffran <joao.saffran at microsoft.com>
Co-authored-by: Joao Saffran <{ID}+{username}@users.noreply.github.com>
Co-authored-by: Joao Saffran <jderezende at microsoft.com>
Added:
llvm/test/CodeGen/DirectX/rootsignature-validation-deny-no-binding.ll
llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-multiple-shader.ll
llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-root-descriptor.ll
llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-single-shader.ll
llvm/test/CodeGen/DirectX/rootsignature-validation-not-dening-shader.ll
Modified:
llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 7e93474e73118..6e95a4232fabe 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -160,6 +160,41 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) {
}
}
+static void reportIfDeniedShaderStageAccess(Module &M,
+ const dxbc::RootFlags &Flags,
+ const dxbc::RootFlags &Mask) {
+ if ((Flags & Mask) != Mask)
+ return;
+
+ SmallString<128> Message;
+ raw_svector_ostream OS(Message);
+ OS << "Shader has root bindings but root signature uses a DENY flag to "
+ "disallow root binding access to the shader stage.";
+ M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+}
+
+static std::optional<dxbc::RootFlags>
+getEnvironmentDenyFlagMask(Triple::EnvironmentType ShaderProfile) {
+ switch (ShaderProfile) {
+ case Triple::Pixel:
+ return dxbc::RootFlags::DenyPixelShaderRootAccess;
+ case Triple::Vertex:
+ return dxbc::RootFlags::DenyVertexShaderRootAccess;
+ case Triple::Geometry:
+ return dxbc::RootFlags::DenyGeometryShaderRootAccess;
+ case Triple::Hull:
+ return dxbc::RootFlags::DenyHullShaderRootAccess;
+ case Triple::Domain:
+ return dxbc::RootFlags::DenyDomainShaderRootAccess;
+ case Triple::Mesh:
+ return dxbc::RootFlags::DenyMeshShaderRootAccess;
+ case Triple::Amplification:
+ return dxbc::RootFlags::DenyAmplificationShaderRootAccess;
+ default:
+ return std::nullopt;
+ }
+}
+
static void validateRootSignature(Module &M,
const mcdxbc::RootSignatureDesc &RSD,
dxil::ModuleMetadataInfo &MMI,
@@ -225,7 +260,9 @@ static void validateRootSignature(Module &M,
Builder.findOverlapping(ReportedBinding);
reportOverlappingRegisters(M, ReportedBinding, Overlaping);
});
+
const hlsl::BoundRegs &BoundRegs = Builder.takeBoundRegs();
+ bool HasBindings = false;
for (const ResourceInfo &RI : DRM) {
const ResourceInfo::ResourceBinding &Binding = RI.getBinding();
const dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
@@ -236,22 +273,33 @@ static void validateRootSignature(Module &M,
BoundRegs.findBoundReg(RC, Binding.Space, Binding.LowerBound,
Binding.LowerBound + Binding.Size - 1);
- if (Reg != nullptr) {
- const auto *ParamInfo =
- static_cast<const mcdxbc::RootParameterInfo *>(Reg->Cookie);
-
- if (RC != ResourceClass::SRV && RC != ResourceClass::UAV)
- continue;
+ if (!Reg) {
+ reportRegNotBound(M, RC, Binding);
+ continue;
+ }
- if (ParamInfo->Type == dxbc::RootParameterType::DescriptorTable)
- continue;
+ const auto *ParamInfo =
+ static_cast<const mcdxbc::RootParameterInfo *>(Reg->Cookie);
- if (RK != ResourceKind::RawBuffer && RK != ResourceKind::StructuredBuffer)
- reportInvalidHandleTyError(M, RC, Binding);
- } else {
- reportRegNotBound(M, RC, Binding);
+ bool IsSRVOrUAV = RC == ResourceClass::SRV || RC == ResourceClass::UAV;
+ bool IsDescriptorTable =
+ ParamInfo->Type == dxbc::RootParameterType::DescriptorTable;
+ bool IsRawOrStructuredBuffer =
+ RK != ResourceKind::RawBuffer && RK != ResourceKind::StructuredBuffer;
+ if (IsSRVOrUAV && !IsDescriptorTable && IsRawOrStructuredBuffer) {
+ reportInvalidHandleTyError(M, RC, Binding);
+ continue;
}
+
+ HasBindings = true;
}
+
+ if (!HasBindings)
+ return;
+
+ if (std::optional<dxbc::RootFlags> Mask =
+ getEnvironmentDenyFlagMask(MMI.ShaderProfile))
+ reportIfDeniedShaderStageAccess(M, dxbc::RootFlags(RSD.Flags), *Mask);
}
static mcdxbc::RootSignatureDesc *
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-deny-no-binding.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-deny-no-binding.ll
new file mode 100644
index 0000000000000..15326d438f021
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-deny-no-binding.ll
@@ -0,0 +1,17 @@
+; RUN: opt -S -passes='dxil-post-optimization-validation' %s
+; This is a valid case where no resource is being used
+target triple = "dxil-pc-shadermodel6.6-pixel"
+
+define void @CSMain() #0 {
+entry:
+ ret void
+}
+attributes #0 = { noinline nounwind "exp-shader"="cs" "hlsl.numthreads"="1,2,1" "hlsl.shader"="geometry" }
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3, !4}
+!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
+!3 = !{ !"RootFlags", i32 294 } ; 294 = deny_pixel/hull/vertex/amplification_shader_root_access
+!4 = !{ !"RootSRV", i32 0, i32 1, i32 0, i32 0 }
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-multiple-shader.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-multiple-shader.ll
new file mode 100644
index 0000000000000..b11cce694bd25
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-multiple-shader.ll
@@ -0,0 +1,20 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' %s 2>&1 | FileCheck %s
+; CHECK: error: Shader has root bindings but root signature uses a DENY flag to disallow root binding access to the shader stage.
+target triple = "dxil-pc-shadermodel6.6-pixel"
+
+%__cblayout_CB = type <{ float }>
+
+ at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+ %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)
+ ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3}
+!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
+!3 = !{!"RootFlags", i32 294} ; 294 = deny_pixel/hull/vertex/amplification_shader_root_access
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-root-descriptor.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-root-descriptor.ll
new file mode 100644
index 0000000000000..6d323757d5897
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-root-descriptor.ll
@@ -0,0 +1,20 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' %s 2>&1 | FileCheck %s
+
+; CHECK: error: Shader has root bindings but root signature uses a DENY flag to disallow root binding access to the shader stage.
+target triple = "dxil-pc-shadermodel6.6-pixel"
+
+ at SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1
+
+define void @CSMain() "hlsl.shader"="pixel" {
+entry:
+ %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)
+ ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3}
+!2 = !{!"DescriptorTable", i32 0, !4}
+!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4}
+!3 = !{!"RootFlags", i32 32} ; 32 = deny_pixel_shader_root_access
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-single-shader.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-single-shader.ll
new file mode 100644
index 0000000000000..4e50f50049b0e
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-deny-single-shader.ll
@@ -0,0 +1,19 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' %s 2>&1 | FileCheck %s
+
+; CHECK: error: Shader has root bindings but root signature uses a DENY flag to disallow root binding access to the shader stage.
+target triple = "dxil-pc-shadermodel6.6-pixel"
+
+ at SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1
+
+define void @CSMain() "hlsl.shader"="pixel" {
+entry:
+ %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)
+ ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3}
+!2 = !{!"RootSRV", i32 0, i32 0, i32 0, i32 4}
+!3 = !{!"RootFlags", i32 32} ; 32 = deny_pixel_shader_root_access
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-not-dening-shader.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-not-dening-shader.ll
new file mode 100644
index 0000000000000..775fc3512ca84
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-not-dening-shader.ll
@@ -0,0 +1,21 @@
+; RUN: opt -S -passes='dxil-post-optimization-validation' %s
+; Valid scenario where shader stage is not blocked from accessing root bindings
+target triple = "dxil-pc-shadermodel6.6-geometry"
+
+%__cblayout_CB = type <{ float }>
+
+ at CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1
+
+define void @CSMain() "hlsl.shader"="geometry" {
+entry:
+ %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)
+ ret void
+}
+attributes #0 = { noinline nounwind "exp-shader"="cs" "hlsl.numthreads"="1,2,1" "hlsl.shader"="geometry" }
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3}
+!2 = !{ !"RootFlags", i32 294 } ; 294 = deny_pixel/hull/vertex/amplification_shader_root_access
+!3 = !{ !"RootCBV", i32 0, i32 2, i32 0, i32 0 }
More information about the llvm-commits
mailing list