Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b1e34ff
adding validaiton and tests
Aug 12, 2025
90c2578
fix?
Aug 12, 2025
6e20bdf
Merge branch 'users/joaosaffran/153276' into validation/root-flags
joaosaffran Aug 12, 2025
84a4c4b
format
Aug 12, 2025
4400e2e
format
Aug 12, 2025
eb425c5
making validation function according to spec
Aug 14, 2025
ffcff83
merge
Aug 15, 2025
51ff280
format
Aug 15, 2025
e5812ce
clean up
Aug 15, 2025
d186ebd
clean up
Aug 15, 2025
5c35c32
clean up
Aug 15, 2025
9c09f21
Merge branch 'validation/descriptor-tables' into validation/root-flags
joaosaffran Sep 15, 2025
9169be0
formatting
joaosaffran Sep 15, 2025
65089ce
clean up
joaosaffran Sep 15, 2025
5910271
clean up
joaosaffran Sep 15, 2025
311a2e5
clean up
joaosaffran Sep 15, 2025
901bd1d
clean up
joaosaffran Sep 15, 2025
aba77f9
fix test
joaosaffran Sep 15, 2025
22319f9
rename test
joaosaffran Sep 15, 2025
4c86232
rename test
joaosaffran Sep 15, 2025
6641d66
rename test
joaosaffran Sep 15, 2025
c9986ed
refactoring follow inbelic suggestion
joaosaffran Sep 15, 2025
a0916e1
formating
joaosaffran Sep 15, 2025
1f8e5b6
adding getEnvironmentDenyFlagMask
joaosaffran Sep 15, 2025
1c2a864
format
joaosaffran Sep 15, 2025
8cccaf3
making getEnvironmentDenyFlagMask return optional
joaosaffran Sep 17, 2025
b3bc8b8
renaming SRVorUAV flag
joaosaffran Sep 17, 2025
18f9e9c
Merge branch 'validation/descriptor-tables' into validation/root-flags
joaosaffran Sep 18, 2025
83ee5fe
addressing comments from bogner
joaosaffran Sep 24, 2025
fdcd3e3
removing consts
joaosaffran Sep 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 62 additions & 3 deletions llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,18 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) {
}
}

static void reportIfDeniedShaderStageAccess(Module &M, dxbc::RootFlags Flags,
dxbc::RootFlags Mask) {
if ((Flags & Mask) != Mask)
return;
Comment on lines +166 to +167
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this check here, because I think it simplifies the code. If this is not here, I need to make the same check in all statements of the switch with slightly different masks.


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 void validateRootSignature(Module &M,
const mcdxbc::RootSignatureDesc &RSD,
dxil::ModuleMetadataInfo &MMI,
Expand Down Expand Up @@ -225,7 +237,9 @@ static void validateRootSignature(Module &M,
Builder.findOverlapping(ReportedBinding);
reportOverlappingRegisters(M, ReportedBinding, Overlaping);
});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is intentional, I think it improves readability.

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()];
Expand All @@ -240,18 +254,63 @@ static void validateRootSignature(Module &M,
const auto *ParamInfo =
static_cast<const mcdxbc::RootParameterInfo *>(Reg->Cookie);

if (RC != ResourceClass::SRV && RC != ResourceClass::UAV)
if (RC != ResourceClass::SRV && RC != ResourceClass::UAV) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CBV Resources are valid here, therefore, we need to set HasBindings

HasBindings = true;
continue;
}

if (ParamInfo->Type == dxbc::RootParameterType::DescriptorTable)
if (ParamInfo->Type == dxbc::RootParameterType::DescriptorTable) {
HasBindings = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SRV and UAV are valid here if bound to Descriptor Table

continue;
}

if (RK != ResourceKind::RawBuffer && RK != ResourceKind::StructuredBuffer)
if (RK != ResourceKind::RawBuffer &&
RK != ResourceKind::StructuredBuffer) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatter trigger that, since it gets linger than 80 columns

reportInvalidHandleTyError(M, RC, Binding);
continue;
}
HasBindings = true;

} else {
reportRegNotBound(M, RC, Binding);
}
}

if (HasBindings && MMI.ShaderProfile != Triple::Compute) {
dxbc::RootFlags Flags = dxbc::RootFlags(RSD.Flags);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it may be nicer if we define a separate function like getEnvironmentDenyFlag and then just invoked reportIfDeniedShaderStageAccess once. Might prevent a copy of this switch table appearing elsewhere

switch (MMI.ShaderProfile) {
case Triple::Pixel:
reportIfDeniedShaderStageAccess(
M, Flags, dxbc::RootFlags::DenyPixelShaderRootAccess);
break;
case Triple::Vertex:
reportIfDeniedShaderStageAccess(
M, Flags, dxbc::RootFlags::DenyVertexShaderRootAccess);
break;
case Triple::Geometry:
reportIfDeniedShaderStageAccess(
M, Flags, dxbc::RootFlags::DenyGeometryShaderRootAccess);
break;
case Triple::Hull:
reportIfDeniedShaderStageAccess(
M, Flags, dxbc::RootFlags::DenyHullShaderRootAccess);
break;
case Triple::Domain:
reportIfDeniedShaderStageAccess(
M, Flags, dxbc::RootFlags::DenyDomainShaderRootAccess);
break;
case Triple::Mesh:
reportIfDeniedShaderStageAccess(
M, Flags, dxbc::RootFlags::DenyMeshShaderRootAccess);
break;
case Triple::Amplification:
reportIfDeniedShaderStageAccess(
M, Flags, dxbc::RootFlags::DenyAmplificationShaderRootAccess);
break;
default:
llvm_unreachable("Invalid triple to shader stage conversion");
}
}
}

static mcdxbc::RootSignatureDesc *
Expand Down
Original file line number Diff line number Diff line change
@@ -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 }
21 changes: 21 additions & 0 deletions llvm/test/CodeGen/DirectX/rootsignature-validation-deny-shader.ll
Original file line number Diff line number Diff line change
@@ -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 }>

@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 }
Original file line number Diff line number Diff line change
@@ -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 }>

@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
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
; RUN: not opt -S -passes='dxil-post-optimization-validation' %s 2>&1 | FileCheck %s
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test checks an edge case, where root descriptors can be bound with non textures, but if they are denied, it should fail


; 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"

@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
Original file line number Diff line number Diff line change
@@ -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"

@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
Loading