[llvm] 9179d3f - [DirectX] Validate if Textures/TypedBuffers are being bound in Root Signatures (#147573)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 10 16:49:38 PDT 2025
Author: joaosaffran
Date: 2025-09-10T19:49:34-04:00
New Revision: 9179d3f19e32630dd54efd8a41cb57737b5ec4f3
URL: https://github.com/llvm/llvm-project/commit/9179d3f19e32630dd54efd8a41cb57737b5ec4f3
DIFF: https://github.com/llvm/llvm-project/commit/9179d3f19e32630dd54efd8a41cb57737b5ec4f3.diff
LOG: [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 <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-valid-textures.ll
llvm/test/CodeGen/DirectX/rootsignature-valid-typedbuffer.ll
llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll
llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll
Modified:
llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
index 5e0175a58e0fb..8afa7687a17c6 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h
@@ -133,17 +133,19 @@ class BoundRegs {
public:
BoundRegs(SmallVector<Binding> &&Bindings) : Bindings(std::move(Bindings)) {}
- bool isBound(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound,
- uint32_t UpperBound) const {
+ const Binding *findBoundReg(dxil::ResourceClass RC, uint32_t Space,
+ uint32_t LowerBound, uint32_t UpperBound) const {
// UpperBound and Cookie are given dummy values, since they aren't
// interesting for operator<
const Binding *It =
llvm::upper_bound(Bindings, Binding{RC, Space, LowerBound, 0, nullptr});
if (It == Bindings.begin())
- return false;
+ return nullptr;
--It;
- return It->RC == RC && It->Space == Space && It->LowerBound <= LowerBound &&
- It->UpperBound >= UpperBound;
+ if (It->RC == RC && It->Space == Space && It->LowerBound <= LowerBound &&
+ It->UpperBound >= UpperBound)
+ return It;
+ return nullptr;
}
};
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index d02f4b9f7ebcd..28d4dd64e8945 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -103,6 +103,17 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
"true, yet no overlapping binding was found");
}
+static void reportInvalidHandleTyError(Module &M, ResourceClass RC,
+ ResourceInfo::ResourceBinding Binding) {
+ SmallString<160> Message;
+ raw_svector_ostream OS(Message);
+ StringRef RCName = getResourceClassName(RC);
+ OS << RCName << " at register " << Binding.LowerBound << " and space "
+ << Binding.Space << " is bound to a texture or typed buffer. " << RCName
+ << " root descriptors can only be Raw or Structured buffers.";
+ M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+}
+
static void reportOverlappingRegisters(Module &M, const llvm::hlsl::Binding &R1,
const llvm::hlsl::Binding &R2) {
SmallString<128> Message;
@@ -217,10 +228,29 @@ static void validateRootSignature(Module &M,
const hlsl::BoundRegs &BoundRegs = Builder.takeBoundRegs();
for (const ResourceInfo &RI : DRM) {
const ResourceInfo::ResourceBinding &Binding = RI.getBinding();
- ResourceClass RC = DRTM[RI.getHandleTy()].getResourceClass();
- if (!BoundRegs.isBound(RC, Binding.Space, Binding.LowerBound,
- Binding.LowerBound + Binding.Size - 1))
+ const dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
+ dxil::ResourceClass RC = RTI.getResourceClass();
+ dxil::ResourceKind RK = RTI.getResourceKind();
+
+ const llvm::hlsl::Binding *Reg =
+ 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 (ParamInfo->Type == dxbc::RootParameterType::DescriptorTable)
+ continue;
+
+ if (RK != ResourceKind::RawBuffer && RK != ResourceKind::StructuredBuffer)
+ reportInvalidHandleTyError(M, RC, Binding);
+ } else {
reportRegNotBound(M, RC, Binding);
+ }
}
}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll b/llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll
new file mode 100644
index 0000000000000..4721db23a766d
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll
@@ -0,0 +1,17 @@
+; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s
+; "This is a valid root signature with a texture/typed buffer resource"
+
+ at TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+ %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)
+ ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!3}
+!3 = !{!"DescriptorTable", i32 0, !4}
+!4 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-valid-typedbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-valid-typedbuffer.ll
new file mode 100644
index 0000000000000..2a52b3dee9d28
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-valid-typedbuffer.ll
@@ -0,0 +1,17 @@
+; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1
+; This is a valid root signature with a texture/typed buffer resource
+
+ at TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+ %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)
+ ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!3}
+!3 = !{!"DescriptorTable", i32 0, !4}
+!4 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll
new file mode 100644
index 0000000000000..7ec9d8047d08f
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll
@@ -0,0 +1,16 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: UAV at register 0 and space 0 is bound to a texture or typed buffer.
+
+ at TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+ %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)
+ ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2}
+!2 = !{!"RootUAV", i32 0, i32 0, i32 0, i32 4}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll
new file mode 100644
index 0000000000000..a0120c3954ad0
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll
@@ -0,0 +1,16 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: UAV at register 0 and space 0 is bound to a texture or typed buffer.
+
+ at TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+ %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)
+ ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2}
+!2 = !{!"RootUAV", i32 0, i32 0, i32 0, i32 4}
More information about the llvm-commits
mailing list