https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/153276
>From 50e78d283fb2915a56cd3844f83d1b97a14bf2b8 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:21:17 -0700 Subject: [PATCH 01/11] check if table mix samplers with others --- .../DXILPostOptimizationValidation.cpp | 66 +++++++++++++++++-- ...otsignature-validation-fail-sampler-mix.ll | 18 +++++ 2 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index abcefe287d9bc..a07f92d5500fa 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -21,6 +21,7 @@ #include "llvm/InitializePasses.h" #include "llvm/MC/DXContainerRootSignature.h" #include "llvm/Support/DXILABI.h" +#include <cstdint> #define DEBUG_TYPE "dxil-post-optimization-validation" @@ -155,6 +156,19 @@ reportRegNotBound(Module &M, ResourceClass Class, M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } +static void +reportDescriptorTableMixingTypes(Module &M, uint32_t Location, + dxbc::DescriptorRangeType RangeType) { + SmallString<128> Message; + raw_svector_ostream OS(Message); + OS << "Samplers cannot be mixed with other " + << "resource types in a descriptor table, " + << getResourceClassName(toResourceClass(RangeType)) + << "(location=" << Location << ")"; + + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); +} + static void reportInvalidHandleTy( Module &M, const llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding> &RDs, const iterator_range<SmallVectorImpl<dxil::ResourceInfo>::iterator> @@ -236,10 +250,47 @@ getRootDescriptorsBindingInfo(const mcdxbc::RootSignatureDesc &RSD, return RDs; } -static void validateRootSignature(Module &M, - const mcdxbc::RootSignatureDesc &RSD, - dxil::ModuleMetadataInfo &MMI, - DXILResourceMap &DRM) { +static void validateDescriptorTables(Module &M, + const mcdxbc::RootSignatureDesc &RSD, + dxil::ModuleMetadataInfo &MMI, + DXILResourceMap &DRM) { + for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) { + if (static_cast<dxbc::RootParameterType>(ParamInfo.Header.ParameterType) != + dxbc::RootParameterType::DescriptorTable) + continue; + + mcdxbc::DescriptorTable Table = + RSD.ParametersContainer.getDescriptorTable(ParamInfo.Location); + + // Samplers cannot be mixed with other resources in a descriptor table. + bool HasSampler = false; + bool HasOtherRangeType = false; + dxbc::DescriptorRangeType OtherRangeType; + uint32_t OtherRangeTypeLocation = 0; + + for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { + dxbc::DescriptorRangeType RangeType = + static_cast<dxbc::DescriptorRangeType>(Range.RangeType); + if (RangeType == dxbc::DescriptorRangeType::Sampler) { + HasSampler = true; + } else { + HasOtherRangeType = true; + OtherRangeType = RangeType; + OtherRangeTypeLocation = ParamInfo.Location; + } + } + if (HasSampler && HasOtherRangeType) { + reportDescriptorTableMixingTypes(M, OtherRangeTypeLocation, + OtherRangeType); + continue; + } + } +} + +static void validateRootSignatureBindings(Module &M, + const mcdxbc::RootSignatureDesc &RSD, + dxil::ModuleMetadataInfo &MMI, + DXILResourceMap &DRM) { hlsl::BindingInfoBuilder Builder; dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); @@ -309,7 +360,6 @@ static void validateRootSignature(Module &M, reportOverlappingRegisters(M, ReportedBinding, Overlaping); }); // Next checks require that the root signature definition is valid. - // Next checks require that the root signature definition is valid. if (!HasOverlap) { SmallVector<ResourceInfo::ResourceBinding> RDs = getRootDescriptorsBindingInfo(RSD, Visibility); @@ -351,8 +401,10 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in " "DXILResourceImplicitBinding pass"); - if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI)) - validateRootSignature(M, *RSD, MMI, DRM); + if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI)) { + validateRootSignatureBindings(M, *RSD, MMI, DRM); + validateDescriptorTables(M, *RSD, MMI, DRM); + } } PreservedAnalyses diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll new file mode 100644 index 0000000000000..d4caeb2675d82 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll @@ -0,0 +1,18 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s +; CHECK: error: Samplers cannot be mixed with other resource types in a descriptor table, UAV(location=0) + +@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!3} +!3 = !{!"DescriptorTable", i32 0, !4, !5} +!4 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0} +!5 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} + >From aee4c564bcd7698c1b3574b8acf8c37ca033e52b Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 12:10:33 -0700 Subject: [PATCH 02/11] validating register not overflow in table --- .../DXILPostOptimizationValidation.cpp | 40 ++++++++++++++++++- ...ture-validation-fail-appending-overflow.ll | 18 +++++++++ ...ature-validation-fail-register-overflow.ll | 17 ++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index a07f92d5500fa..3721b5f539b8c 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -169,6 +169,18 @@ reportDescriptorTableMixingTypes(Module &M, uint32_t Location, M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } +static void reportOverlowingRange(Module &M, const dxbc::RTS0::v2::DescriptorRange &Range) { + SmallString<128> Message; + raw_svector_ostream OS(Message); + OS << "Cannot append range with implicit lower " + << "bound after an unbounded range " + << getResourceClassName(toResourceClass(static_cast<dxbc::DescriptorRangeType>(Range.RangeType))) + << "(register=" << Range.BaseShaderRegister << ", space=" << + Range.RegisterSpace + << ") exceeds maximum allowed value."; + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); +} + static void reportInvalidHandleTy( Module &M, const llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding> &RDs, const iterator_range<SmallVectorImpl<dxil::ResourceInfo>::iterator> @@ -250,6 +262,8 @@ getRootDescriptorsBindingInfo(const mcdxbc::RootSignatureDesc &RSD, return RDs; } + + static void validateDescriptorTables(Module &M, const mcdxbc::RootSignatureDesc &RSD, dxil::ModuleMetadataInfo &MMI, @@ -262,15 +276,37 @@ static void validateDescriptorTables(Module &M, mcdxbc::DescriptorTable Table = RSD.ParametersContainer.getDescriptorTable(ParamInfo.Location); - // Samplers cannot be mixed with other resources in a descriptor table. bool HasSampler = false; bool HasOtherRangeType = false; dxbc::DescriptorRangeType OtherRangeType; uint32_t OtherRangeTypeLocation = 0; + uint64_t AppendingOffset = 0; + + for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { dxbc::DescriptorRangeType RangeType = static_cast<dxbc::DescriptorRangeType>(Range.RangeType); + + uint64_t Offset = AppendingOffset; + if(Range.OffsetInDescriptorsFromTableStart != ~0U) + Offset = Range.OffsetInDescriptorsFromTableStart; + + if(Offset > ~0U) + reportOverlowingRange(M, Range); + if(Range.NumDescriptors == ~0U) { + AppendingOffset = (uint64_t)~0U + (uint64_t)1ULL; + } else { + uint64_t UpperBound = (uint64_t)Range.BaseShaderRegister + (uint64_t)Range.NumDescriptors - (uint64_t)1U; + if(UpperBound > ~0U) + reportOverlowingRange(M, Range); + + uint64_t AppendingUpperBound = (uint64_t)Offset + (uint64_t)Range.NumDescriptors - (uint64_t)1U; + if(AppendingUpperBound > ~0U) + reportOverlowingRange(M, Range); + AppendingOffset = Offset + Range.NumDescriptors; + } + if (RangeType == dxbc::DescriptorRangeType::Sampler) { HasSampler = true; } else { @@ -279,6 +315,8 @@ static void validateDescriptorTables(Module &M, OtherRangeTypeLocation = ParamInfo.Location; } } + + // Samplers cannot be mixed with other resources in a descriptor table. if (HasSampler && HasOtherRangeType) { reportDescriptorTableMixingTypes(M, OtherRangeTypeLocation, OtherRangeType); diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll new file mode 100644 index 0000000000000..865312a43b5a8 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll @@ -0,0 +1,18 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s +; CHECK: error: Cannot append range with implicit lower bound after an unbounded range UAV(register=3, space=4) exceeds maximum allowed value. + +@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!3} +!3 = !{!"DescriptorTable", i32 0, !4, !5} +!4 = !{!"UAV", i32 -1, i32 1, i32 2, i32 -1, i32 0} +!5 = !{!"UAV", i32 1, i32 3, i32 4, i32 -1, i32 0} + diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll new file mode 100644 index 0000000000000..ef887baf80728 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll @@ -0,0 +1,17 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s +; CHECK: error: Cannot append range with implicit lower bound after an unbounded range UAV(register=4294967295, space=0) exceeds maximum allowed value. + +@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!3} +!3 = !{!"DescriptorTable", i32 0, !4} +!4 = !{!"UAV", i32 100, i32 4294967295, i32 0, i32 -1, i32 0} + >From 7d1c13ee694848d9211c24c414bf14727a8395c7 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:19:37 -0700 Subject: [PATCH 03/11] clean --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 3721b5f539b8c..7067d6a2960e8 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -21,7 +21,6 @@ #include "llvm/InitializePasses.h" #include "llvm/MC/DXContainerRootSignature.h" #include "llvm/Support/DXILABI.h" -#include <cstdint> #define DEBUG_TYPE "dxil-post-optimization-validation" >From 85719afb44b59b1aa5f6afdb494983983da0ce1a Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:26:11 -0700 Subject: [PATCH 04/11] format --- .../DXILPostOptimizationValidation.cpp | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 7067d6a2960e8..f749e255b5125 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -168,15 +168,16 @@ reportDescriptorTableMixingTypes(Module &M, uint32_t Location, M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } -static void reportOverlowingRange(Module &M, const dxbc::RTS0::v2::DescriptorRange &Range) { +static void +reportOverlowingRange(Module &M, const dxbc::RTS0::v2::DescriptorRange &Range) { SmallString<128> Message; raw_svector_ostream OS(Message); - OS << "Cannot append range with implicit lower " - << "bound after an unbounded range " - << getResourceClassName(toResourceClass(static_cast<dxbc::DescriptorRangeType>(Range.RangeType))) - << "(register=" << Range.BaseShaderRegister << ", space=" << - Range.RegisterSpace - << ") exceeds maximum allowed value."; + OS << "Cannot append range with implicit lower " + << "bound after an unbounded range " + << getResourceClassName(toResourceClass( + static_cast<dxbc::DescriptorRangeType>(Range.RangeType))) + << "(register=" << Range.BaseShaderRegister + << ", space=" << Range.RegisterSpace << ") exceeds maximum allowed value."; M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } @@ -261,8 +262,6 @@ getRootDescriptorsBindingInfo(const mcdxbc::RootSignatureDesc &RSD, return RDs; } - - static void validateDescriptorTables(Module &M, const mcdxbc::RootSignatureDesc &RSD, dxil::ModuleMetadataInfo &MMI, @@ -282,30 +281,31 @@ static void validateDescriptorTables(Module &M, uint64_t AppendingOffset = 0; - for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { dxbc::DescriptorRangeType RangeType = static_cast<dxbc::DescriptorRangeType>(Range.RangeType); - + uint64_t Offset = AppendingOffset; - if(Range.OffsetInDescriptorsFromTableStart != ~0U) + if (Range.OffsetInDescriptorsFromTableStart != ~0U) Offset = Range.OffsetInDescriptorsFromTableStart; - - if(Offset > ~0U) + + if (Offset > ~0U) reportOverlowingRange(M, Range); - if(Range.NumDescriptors == ~0U) { + if (Range.NumDescriptors == ~0U) { AppendingOffset = (uint64_t)~0U + (uint64_t)1ULL; - } else { - uint64_t UpperBound = (uint64_t)Range.BaseShaderRegister + (uint64_t)Range.NumDescriptors - (uint64_t)1U; - if(UpperBound > ~0U) + } else { + uint64_t UpperBound = (uint64_t)Range.BaseShaderRegister + + (uint64_t)Range.NumDescriptors - (uint64_t)1U; + if (UpperBound > ~0U) reportOverlowingRange(M, Range); - uint64_t AppendingUpperBound = (uint64_t)Offset + (uint64_t)Range.NumDescriptors - (uint64_t)1U; - if(AppendingUpperBound > ~0U) + uint64_t AppendingUpperBound = + (uint64_t)Offset + (uint64_t)Range.NumDescriptors - (uint64_t)1U; + if (AppendingUpperBound > ~0U) reportOverlowingRange(M, Range); AppendingOffset = Offset + Range.NumDescriptors; } - + if (RangeType == dxbc::DescriptorRangeType::Sampler) { HasSampler = true; } else { >From cc304fd464e1133cffc59cd28705cb3d68b25cbe Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:30:22 -0700 Subject: [PATCH 05/11] format --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index f749e255b5125..762a67a4c7f76 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -263,9 +263,7 @@ getRootDescriptorsBindingInfo(const mcdxbc::RootSignatureDesc &RSD, } static void validateDescriptorTables(Module &M, - const mcdxbc::RootSignatureDesc &RSD, - dxil::ModuleMetadataInfo &MMI, - DXILResourceMap &DRM) { + const mcdxbc::RootSignatureDesc &RSD) { for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) { if (static_cast<dxbc::RootParameterType>(ParamInfo.Header.ParameterType) != dxbc::RootParameterType::DescriptorTable) @@ -440,7 +438,7 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI)) { validateRootSignatureBindings(M, *RSD, MMI, DRM); - validateDescriptorTables(M, *RSD, MMI, DRM); + validateDescriptorTables(M, *RSD); } } >From 3c2814223ab6c439717e1a2bc15c4f929dfcb554 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:37:06 -0700 Subject: [PATCH 06/11] fix typo --- .../lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 762a67a4c7f76..bb1d9fa68528e 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -169,7 +169,7 @@ reportDescriptorTableMixingTypes(Module &M, uint32_t Location, } static void -reportOverlowingRange(Module &M, const dxbc::RTS0::v2::DescriptorRange &Range) { +reportOverflowingRange(Module &M, const dxbc::RTS0::v2::DescriptorRange &Range) { SmallString<128> Message; raw_svector_ostream OS(Message); OS << "Cannot append range with implicit lower " @@ -288,19 +288,19 @@ static void validateDescriptorTables(Module &M, Offset = Range.OffsetInDescriptorsFromTableStart; if (Offset > ~0U) - reportOverlowingRange(M, Range); + reportOverflowingRange(M, Range); if (Range.NumDescriptors == ~0U) { AppendingOffset = (uint64_t)~0U + (uint64_t)1ULL; } else { uint64_t UpperBound = (uint64_t)Range.BaseShaderRegister + (uint64_t)Range.NumDescriptors - (uint64_t)1U; if (UpperBound > ~0U) - reportOverlowingRange(M, Range); + reportOverflowingRange(M, Range); uint64_t AppendingUpperBound = (uint64_t)Offset + (uint64_t)Range.NumDescriptors - (uint64_t)1U; if (AppendingUpperBound > ~0U) - reportOverlowingRange(M, Range); + reportOverflowingRange(M, Range); AppendingOffset = Offset + Range.NumDescriptors; } >From 81261ff42897288b8d4cd625511257f6d113ed57 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:45:17 -0700 Subject: [PATCH 07/11] clean --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index bb1d9fa68528e..c9b558a5c62bc 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -169,7 +169,8 @@ reportDescriptorTableMixingTypes(Module &M, uint32_t Location, } static void -reportOverflowingRange(Module &M, const dxbc::RTS0::v2::DescriptorRange &Range) { +reportOverflowingRange(Module &M, + const dxbc::RTS0::v2::DescriptorRange &Range) { SmallString<128> Message; raw_svector_ostream OS(Message); OS << "Cannot append range with implicit lower " >From e5e73febb73594b3e51b4deaabf9d913b987f2b5 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 16:58:24 -0700 Subject: [PATCH 08/11] address comments --- .../Frontend/HLSL/RootSignatureMetadata.h | 80 +++++++++++ .../Frontend/HLSL/RootSignatureMetadata.cpp | 91 ++++++++++++ .../DXILPostOptimizationValidation.cpp | 131 +----------------- 3 files changed, 178 insertions(+), 124 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index 0bd0774641287..87b950d77df53 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -15,9 +15,11 @@ #define LLVM_FRONTEND_HLSL_ROOTSIGNATUREMETADATA_H #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" #include "llvm/IR/Constants.h" #include "llvm/MC/DXContainerRootSignature.h" +#include <cstdint> namespace llvm { class LLVMContext; @@ -27,6 +29,38 @@ class Metadata; namespace hlsl { namespace rootsig { +inline dxil::ResourceClass +toResourceClass(dxbc::DescriptorRangeType RangeType) { + using namespace dxbc; + switch (RangeType) { + case DescriptorRangeType::SRV: + return dxil::ResourceClass::SRV; + case DescriptorRangeType::UAV: + return dxil::ResourceClass::UAV; + case DescriptorRangeType::CBV: + return dxil::ResourceClass::CBuffer; + case DescriptorRangeType::Sampler: + return dxil::ResourceClass::Sampler; + } +} + +inline dxil::ResourceClass toResourceClass(dxbc::RootParameterType Type) { + using namespace dxbc; + switch (Type) { + case RootParameterType::Constants32Bit: + return dxil::ResourceClass::CBuffer; + case RootParameterType::SRV: + return dxil::ResourceClass::SRV; + case RootParameterType::UAV: + return dxil::ResourceClass::UAV; + case RootParameterType::CBV: + return dxil::ResourceClass::CBuffer; + case dxbc::RootParameterType::DescriptorTable: + break; + } + llvm_unreachable("Unconvertible RootParameterType"); +} + template <typename T> class RootSignatureValidationError : public ErrorInfo<RootSignatureValidationError<T>> { @@ -47,6 +81,52 @@ class RootSignatureValidationError } }; +class TableRegisterOverflowError + : public ErrorInfo<TableRegisterOverflowError> { +public: + static char ID; + dxbc::DescriptorRangeType Type; + uint32_t Register; + uint32_t Space; + + TableRegisterOverflowError(dxbc::DescriptorRangeType Type, uint32_t Register, + uint32_t Space) + : Type(Type), Register(Register), Space(Space) {} + + void log(raw_ostream &OS) const override { + OS << "Cannot append range with implicit lower " + << "bound after an unbounded range " + << getResourceClassName(toResourceClass(Type)) + << "(register=" << Register << ", space=" << Space + << ") exceeds maximum allowed value."; + } + + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; + +class TableSamplerMixinError : public ErrorInfo<TableSamplerMixinError> { +public: + static char ID; + dxbc::DescriptorRangeType Type; + uint32_t Location; + + TableSamplerMixinError(dxbc::DescriptorRangeType Type, uint32_t Location) + : Type(Type), Location(Location) {} + + void log(raw_ostream &OS) const override { + OS << "Samplers cannot be mixed with other " + << "resource types in a descriptor table, " + << getResourceClassName(toResourceClass(Type)) + << "(location=" << Location << ")"; + } + + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; + class GenericRSMetadataError : public ErrorInfo<GenericRSMetadataError> { public: static char ID; diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 6d89fa7b1222c..3878026518882 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -15,7 +15,9 @@ #include "llvm/Frontend/HLSL/RootSignatureValidations.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Metadata.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ScopedPrinter.h" +#include <cstdint> using namespace llvm; @@ -26,6 +28,8 @@ namespace rootsig { char GenericRSMetadataError::ID; char InvalidRSMetadataFormat::ID; char InvalidRSMetadataValue::ID; +char TableSamplerMixinError::ID; +char TableRegisterOverflowError::ID; template <typename T> char RootSignatureValidationError<T>::ID; static std::optional<uint32_t> extractMdIntValue(MDNode *Node, @@ -525,6 +529,83 @@ Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD, llvm_unreachable("Unhandled RootSignatureElementKind enum."); } +Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, + uint32_t Location) { + bool HasSampler = false; + bool HasOtherRangeType = false; + dxbc::DescriptorRangeType OtherRangeType; + + for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { + dxbc::DescriptorRangeType RangeType = + static_cast<dxbc::DescriptorRangeType>(Range.RangeType); + + if (RangeType == dxbc::DescriptorRangeType::Sampler) { + HasSampler = true; + } else { + HasOtherRangeType = true; + OtherRangeType = RangeType; + } + } + + // Samplers cannot be mixed with other resources in a descriptor table. + if (HasSampler && HasOtherRangeType) + return make_error<TableSamplerMixinError>(OtherRangeType, Location); + return Error::success(); +} + +/** This validation logic was extracted from the DXC codebase + * https://github.com/microsoft/DirectXShaderCompiler/blob/7a1b1df9b50a8350a63756720e85196e0285e664/lib/DxilRootSignature/DxilRootSignatureValidator.cpp#L205 + * + * It checks if the registers in a descriptor table are overflowing, meaning, + * they are trying to bind a register larger than MAX_UINT. + * This will usually happen when the descriptor table defined a range after an + * unbounded range, which would lead to an overflow in the register; + * Or if trying append a bunch or really large ranges. + **/ +Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, + uint32_t Location) { + uint64_t AppendingRegister = 0; + + for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { + + dxbc::DescriptorRangeType RangeType = + static_cast<dxbc::DescriptorRangeType>(Range.RangeType); + + uint64_t Register = AppendingRegister; + + // Checks if the current register should be appended to the previous range. + if (Range.OffsetInDescriptorsFromTableStart != ~0U) + Register = Range.OffsetInDescriptorsFromTableStart; + + // Check for overflow in the register value. + if (Register > ~0U) + return make_error<TableRegisterOverflowError>( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + // Is the current range unbounded? + if (Range.NumDescriptors == ~0U) { + // No ranges should be appended to an unbounded range. + AppendingRegister = (uint64_t)~0U + (uint64_t)1ULL; + } else { + // Is the defined range, overflowing? + uint64_t UpperBound = (uint64_t)Range.BaseShaderRegister + + (uint64_t)Range.NumDescriptors - (uint64_t)1U; + if (UpperBound > ~0U) + return make_error<TableRegisterOverflowError>( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + + // If we append this range, will it overflow? + uint64_t AppendingUpperBound = + (uint64_t)Register + (uint64_t)Range.NumDescriptors - (uint64_t)1U; + if (AppendingUpperBound > ~0U) + return make_error<TableRegisterOverflowError>( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + AppendingRegister = Register + Range.NumDescriptors; + } + } + + return Error::success(); +} + Error MetadataParser::validateRootSignature( const mcdxbc::RootSignatureDesc &RSD) { Error DeferredErrs = Error::success(); @@ -609,6 +690,16 @@ Error MetadataParser::validateRootSignature( joinErrors(std::move(DeferredErrs), make_error<RootSignatureValidationError<uint32_t>>( "DescriptorFlag", Range.Flags)); + + if (Error Err = + validateDescriptorTableSamplerMixin(Table, Info.Location)) { + DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err)); + } + + if (Error Err = + validateDescriptorTableRegisterOverflow(Table, Info.Location)) { + DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err)); + } } break; } diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index c9b558a5c62bc..492c0436d0178 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -14,6 +14,7 @@ #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" #include "llvm/BinaryFormat/DXContainer.h" +#include "llvm/Frontend/HLSL/RootSignatureMetadata.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicsDirectX.h" @@ -27,37 +28,6 @@ using namespace llvm; using namespace llvm::dxil; -static ResourceClass toResourceClass(dxbc::DescriptorRangeType RangeType) { - using namespace dxbc; - switch (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; - } -} - -static ResourceClass toResourceClass(dxbc::RootParameterType Type) { - using namespace dxbc; - switch (Type) { - case RootParameterType::Constants32Bit: - return ResourceClass::CBuffer; - case RootParameterType::SRV: - return ResourceClass::SRV; - case RootParameterType::UAV: - return ResourceClass::UAV; - case RootParameterType::CBV: - return ResourceClass::CBuffer; - case dxbc::RootParameterType::DescriptorTable: - break; - } - llvm_unreachable("Unconvertible RootParameterType"); -} - static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) { for (const auto &UAV : DRM.uavs()) { if (UAV.CounterDirection != ResourceCounterDirection::Invalid) @@ -155,33 +125,6 @@ reportRegNotBound(Module &M, ResourceClass Class, M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } -static void -reportDescriptorTableMixingTypes(Module &M, uint32_t Location, - dxbc::DescriptorRangeType RangeType) { - SmallString<128> Message; - raw_svector_ostream OS(Message); - OS << "Samplers cannot be mixed with other " - << "resource types in a descriptor table, " - << getResourceClassName(toResourceClass(RangeType)) - << "(location=" << Location << ")"; - - M.getContext().diagnose(DiagnosticInfoGeneric(Message)); -} - -static void -reportOverflowingRange(Module &M, - const dxbc::RTS0::v2::DescriptorRange &Range) { - SmallString<128> Message; - raw_svector_ostream OS(Message); - OS << "Cannot append range with implicit lower " - << "bound after an unbounded range " - << getResourceClassName(toResourceClass( - static_cast<dxbc::DescriptorRangeType>(Range.RangeType))) - << "(register=" << Range.BaseShaderRegister - << ", space=" << Range.RegisterSpace << ") exceeds maximum allowed value."; - M.getContext().diagnose(DiagnosticInfoGeneric(Message)); -} - static void reportInvalidHandleTy( Module &M, const llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding> &RDs, const iterator_range<SmallVectorImpl<dxil::ResourceInfo>::iterator> @@ -263,66 +206,6 @@ getRootDescriptorsBindingInfo(const mcdxbc::RootSignatureDesc &RSD, return RDs; } -static void validateDescriptorTables(Module &M, - const mcdxbc::RootSignatureDesc &RSD) { - for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) { - if (static_cast<dxbc::RootParameterType>(ParamInfo.Header.ParameterType) != - dxbc::RootParameterType::DescriptorTable) - continue; - - mcdxbc::DescriptorTable Table = - RSD.ParametersContainer.getDescriptorTable(ParamInfo.Location); - - bool HasSampler = false; - bool HasOtherRangeType = false; - dxbc::DescriptorRangeType OtherRangeType; - uint32_t OtherRangeTypeLocation = 0; - - uint64_t AppendingOffset = 0; - - for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { - dxbc::DescriptorRangeType RangeType = - static_cast<dxbc::DescriptorRangeType>(Range.RangeType); - - uint64_t Offset = AppendingOffset; - if (Range.OffsetInDescriptorsFromTableStart != ~0U) - Offset = Range.OffsetInDescriptorsFromTableStart; - - if (Offset > ~0U) - reportOverflowingRange(M, Range); - if (Range.NumDescriptors == ~0U) { - AppendingOffset = (uint64_t)~0U + (uint64_t)1ULL; - } else { - uint64_t UpperBound = (uint64_t)Range.BaseShaderRegister + - (uint64_t)Range.NumDescriptors - (uint64_t)1U; - if (UpperBound > ~0U) - reportOverflowingRange(M, Range); - - uint64_t AppendingUpperBound = - (uint64_t)Offset + (uint64_t)Range.NumDescriptors - (uint64_t)1U; - if (AppendingUpperBound > ~0U) - reportOverflowingRange(M, Range); - AppendingOffset = Offset + Range.NumDescriptors; - } - - if (RangeType == dxbc::DescriptorRangeType::Sampler) { - HasSampler = true; - } else { - HasOtherRangeType = true; - OtherRangeType = RangeType; - OtherRangeTypeLocation = ParamInfo.Location; - } - } - - // Samplers cannot be mixed with other resources in a descriptor table. - if (HasSampler && HasOtherRangeType) { - reportDescriptorTableMixingTypes(M, OtherRangeTypeLocation, - OtherRangeType); - continue; - } - } -} - static void validateRootSignatureBindings(Module &M, const mcdxbc::RootSignatureDesc &RSD, dxil::ModuleMetadataInfo &MMI, @@ -354,10 +237,11 @@ static void validateRootSignatureBindings(Module &M, case dxbc::RootParameterType::CBV: { dxbc::RTS0::v2::RootDescriptor Desc = RSD.ParametersContainer.getRootDescriptor(ParamInfo.Location); - Builder.trackBinding(toResourceClass(static_cast<dxbc::RootParameterType>( - ParamInfo.Header.ParameterType)), - Desc.RegisterSpace, Desc.ShaderRegister, - Desc.ShaderRegister, &IDs.emplace_back()); + Builder.trackBinding( + hlsl::rootsig::toResourceClass(static_cast<dxbc::RootParameterType>( + ParamInfo.Header.ParameterType)), + Desc.RegisterSpace, Desc.ShaderRegister, Desc.ShaderRegister, + &IDs.emplace_back()); break; } @@ -371,7 +255,7 @@ static void validateRootSignatureBindings(Module &M, ? Range.BaseShaderRegister : Range.BaseShaderRegister + Range.NumDescriptors - 1; Builder.trackBinding( - toResourceClass( + hlsl::rootsig::toResourceClass( static_cast<dxbc::DescriptorRangeType>(Range.RangeType)), Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, &IDs.emplace_back()); @@ -439,7 +323,6 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI)) { validateRootSignatureBindings(M, *RSD, MMI, DRM); - validateDescriptorTables(M, *RSD); } } >From ad0e1f3f2539316571d91ca4451b0b467afe631e Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 16:58:24 -0700 Subject: [PATCH 09/11] address comments --- .../Frontend/HLSL/RootSignatureMetadata.h | 79 +++++++++++ .../Frontend/HLSL/RootSignatureMetadata.cpp | 91 ++++++++++++ .../DXILPostOptimizationValidation.cpp | 131 +----------------- 3 files changed, 177 insertions(+), 124 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index 0bd0774641287..308d04a5ee1e9 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -15,9 +15,11 @@ #define LLVM_FRONTEND_HLSL_ROOTSIGNATUREMETADATA_H #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" #include "llvm/IR/Constants.h" #include "llvm/MC/DXContainerRootSignature.h" +#include <cstdint> namespace llvm { class LLVMContext; @@ -27,6 +29,38 @@ class Metadata; namespace hlsl { namespace rootsig { +inline dxil::ResourceClass +toResourceClass(dxbc::DescriptorRangeType RangeType) { + using namespace dxbc; + switch (RangeType) { + case DescriptorRangeType::SRV: + return dxil::ResourceClass::SRV; + case DescriptorRangeType::UAV: + return dxil::ResourceClass::UAV; + case DescriptorRangeType::CBV: + return dxil::ResourceClass::CBuffer; + case DescriptorRangeType::Sampler: + return dxil::ResourceClass::Sampler; + } +} + +inline dxil::ResourceClass toResourceClass(dxbc::RootParameterType Type) { + using namespace dxbc; + switch (Type) { + case RootParameterType::Constants32Bit: + return dxil::ResourceClass::CBuffer; + case RootParameterType::SRV: + return dxil::ResourceClass::SRV; + case RootParameterType::UAV: + return dxil::ResourceClass::UAV; + case RootParameterType::CBV: + return dxil::ResourceClass::CBuffer; + case dxbc::RootParameterType::DescriptorTable: + break; + } + llvm_unreachable("Unconvertible RootParameterType"); +} + template <typename T> class RootSignatureValidationError : public ErrorInfo<RootSignatureValidationError<T>> { @@ -47,6 +81,51 @@ class RootSignatureValidationError } }; +class TableRegisterOverflowError + : public ErrorInfo<TableRegisterOverflowError> { +public: + static char ID; + dxbc::DescriptorRangeType Type; + uint32_t Register; + uint32_t Space; + + TableRegisterOverflowError(dxbc::DescriptorRangeType Type, uint32_t Register, + uint32_t Space) + : Type(Type), Register(Register), Space(Space) {} + + void log(raw_ostream &OS) const override { + OS << "Cannot bind resource of type " + << getResourceClassName(toResourceClass(Type)) + << "(register=" << Register << ", space=" << Space + << "), it exceeds the maximum allowed register value."; + } + + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; + +class TableSamplerMixinError : public ErrorInfo<TableSamplerMixinError> { +public: + static char ID; + dxbc::DescriptorRangeType Type; + uint32_t Location; + + TableSamplerMixinError(dxbc::DescriptorRangeType Type, uint32_t Location) + : Type(Type), Location(Location) {} + + void log(raw_ostream &OS) const override { + OS << "Samplers cannot be mixed with other " + << "resource types in a descriptor table, " + << getResourceClassName(toResourceClass(Type)) + << "(location=" << Location << ")"; + } + + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; + class GenericRSMetadataError : public ErrorInfo<GenericRSMetadataError> { public: static char ID; diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 6d89fa7b1222c..3878026518882 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -15,7 +15,9 @@ #include "llvm/Frontend/HLSL/RootSignatureValidations.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Metadata.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ScopedPrinter.h" +#include <cstdint> using namespace llvm; @@ -26,6 +28,8 @@ namespace rootsig { char GenericRSMetadataError::ID; char InvalidRSMetadataFormat::ID; char InvalidRSMetadataValue::ID; +char TableSamplerMixinError::ID; +char TableRegisterOverflowError::ID; template <typename T> char RootSignatureValidationError<T>::ID; static std::optional<uint32_t> extractMdIntValue(MDNode *Node, @@ -525,6 +529,83 @@ Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD, llvm_unreachable("Unhandled RootSignatureElementKind enum."); } +Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, + uint32_t Location) { + bool HasSampler = false; + bool HasOtherRangeType = false; + dxbc::DescriptorRangeType OtherRangeType; + + for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { + dxbc::DescriptorRangeType RangeType = + static_cast<dxbc::DescriptorRangeType>(Range.RangeType); + + if (RangeType == dxbc::DescriptorRangeType::Sampler) { + HasSampler = true; + } else { + HasOtherRangeType = true; + OtherRangeType = RangeType; + } + } + + // Samplers cannot be mixed with other resources in a descriptor table. + if (HasSampler && HasOtherRangeType) + return make_error<TableSamplerMixinError>(OtherRangeType, Location); + return Error::success(); +} + +/** This validation logic was extracted from the DXC codebase + * https://github.com/microsoft/DirectXShaderCompiler/blob/7a1b1df9b50a8350a63756720e85196e0285e664/lib/DxilRootSignature/DxilRootSignatureValidator.cpp#L205 + * + * It checks if the registers in a descriptor table are overflowing, meaning, + * they are trying to bind a register larger than MAX_UINT. + * This will usually happen when the descriptor table defined a range after an + * unbounded range, which would lead to an overflow in the register; + * Or if trying append a bunch or really large ranges. + **/ +Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, + uint32_t Location) { + uint64_t AppendingRegister = 0; + + for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { + + dxbc::DescriptorRangeType RangeType = + static_cast<dxbc::DescriptorRangeType>(Range.RangeType); + + uint64_t Register = AppendingRegister; + + // Checks if the current register should be appended to the previous range. + if (Range.OffsetInDescriptorsFromTableStart != ~0U) + Register = Range.OffsetInDescriptorsFromTableStart; + + // Check for overflow in the register value. + if (Register > ~0U) + return make_error<TableRegisterOverflowError>( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + // Is the current range unbounded? + if (Range.NumDescriptors == ~0U) { + // No ranges should be appended to an unbounded range. + AppendingRegister = (uint64_t)~0U + (uint64_t)1ULL; + } else { + // Is the defined range, overflowing? + uint64_t UpperBound = (uint64_t)Range.BaseShaderRegister + + (uint64_t)Range.NumDescriptors - (uint64_t)1U; + if (UpperBound > ~0U) + return make_error<TableRegisterOverflowError>( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + + // If we append this range, will it overflow? + uint64_t AppendingUpperBound = + (uint64_t)Register + (uint64_t)Range.NumDescriptors - (uint64_t)1U; + if (AppendingUpperBound > ~0U) + return make_error<TableRegisterOverflowError>( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + AppendingRegister = Register + Range.NumDescriptors; + } + } + + return Error::success(); +} + Error MetadataParser::validateRootSignature( const mcdxbc::RootSignatureDesc &RSD) { Error DeferredErrs = Error::success(); @@ -609,6 +690,16 @@ Error MetadataParser::validateRootSignature( joinErrors(std::move(DeferredErrs), make_error<RootSignatureValidationError<uint32_t>>( "DescriptorFlag", Range.Flags)); + + if (Error Err = + validateDescriptorTableSamplerMixin(Table, Info.Location)) { + DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err)); + } + + if (Error Err = + validateDescriptorTableRegisterOverflow(Table, Info.Location)) { + DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err)); + } } break; } diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index c9b558a5c62bc..492c0436d0178 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -14,6 +14,7 @@ #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" #include "llvm/BinaryFormat/DXContainer.h" +#include "llvm/Frontend/HLSL/RootSignatureMetadata.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicsDirectX.h" @@ -27,37 +28,6 @@ using namespace llvm; using namespace llvm::dxil; -static ResourceClass toResourceClass(dxbc::DescriptorRangeType RangeType) { - using namespace dxbc; - switch (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; - } -} - -static ResourceClass toResourceClass(dxbc::RootParameterType Type) { - using namespace dxbc; - switch (Type) { - case RootParameterType::Constants32Bit: - return ResourceClass::CBuffer; - case RootParameterType::SRV: - return ResourceClass::SRV; - case RootParameterType::UAV: - return ResourceClass::UAV; - case RootParameterType::CBV: - return ResourceClass::CBuffer; - case dxbc::RootParameterType::DescriptorTable: - break; - } - llvm_unreachable("Unconvertible RootParameterType"); -} - static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) { for (const auto &UAV : DRM.uavs()) { if (UAV.CounterDirection != ResourceCounterDirection::Invalid) @@ -155,33 +125,6 @@ reportRegNotBound(Module &M, ResourceClass Class, M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } -static void -reportDescriptorTableMixingTypes(Module &M, uint32_t Location, - dxbc::DescriptorRangeType RangeType) { - SmallString<128> Message; - raw_svector_ostream OS(Message); - OS << "Samplers cannot be mixed with other " - << "resource types in a descriptor table, " - << getResourceClassName(toResourceClass(RangeType)) - << "(location=" << Location << ")"; - - M.getContext().diagnose(DiagnosticInfoGeneric(Message)); -} - -static void -reportOverflowingRange(Module &M, - const dxbc::RTS0::v2::DescriptorRange &Range) { - SmallString<128> Message; - raw_svector_ostream OS(Message); - OS << "Cannot append range with implicit lower " - << "bound after an unbounded range " - << getResourceClassName(toResourceClass( - static_cast<dxbc::DescriptorRangeType>(Range.RangeType))) - << "(register=" << Range.BaseShaderRegister - << ", space=" << Range.RegisterSpace << ") exceeds maximum allowed value."; - M.getContext().diagnose(DiagnosticInfoGeneric(Message)); -} - static void reportInvalidHandleTy( Module &M, const llvm::ArrayRef<dxil::ResourceInfo::ResourceBinding> &RDs, const iterator_range<SmallVectorImpl<dxil::ResourceInfo>::iterator> @@ -263,66 +206,6 @@ getRootDescriptorsBindingInfo(const mcdxbc::RootSignatureDesc &RSD, return RDs; } -static void validateDescriptorTables(Module &M, - const mcdxbc::RootSignatureDesc &RSD) { - for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) { - if (static_cast<dxbc::RootParameterType>(ParamInfo.Header.ParameterType) != - dxbc::RootParameterType::DescriptorTable) - continue; - - mcdxbc::DescriptorTable Table = - RSD.ParametersContainer.getDescriptorTable(ParamInfo.Location); - - bool HasSampler = false; - bool HasOtherRangeType = false; - dxbc::DescriptorRangeType OtherRangeType; - uint32_t OtherRangeTypeLocation = 0; - - uint64_t AppendingOffset = 0; - - for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { - dxbc::DescriptorRangeType RangeType = - static_cast<dxbc::DescriptorRangeType>(Range.RangeType); - - uint64_t Offset = AppendingOffset; - if (Range.OffsetInDescriptorsFromTableStart != ~0U) - Offset = Range.OffsetInDescriptorsFromTableStart; - - if (Offset > ~0U) - reportOverflowingRange(M, Range); - if (Range.NumDescriptors == ~0U) { - AppendingOffset = (uint64_t)~0U + (uint64_t)1ULL; - } else { - uint64_t UpperBound = (uint64_t)Range.BaseShaderRegister + - (uint64_t)Range.NumDescriptors - (uint64_t)1U; - if (UpperBound > ~0U) - reportOverflowingRange(M, Range); - - uint64_t AppendingUpperBound = - (uint64_t)Offset + (uint64_t)Range.NumDescriptors - (uint64_t)1U; - if (AppendingUpperBound > ~0U) - reportOverflowingRange(M, Range); - AppendingOffset = Offset + Range.NumDescriptors; - } - - if (RangeType == dxbc::DescriptorRangeType::Sampler) { - HasSampler = true; - } else { - HasOtherRangeType = true; - OtherRangeType = RangeType; - OtherRangeTypeLocation = ParamInfo.Location; - } - } - - // Samplers cannot be mixed with other resources in a descriptor table. - if (HasSampler && HasOtherRangeType) { - reportDescriptorTableMixingTypes(M, OtherRangeTypeLocation, - OtherRangeType); - continue; - } - } -} - static void validateRootSignatureBindings(Module &M, const mcdxbc::RootSignatureDesc &RSD, dxil::ModuleMetadataInfo &MMI, @@ -354,10 +237,11 @@ static void validateRootSignatureBindings(Module &M, case dxbc::RootParameterType::CBV: { dxbc::RTS0::v2::RootDescriptor Desc = RSD.ParametersContainer.getRootDescriptor(ParamInfo.Location); - Builder.trackBinding(toResourceClass(static_cast<dxbc::RootParameterType>( - ParamInfo.Header.ParameterType)), - Desc.RegisterSpace, Desc.ShaderRegister, - Desc.ShaderRegister, &IDs.emplace_back()); + Builder.trackBinding( + hlsl::rootsig::toResourceClass(static_cast<dxbc::RootParameterType>( + ParamInfo.Header.ParameterType)), + Desc.RegisterSpace, Desc.ShaderRegister, Desc.ShaderRegister, + &IDs.emplace_back()); break; } @@ -371,7 +255,7 @@ static void validateRootSignatureBindings(Module &M, ? Range.BaseShaderRegister : Range.BaseShaderRegister + Range.NumDescriptors - 1; Builder.trackBinding( - toResourceClass( + hlsl::rootsig::toResourceClass( static_cast<dxbc::DescriptorRangeType>(Range.RangeType)), Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, &IDs.emplace_back()); @@ -439,7 +323,6 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI)) { validateRootSignatureBindings(M, *RSD, MMI, DRM); - validateDescriptorTables(M, *RSD); } } >From 8a4ee3c7077e216aadc94749a8ba2adf9e05a822 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 17:12:04 -0700 Subject: [PATCH 10/11] fix comment --- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 3878026518882..dd183b6446a48 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -558,9 +558,8 @@ Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, * * It checks if the registers in a descriptor table are overflowing, meaning, * they are trying to bind a register larger than MAX_UINT. - * This will usually happen when the descriptor table defined a range after an - * unbounded range, which would lead to an overflow in the register; - * Or if trying append a bunch or really large ranges. + * This will usually happen when the descriptor table appends a resource + * after an unbounded range. **/ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, uint32_t Location) { >From 23537b5fb06ea9eeef2fee0db4fa135ed301146e Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 13:31:49 -0700 Subject: [PATCH 11/11] addressing comment --- llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h | 6 +++--- .../rootsignature-validation-fail-appending-overflow.ll | 4 +--- .../rootsignature-validation-fail-register-overflow.ll | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index 036b07f0d4b58..2a9644fff1923 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -93,10 +93,10 @@ class TableRegisterOverflowError : Type(Type), Register(Register), Space(Space) {} void log(raw_ostream &OS) const override { - OS << "Cannot bind resource of type " + OS << "Cannot append range with implicit lower bound after an unbounded " + "range " << getResourceClassName(toResourceClass(Type)) - << "(register=" << Register << ", space=" << Space - << "), it exceeds the maximum allowed register value."; + << "(register=" << Register << ", space=" << Space << ")."; } std::error_code convertToErrorCode() const override { diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll index 93d6cb4c17f50..2b5ce4f52b94e 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll @@ -1,7 +1,7 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s ; This test check if a resource is implicitly overflowing. That means, it is appending a resource after an unbounded range. -; CHECK: error: Cannot bind resource of type UAV(register=0, space=0), it exceeds the maximum allowed register value. +; CHECK: error: Cannot append range with implicit lower bound after an unbounded range UAV(register=0, space=0). @TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 @@ -17,5 +17,3 @@ entry: !3 = !{!"DescriptorTable", i32 0, !4, !5} !4 = !{!"UAV", i32 -1, i32 1, i32 0, i32 2, i32 0} !5 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0} - - diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll index 632d5ca7978f3..65542a6ca98f2 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll @@ -1,5 +1,5 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s -; CHECK: error: Cannot bind resource of type UAV(register=4294967295, space=0), it exceeds the maximum allowed register value. +; CHECK: error: Cannot append range with implicit lower bound after an unbounded range UAV(register=4294967295, space=0). @TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 define void @CSMain() "hlsl.shader"="compute" { @@ -13,4 +13,3 @@ entry: !1 = !{!3} !3 = !{!"DescriptorTable", i32 0, !4} !4 = !{!"UAV", i32 100, i32 4294967295, i32 0, i32 -1, i32 0} - _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits