[llvm-branch-commits] [clang] [llvm] [DirectX] Add Range Overlap validation to `DXILPostOptimizationValidation.cpp` (PR #148919)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jul 24 13:15:30 PDT 2025
https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/148919
>From 831dc1cab2662151e0c4a95883f6fb73afc595d4 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 15 Jul 2025 01:59:47 +0000
Subject: [PATCH 1/6] adding validation
---
.../DXILPostOptimizationValidation.cpp | 152 ++++++++++++++++--
...signature-validation-fail-overlap-range.ll | 16 ++
2 files changed, 153 insertions(+), 15 deletions(-)
create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.ll
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index a09c5ac353fed..e42d2bef62ba7 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -13,6 +13,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/DXILMetadataAnalysis.h"
#include "llvm/Analysis/DXILResource.h"
+#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicsDirectX.h"
@@ -209,6 +210,123 @@ getRootSignature(RootSignatureBindingInfo &RSBI,
return RootSigDesc;
}
+static void
+reportOverlappingRegisters(Module &M,
+ llvm::hlsl::rootsig::OverlappingRanges Overlap) {
+ const llvm::hlsl::rootsig::RangeInfo *Info = Overlap.A;
+ const llvm::hlsl::rootsig::RangeInfo *OInfo = Overlap.B;
+ SmallString<128> Message;
+ raw_svector_ostream OS(Message);
+ auto ResourceClassToString =
+ [](llvm::dxil::ResourceClass Class) -> const char * {
+ switch (Class) {
+
+ case ResourceClass::SRV:
+ return "SRV";
+ case ResourceClass::UAV:
+ return "UAV";
+ case ResourceClass::CBuffer:
+ return "CBuffer";
+ case ResourceClass::Sampler:
+ return "Sampler";
+ break;
+ }
+ };
+ OS << "register " << ResourceClassToString(Info->Class)
+ << " (space=" << Info->Space << ", register=" << Info->LowerBound << ")"
+ << " is overlapping with"
+ << " register " << ResourceClassToString(OInfo->Class)
+ << " (space=" << OInfo->Space << ", register=" << OInfo->LowerBound << ")"
+ << ", verify your root signature definition";
+
+ M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+}
+
+static bool reportOverlappingRanges(Module &M,
+ const mcdxbc::RootSignatureDesc &RSD) {
+ using namespace llvm::hlsl::rootsig;
+
+ llvm::SmallVector<RangeInfo> Infos;
+ // Helper to map DescriptorRangeType to ResourceClass
+ auto RangeToResourceClass = [](uint32_t RangeType) -> ResourceClass {
+ using namespace dxbc;
+ switch (static_cast<DescriptorRangeType>(RangeType)) {
+ case DescriptorRangeType::SRV:
+ return ResourceClass::SRV;
+ case DescriptorRangeType::UAV:
+ return ResourceClass::UAV;
+ case DescriptorRangeType::CBV:
+ return ResourceClass::CBuffer;
+ case DescriptorRangeType::Sampler:
+ return ResourceClass::Sampler;
+ }
+ };
+
+ // Helper to map RootParameterType to ResourceClass
+ auto ParameterToResourceClass = [](uint32_t Type) -> ResourceClass {
+ using namespace dxbc;
+ switch (static_cast<RootParameterType>(Type)) {
+ case RootParameterType::SRV:
+ return ResourceClass::SRV;
+ case RootParameterType::UAV:
+ return ResourceClass::UAV;
+ case RootParameterType::CBV:
+ return ResourceClass::CBuffer;
+ default:
+ llvm_unreachable("Unknown RootParameterType");
+ }
+ };
+
+ for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) {
+ const auto &[Type, Loc] =
+ RSD.ParametersContainer.getTypeAndLocForParameter(I);
+ const auto &Header = RSD.ParametersContainer.getHeader(I);
+ switch (Type) {
+ case llvm::to_underlying(dxbc::RootParameterType::SRV):
+ case llvm::to_underlying(dxbc::RootParameterType::UAV):
+ case llvm::to_underlying(dxbc::RootParameterType::CBV): {
+ dxbc::RTS0::v2::RootDescriptor Desc =
+ RSD.ParametersContainer.getRootDescriptor(Loc);
+
+ RangeInfo Info;
+ Info.Space = Desc.RegisterSpace;
+ Info.LowerBound = Desc.ShaderRegister;
+ Info.UpperBound = Info.LowerBound;
+ Info.Class = ParameterToResourceClass(Type);
+ Info.Visibility = (dxbc::ShaderVisibility)Header.ShaderVisibility;
+
+ Infos.push_back(Info);
+ break;
+ }
+ case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
+ const mcdxbc::DescriptorTable &Table =
+ RSD.ParametersContainer.getDescriptorTable(Loc);
+
+ for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) {
+ RangeInfo Info;
+ Info.Space = Range.RegisterSpace;
+ Info.LowerBound = Range.BaseShaderRegister;
+ Info.UpperBound = Info.LowerBound + ((Range.NumDescriptors == ~0U)
+ ? Range.NumDescriptors
+ : Range.NumDescriptors - 1);
+ Info.Visibility = (dxbc::ShaderVisibility)Header.ShaderVisibility;
+ Info.Class = RangeToResourceClass(Range.RangeType);
+
+ Infos.push_back(Info);
+ }
+ break;
+ }
+ }
+ }
+
+ llvm::SmallVector<OverlappingRanges> Overlaps =
+ llvm::hlsl::rootsig::findOverlappingRanges(Infos);
+ for (OverlappingRanges Overlap : Overlaps)
+ reportOverlappingRegisters(M, Overlap);
+
+ return Overlaps.size() > 0;
+}
+
static void reportInvalidRegistersBinding(
Module &M,
const llvm::ArrayRef<llvm::dxil::ResourceInfo::ResourceBinding> &Bindings,
@@ -254,21 +372,25 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
if (auto RSD = getRootSignature(RSBI, MMI)) {
- RootSignatureBindingValidation Validation =
- initRSBindingValidation(*RSD, tripleToVisibility(MMI.ShaderProfile));
-
- reportInvalidRegistersBinding(
- M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV),
- DRM.cbuffers());
- reportInvalidRegistersBinding(
- M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV),
- DRM.uavs());
- reportInvalidRegistersBinding(
- M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler),
- DRM.samplers());
- reportInvalidRegistersBinding(
- M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV),
- DRM.srvs());
+ if (!reportOverlappingRanges(M, *RSD)) {
+ // Those checks require that no range is overlapping to provide correct
+ // diagnostic.
+ RootSignatureBindingValidation Validation =
+ initRSBindingValidation(*RSD, tripleToVisibility(MMI.ShaderProfile));
+
+ reportInvalidRegistersBinding(
+ M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV),
+ DRM.cbuffers());
+ reportInvalidRegistersBinding(
+ M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV),
+ DRM.uavs());
+ reportInvalidRegistersBinding(
+ M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler),
+ DRM.samplers());
+ reportInvalidRegistersBinding(
+ M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV),
+ DRM.srvs());
+ }
}
}
} // namespace
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.ll
new file mode 100644
index 0000000000000..8154588717a93
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.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: register UAV (space=0, register=2) is overlapping with register UAV (space=0, register=0), verify your root signature definition
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+ ret void
+}
+
+!dx.rootsignatures = !{!0}
+
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !4}
+!2 = !{!"DescriptorTable", i32 2, !3}
+!3 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2}
+!4 = !{!"DescriptorTable", i32 0, !5}
+!5 = !{!"UAV", i32 4, i32 2, i32 0, i32 -1, i32 2}
>From e0949e0de87728befe023547c6be6b5db18ef71e Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 15 Jul 2025 17:57:55 +0000
Subject: [PATCH 2/6] adding root constants
---
.../RootSignature-resource-ranges-err.hlsl | 62 +------------------
.../DXILPostOptimizationValidation.cpp | 26 ++++++--
...signature-validation-fail-cbuffer-range.ll | 15 +++++
...signature-validation-fail-overlap-range.ll | 2 +-
4 files changed, 40 insertions(+), 65 deletions(-)
create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
diff --git a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
index 4b3579d51818a..bbe101d0a6cf2 100644
--- a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
@@ -1,64 +1,6 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify
-// expected-error at +1 {{resource ranges b[42;42] and b[42;42] overlap within space = 0 and visibility = All}}
-[RootSignature("CBV(b42), CBV(b42)")]
-void bad_root_signature_0() {}
-
-// expected-error at +1 {{resource ranges t[0;0] and t[0;0] overlap within space = 3 and visibility = All}}
-[RootSignature("SRV(t0, space = 3), SRV(t0, space = 3)")]
-void bad_root_signature_1() {}
-
-// expected-error at +1 {{resource ranges u[0;0] and u[0;0] overlap within space = 0 and visibility = Pixel}}
-[RootSignature("UAV(u0, visibility = SHADER_VISIBILITY_PIXEL), UAV(u0, visibility = SHADER_VISIBILITY_PIXEL)")]
-void bad_root_signature_2() {}
-
-// expected-error at +1 {{resource ranges u[0;0] and u[0;0] overlap within space = 0 and visibility = Pixel}}
-[RootSignature("UAV(u0, visibility = SHADER_VISIBILITY_ALL), UAV(u0, visibility = SHADER_VISIBILITY_PIXEL)")]
-void bad_root_signature_3() {}
-
-// expected-error at +1 {{resource ranges u[0;0] and u[0;0] overlap within space = 0 and visibility = Pixel}}
-[RootSignature("UAV(u0, visibility = SHADER_VISIBILITY_PIXEL), UAV(u0, visibility = SHADER_VISIBILITY_ALL)")]
-void bad_root_signature_4() {}
-
-// expected-error at +1 {{resource ranges b[0;0] and b[0;0] overlap within space = 0 and visibility = All}}
-[RootSignature("RootConstants(num32BitConstants=4, b0), RootConstants(num32BitConstants=2, b0)")]
-void bad_root_signature_5() {}
-
-// expected-error at +1 {{resource ranges s[3;3] and s[3;3] overlap within space = 0 and visibility = All}}
-[RootSignature("StaticSampler(s3), StaticSampler(s3)")]
-void bad_root_signature_6() {}
-
-// expected-error at +1 {{resource ranges t[2;5] and t[0;3] overlap within space = 0 and visibility = All}}
-[RootSignature("DescriptorTable(SRV(t0, numDescriptors=4), SRV(t2, numDescriptors=4))")]
-void bad_root_signature_7() {}
-
-// expected-error at +1 {{resource ranges u[2;5] and u[0;unbounded) overlap within space = 0 and visibility = Hull}}
-[RootSignature("DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), DescriptorTable(UAV(u2, numDescriptors=4))")]
-void bad_root_signature_8() {}
-
// expected-error at +1 {{resource ranges b[0;2] and b[2;2] overlap within space = 0 and visibility = All}}
-[RootSignature("RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b0, numDescriptors=3))")]
+[numthreads(8, 8, 1)]
+[RootSignature("RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b10, numDescriptors=3))")]
void bad_root_signature_9() {}
-
-// expected-error at +1 {{resource ranges s[4;unbounded) and s[17;17] overlap within space = 0 and visibility = All}}
-[RootSignature("StaticSampler(s17), DescriptorTable(Sampler(s0, numDescriptors=3),Sampler(s4, numDescriptors=unbounded))")]
-void bad_root_signature_10() {}
-
-// expected-error at +1 {{resource ranges b[45;45] and b[4;unbounded) overlap within space = 0 and visibility = Geometry}}
-[RootSignature("DescriptorTable(CBV(b4, numDescriptors=unbounded)), CBV(b45, visibility = SHADER_VISIBILITY_GEOMETRY)")]
-void bad_root_signature_11() {}
-
-#define ReportFirstOverlap \
- "DescriptorTable( " \
- " CBV(b4, numDescriptors = 4), " \
- " CBV(b1, numDescriptors = 2), " \
- " CBV(b0, numDescriptors = 8), " \
- ")"
-
-// expected-error at +1 {{resource ranges b[0;7] and b[1;2] overlap within space = 0 and visibility = All}}
-[RootSignature(ReportFirstOverlap)]
-void bad_root_signature_12() {}
-
-// expected-error at +1 {{resource ranges s[2;2] and s[2;2] overlap within space = 0 and visibility = Vertex}}
-[RootSignature("StaticSampler(s2, visibility=SHADER_VISIBILITY_ALL), DescriptorTable(Sampler(s2), visibility=SHADER_VISIBILITY_VERTEX)")]
-void valid_root_signature_13() {}
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index e42d2bef62ba7..7a1abaefa60df 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -9,10 +9,12 @@
#include "DXILPostOptimizationValidation.h"
#include "DXILShaderFlags.h"
#include "DirectX.h"
+#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/DXILMetadataAnalysis.h"
#include "llvm/Analysis/DXILResource.h"
+#include "llvm/BinaryFormat/DXContainer.h"
#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Instructions.h"
@@ -265,12 +267,14 @@ static bool reportOverlappingRanges(Module &M,
// Helper to map RootParameterType to ResourceClass
auto ParameterToResourceClass = [](uint32_t Type) -> ResourceClass {
using namespace dxbc;
- switch (static_cast<RootParameterType>(Type)) {
- case RootParameterType::SRV:
+ switch (Type) {
+ case llvm::to_underlying(RootParameterType::Constants32Bit):
+ return ResourceClass::CBuffer;
+ case llvm::to_underlying(RootParameterType::SRV):
return ResourceClass::SRV;
- case RootParameterType::UAV:
+ case llvm::to_underlying(RootParameterType::UAV):
return ResourceClass::UAV;
- case RootParameterType::CBV:
+ case llvm::to_underlying(RootParameterType::CBV):
return ResourceClass::CBuffer;
default:
llvm_unreachable("Unknown RootParameterType");
@@ -282,6 +286,20 @@ static bool reportOverlappingRanges(Module &M,
RSD.ParametersContainer.getTypeAndLocForParameter(I);
const auto &Header = RSD.ParametersContainer.getHeader(I);
switch (Type) {
+ case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): {
+ dxbc::RTS0::v1::RootConstants Const =
+ RSD.ParametersContainer.getConstant(Loc);
+
+ RangeInfo Info;
+ Info.Space = Const.RegisterSpace;
+ Info.LowerBound = Const.ShaderRegister;
+ Info.UpperBound = Info.LowerBound;
+ Info.Class = ParameterToResourceClass(Type);
+ Info.Visibility = (dxbc::ShaderVisibility)Header.ShaderVisibility;
+
+ Infos.push_back(Info);
+ break;
+ }
case llvm::to_underlying(dxbc::RootParameterType::SRV):
case llvm::to_underlying(dxbc::RootParameterType::UAV):
case llvm::to_underlying(dxbc::RootParameterType::CBV): {
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
new file mode 100644
index 0000000000000..431ec577efc5f
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
@@ -0,0 +1,15 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: register CBuffer (space=0, register=0) is overlapping with register CBuffer (space=0, register=2), verify your root signature definition
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+ ret void
+}
+
+; RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b10, numDescriptors=3))
+!dx.rootsignatures = !{!0}
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3}
+!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4}
+!3 = !{!"DescriptorTable", i32 0, !4}
+!4 = !{!"CBV", i32 3, i32 0, i32 0, i32 -1, i32 4}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.ll
index 8154588717a93..17b22b62ff8f5 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.ll
@@ -6,8 +6,8 @@ entry:
ret void
}
+; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), DescriptorTable(UAV(u2, numDescriptors=4))
!dx.rootsignatures = !{!0}
-
!0 = !{ptr @CSMain, !1, i32 2}
!1 = !{!2, !4}
!2 = !{!"DescriptorTable", i32 2, !3}
>From 4bb0368c44f664fed2de6b6ec6e0d5f1a43d10f8 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 15 Jul 2025 18:30:11 +0000
Subject: [PATCH 3/6] fix
---
.../RootSignature-resource-ranges-err.hlsl | 62 ++++++++++++++++++-
1 file changed, 60 insertions(+), 2 deletions(-)
diff --git a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
index bbe101d0a6cf2..4b3579d51818a 100644
--- a/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
+++ b/clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
@@ -1,6 +1,64 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify
+// expected-error at +1 {{resource ranges b[42;42] and b[42;42] overlap within space = 0 and visibility = All}}
+[RootSignature("CBV(b42), CBV(b42)")]
+void bad_root_signature_0() {}
+
+// expected-error at +1 {{resource ranges t[0;0] and t[0;0] overlap within space = 3 and visibility = All}}
+[RootSignature("SRV(t0, space = 3), SRV(t0, space = 3)")]
+void bad_root_signature_1() {}
+
+// expected-error at +1 {{resource ranges u[0;0] and u[0;0] overlap within space = 0 and visibility = Pixel}}
+[RootSignature("UAV(u0, visibility = SHADER_VISIBILITY_PIXEL), UAV(u0, visibility = SHADER_VISIBILITY_PIXEL)")]
+void bad_root_signature_2() {}
+
+// expected-error at +1 {{resource ranges u[0;0] and u[0;0] overlap within space = 0 and visibility = Pixel}}
+[RootSignature("UAV(u0, visibility = SHADER_VISIBILITY_ALL), UAV(u0, visibility = SHADER_VISIBILITY_PIXEL)")]
+void bad_root_signature_3() {}
+
+// expected-error at +1 {{resource ranges u[0;0] and u[0;0] overlap within space = 0 and visibility = Pixel}}
+[RootSignature("UAV(u0, visibility = SHADER_VISIBILITY_PIXEL), UAV(u0, visibility = SHADER_VISIBILITY_ALL)")]
+void bad_root_signature_4() {}
+
+// expected-error at +1 {{resource ranges b[0;0] and b[0;0] overlap within space = 0 and visibility = All}}
+[RootSignature("RootConstants(num32BitConstants=4, b0), RootConstants(num32BitConstants=2, b0)")]
+void bad_root_signature_5() {}
+
+// expected-error at +1 {{resource ranges s[3;3] and s[3;3] overlap within space = 0 and visibility = All}}
+[RootSignature("StaticSampler(s3), StaticSampler(s3)")]
+void bad_root_signature_6() {}
+
+// expected-error at +1 {{resource ranges t[2;5] and t[0;3] overlap within space = 0 and visibility = All}}
+[RootSignature("DescriptorTable(SRV(t0, numDescriptors=4), SRV(t2, numDescriptors=4))")]
+void bad_root_signature_7() {}
+
+// expected-error at +1 {{resource ranges u[2;5] and u[0;unbounded) overlap within space = 0 and visibility = Hull}}
+[RootSignature("DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), DescriptorTable(UAV(u2, numDescriptors=4))")]
+void bad_root_signature_8() {}
+
// expected-error at +1 {{resource ranges b[0;2] and b[2;2] overlap within space = 0 and visibility = All}}
-[numthreads(8, 8, 1)]
-[RootSignature("RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b10, numDescriptors=3))")]
+[RootSignature("RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b0, numDescriptors=3))")]
void bad_root_signature_9() {}
+
+// expected-error at +1 {{resource ranges s[4;unbounded) and s[17;17] overlap within space = 0 and visibility = All}}
+[RootSignature("StaticSampler(s17), DescriptorTable(Sampler(s0, numDescriptors=3),Sampler(s4, numDescriptors=unbounded))")]
+void bad_root_signature_10() {}
+
+// expected-error at +1 {{resource ranges b[45;45] and b[4;unbounded) overlap within space = 0 and visibility = Geometry}}
+[RootSignature("DescriptorTable(CBV(b4, numDescriptors=unbounded)), CBV(b45, visibility = SHADER_VISIBILITY_GEOMETRY)")]
+void bad_root_signature_11() {}
+
+#define ReportFirstOverlap \
+ "DescriptorTable( " \
+ " CBV(b4, numDescriptors = 4), " \
+ " CBV(b1, numDescriptors = 2), " \
+ " CBV(b0, numDescriptors = 8), " \
+ ")"
+
+// expected-error at +1 {{resource ranges b[0;7] and b[1;2] overlap within space = 0 and visibility = All}}
+[RootSignature(ReportFirstOverlap)]
+void bad_root_signature_12() {}
+
+// expected-error at +1 {{resource ranges s[2;2] and s[2;2] overlap within space = 0 and visibility = Vertex}}
+[RootSignature("StaticSampler(s2, visibility=SHADER_VISIBILITY_ALL), DescriptorTable(Sampler(s2), visibility=SHADER_VISIBILITY_VERTEX)")]
+void valid_root_signature_13() {}
>From 67208157d43f0a15c4089f094e3a3674cf15cc9c Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 22 Jul 2025 00:01:21 +0000
Subject: [PATCH 4/6] address comments
---
.../DXILPostOptimizationValidation.cpp | 37 ++++++++++---------
...signature-validation-fail-cbuffer-range.ll | 2 +-
2 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 3cb116616e85d..130009b6a3a5b 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -272,7 +272,7 @@ reportOverlappingRegisters(Module &M,
<< " is overlapping with"
<< " register " << ResourceClassToString(OInfo->Class)
<< " (space=" << OInfo->Space << ", register=" << OInfo->LowerBound << ")"
- << ", verify your root signature definition";
+ << ", verify your root signature definition.";
M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}
@@ -323,14 +323,15 @@ static bool reportOverlappingRanges(Module &M,
RSD.ParametersContainer.getDescriptorTable(Loc);
for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) {
+ assert(Range.NumDescriptors > 0);
RangeInfo Info;
Info.Space = Range.RegisterSpace;
Info.LowerBound = Range.BaseShaderRegister;
Info.UpperBound = Info.LowerBound + ((Range.NumDescriptors == ~0U)
? Range.NumDescriptors
: Range.NumDescriptors - 1);
- Info.Visibility = (dxbc::ShaderVisibility)Header.ShaderVisibility;
Info.Class = RangeToResourceClass(Range.RangeType);
+ Info.Visibility = (dxbc::ShaderVisibility)Header.ShaderVisibility;
Infos.push_back(Info);
}
@@ -399,22 +400,22 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
"DXILResourceImplicitBinding pass");
if (auto RSD = getRootSignature(RSBI, MMI)) {
- if (!reportOverlappingRanges(M, *RSD)) {
- llvm::hlsl::rootsig::RootSignatureBindingValidation Validation =
- initRSBindingValidation(*RSD, tripleToVisibility(MMI.ShaderProfile));
-
- reportUnboundRegisters(M, Validation, ResourceClass::CBuffer,
- DRM.cbuffers());
- reportUnboundRegisters(M, Validation, ResourceClass::UAV, DRM.uavs());
- reportUnboundRegisters(M, Validation, ResourceClass::Sampler,
- DRM.samplers());
- reportUnboundRegisters(M, Validation, ResourceClass::SRV, DRM.srvs());
-
- reportInvalidHandleTy(M, DRM.cbuffers());
- reportInvalidHandleTy(M, DRM.srvs());
- reportInvalidHandleTy(M, DRM.uavs());
- reportInvalidHandleTy(M, DRM.samplers());
- }
+ if (reportOverlappingRanges(M, *RSD))
+ return;
+ llvm::hlsl::rootsig::RootSignatureBindingValidation Validation =
+ initRSBindingValidation(*RSD, tripleToVisibility(MMI.ShaderProfile));
+
+ reportUnboundRegisters(M, Validation, ResourceClass::CBuffer,
+ DRM.cbuffers());
+ reportUnboundRegisters(M, Validation, ResourceClass::UAV, DRM.uavs());
+ reportUnboundRegisters(M, Validation, ResourceClass::Sampler,
+ DRM.samplers());
+ reportUnboundRegisters(M, Validation, ResourceClass::SRV, DRM.srvs());
+
+ reportInvalidHandleTy(M, DRM.cbuffers());
+ reportInvalidHandleTy(M, DRM.srvs());
+ reportInvalidHandleTy(M, DRM.uavs());
+ reportInvalidHandleTy(M, DRM.samplers());
}
}
} // namespace
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
index 431ec577efc5f..bcc05c61637ec 100644
--- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll
@@ -6,7 +6,7 @@ entry:
ret void
}
-; RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b10, numDescriptors=3))
+; RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b0, numDescriptors=3))
!dx.rootsignatures = !{!0}
!0 = !{ptr @CSMain, !1, i32 2}
!1 = !{!2, !3}
>From 356c4b7652478374cc2ad0e1bf9afbbe35e7e5d1 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 22 Jul 2025 17:08:40 +0000
Subject: [PATCH 5/6] adding samplers
---
.../DirectX/DXILPostOptimizationValidation.cpp | 12 ++++++++++++
.../rootsignature-validation-fail-sampler-range.ll | 14 ++++++++++++++
2 files changed, 26 insertions(+)
create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-range.ll
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 5626fbe5eb66d..85ce1a4d569d4 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -22,6 +22,7 @@
#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
+#include "llvm/Support/DXILABI.h"
#define DEBUG_TYPE "dxil-post-optimization-validation"
@@ -376,6 +377,17 @@ static bool reportOverlappingRanges(Module &M,
}
}
+ for (const dxbc::RTS0::v1::StaticSampler &Sampler : RSD.StaticSamplers) {
+ RangeInfo Info;
+ Info.Space = Sampler.RegisterSpace;
+ Info.LowerBound = Sampler.ShaderRegister;
+ Info.UpperBound = Info.LowerBound;
+ Info.Class = ResourceClass::Sampler;
+ Info.Visibility = (dxbc::ShaderVisibility)Sampler.ShaderVisibility;
+
+ Infos.push_back(Info);
+ }
+
llvm::SmallVector<OverlappingRanges> Overlaps =
llvm::hlsl::rootsig::findOverlappingRanges(Infos);
for (OverlappingRanges Overlap : Overlaps)
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-range.ll
new file mode 100644
index 0000000000000..5574b64c015cc
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-range.ll
@@ -0,0 +1,14 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: register Sampler (space=0, register=42) is overlapping with register Sampler (space=0, register=42), verify your root signature definition.
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+ ret void
+}
+
+; RootConstants(num32BitConstants=4, b2), DescriptorTable(CBV(b0, numDescriptors=3))
+!dx.rootsignatures = !{!0}
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !3}
+!2 = !{ !"StaticSampler", i32 4, i32 2, i32 3, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0 }
+!3 = !{ !"StaticSampler", i32 4, i32 2, i32 3, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0 }
>From dec12d93d053befc1d1e68854e063cab4d362e87 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Thu, 24 Jul 2025 20:14:52 +0000
Subject: [PATCH 6/6] improve tests
---
...ure-validation-fail-descriptor-table-range.ll} | 0
...ature-validation-fail-root-descriptor-range.ll | 15 +++++++++++++++
...ature-validation-fail-static-sampler-range.ll} | 0
3 files changed, 15 insertions(+)
rename llvm/test/CodeGen/DirectX/{rootsignature-validation-fail-overlap-range.ll => rootsignature-validation-fail-descriptor-table-range.ll} (100%)
create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
rename llvm/test/CodeGen/DirectX/{rootsignature-validation-fail-sampler-range.ll => rootsignature-validation-fail-static-sampler-range.ll} (100%)
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll
similarity index 100%
rename from llvm/test/CodeGen/DirectX/rootsignature-validation-fail-overlap-range.ll
rename to llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
new file mode 100644
index 0000000000000..79544a4fbbc7c
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll
@@ -0,0 +1,15 @@
+; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s
+; CHECK: error: register UAV (space=0, register=2) is overlapping with register UAV (space=0, register=0), verify your root signature definition
+
+define void @CSMain() "hlsl.shader"="compute" {
+entry:
+ ret void
+}
+
+; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_ALL), UAV(u2, space=0, visibility=SHADER_VISIBILITY_ALL))
+!dx.rootsignatures = !{!0}
+!0 = !{ptr @CSMain, !1, i32 2}
+!1 = !{!2, !4}
+!2 = !{!"DescriptorTable", i32 2, !3}
+!3 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 4}
+!4 = !{!"RootUAV", i32 0, i32 2, i32 0, i32 4}
diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll
similarity index 100%
rename from llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-range.ll
rename to llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll
More information about the llvm-branch-commits
mailing list