https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/147573
>From 01a558be2b36a6bb00e1027c4d042c7bacd4ed5a Mon Sep 17 00:00:00 2001 From: joaosaffran <joao.saff...@microsoft.com> Date: Mon, 7 Jul 2025 19:26:24 +0000 Subject: [PATCH 1/7] add validation --- .../DXILPostOptimizationValidation.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index a52a04323514c..1a57cd56f8eef 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" +#include "llvm/Support/Casting.h" #define DEBUG_TYPE "dxil-post-optimization-validation" @@ -85,6 +86,16 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } +static void reportTextureBoundInRs(Module &M, Twine Type, + ResourceInfo::ResourceBinding Binding) { + SmallString<128> Message; + raw_svector_ostream OS(Message); + OS << "register " << Type << " (space=" << Binding.Space + << ", register=" << Binding.LowerBound << ")" + << " is bound to a texture."; + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); +} + static void reportRegNotBound(Module &M, Twine Type, ResourceInfo::ResourceBinding Binding) { SmallString<128> Message; @@ -155,24 +166,40 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, for (const ResourceInfo &CBuf : DRM.cbuffers()) { ResourceInfo::ResourceBinding Binding = CBuf.getBinding(); + + if (auto *TB = dyn_cast<TextureExtType>(CBuf.getHandleTy())) + reportTextureBoundInRs(M, "cbuffer", Binding); + if (!Validation.checkCRegBinding(Binding)) reportRegNotBound(M, "cbuffer", Binding); } for (const ResourceInfo &SRV : DRM.srvs()) { ResourceInfo::ResourceBinding Binding = SRV.getBinding(); + + if (auto *TB = dyn_cast<TextureExtType>(SRV.getHandleTy())) + reportTextureBoundInRs(M, "srv", Binding); + if (!Validation.checkTRegBinding(Binding)) reportRegNotBound(M, "srv", Binding); } for (const ResourceInfo &UAV : DRM.uavs()) { ResourceInfo::ResourceBinding Binding = UAV.getBinding(); + + if (auto *TB = dyn_cast<TextureExtType>(UAV.getHandleTy())) + reportTextureBoundInRs(M, "uav", Binding); + if (!Validation.checkURegBinding(Binding)) reportRegNotBound(M, "uav", Binding); } for (const ResourceInfo &Sampler : DRM.samplers()) { ResourceInfo::ResourceBinding Binding = Sampler.getBinding(); + + if (auto *TB = dyn_cast<TextureExtType>(Sampler.getHandleTy())) + reportTextureBoundInRs(M, "sampler", Binding); + if (!Validation.checkSamplerBinding(Binding)) reportRegNotBound(M, "sampler", Binding); } >From 43eb04ecebd44ec86a688abc9f067db0dfce2620 Mon Sep 17 00:00:00 2001 From: joaosaffran <joao.saff...@microsoft.com> Date: Tue, 8 Jul 2025 02:01:02 +0000 Subject: [PATCH 2/7] adding validation --- .../RootSignature-Validation-Textures.hlsl | 13 ++++++++ .../SemaHLSL/RootSignature-Validation.hlsl | 6 ++-- .../DXILPostOptimizationValidation.cpp | 33 ++++++++++--------- 3 files changed, 34 insertions(+), 18 deletions(-) create mode 100644 clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl new file mode 100644 index 0000000000000..9daf38e30dd67 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl @@ -0,0 +1,13 @@ +// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s + +// CHECK: error: register srv (space=0, register=0) is bound to a texture or typed buffer. + +RWStructuredBuffer<int> Out : register(u0); +Buffer<float> B : register(t0); +// Compute Shader for UAV testing +[numthreads(8, 8, 1)] +[RootSignature("SRV(t0), UAV(u0)")] +void CSMain(uint id : SV_GroupID) +{ + Out[0] = B[0]; +} diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl index 5a7f5baf00619..c4ea897c6f490 100644 --- a/clang/test/SemaHLSL/RootSignature-Validation.hlsl +++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl @@ -16,11 +16,11 @@ cbuffer CB : register(b3, space1) { StructuredBuffer<int> In : register(t0, space0); RWStructuredBuffer<int> Out : register(u0); -RWBuffer<float> UAV : register(u4294967294); +RWStructuredBuffer<float> UAV : register(u4294967294); -RWBuffer<float> UAV1 : register(u2), UAV2 : register(u4); +RWStructuredBuffer<float> UAV1 : register(u2), UAV2 : register(u4); -RWBuffer<float> UAV3 : register(space0); +RWStructuredBuffer<float> UAV3 : register(space0); diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 1a57cd56f8eef..13ac6a28d44f7 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -86,13 +86,14 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } -static void reportTextureBoundInRs(Module &M, Twine Type, - ResourceInfo::ResourceBinding Binding) { +static void +reportInvalidHandleTyBoundInRs(Module &M, Twine Type, + ResourceInfo::ResourceBinding Binding) { SmallString<128> Message; raw_svector_ostream OS(Message); OS << "register " << Type << " (space=" << Binding.Space << ", register=" << Binding.LowerBound << ")" - << " is bound to a texture."; + << " is bound to a texture or typed buffer."; M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } @@ -167,9 +168,6 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, for (const ResourceInfo &CBuf : DRM.cbuffers()) { ResourceInfo::ResourceBinding Binding = CBuf.getBinding(); - if (auto *TB = dyn_cast<TextureExtType>(CBuf.getHandleTy())) - reportTextureBoundInRs(M, "cbuffer", Binding); - if (!Validation.checkCRegBinding(Binding)) reportRegNotBound(M, "cbuffer", Binding); } @@ -177,29 +175,34 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, for (const ResourceInfo &SRV : DRM.srvs()) { ResourceInfo::ResourceBinding Binding = SRV.getBinding(); - if (auto *TB = dyn_cast<TextureExtType>(SRV.getHandleTy())) - reportTextureBoundInRs(M, "srv", Binding); - if (!Validation.checkTRegBinding(Binding)) reportRegNotBound(M, "srv", Binding); + else { + const auto *Handle = + dyn_cast_or_null<RawBufferExtType>(SRV.getHandleTy()); + + if (!Handle) + reportInvalidHandleTyBoundInRs(M, "srv", Binding); + } } for (const ResourceInfo &UAV : DRM.uavs()) { ResourceInfo::ResourceBinding Binding = UAV.getBinding(); - if (auto *TB = dyn_cast<TextureExtType>(UAV.getHandleTy())) - reportTextureBoundInRs(M, "uav", Binding); - if (!Validation.checkURegBinding(Binding)) reportRegNotBound(M, "uav", Binding); + else { + const auto *Handle = + dyn_cast_or_null<RawBufferExtType>(UAV.getHandleTy()); + + if (!Handle) + reportInvalidHandleTyBoundInRs(M, "srv", Binding); + } } for (const ResourceInfo &Sampler : DRM.samplers()) { ResourceInfo::ResourceBinding Binding = Sampler.getBinding(); - if (auto *TB = dyn_cast<TextureExtType>(Sampler.getHandleTy())) - reportTextureBoundInRs(M, "sampler", Binding); - if (!Validation.checkSamplerBinding(Binding)) reportRegNotBound(M, "sampler", Binding); } >From d7b4cf44541866a47160ac005e85223b3b7b076d Mon Sep 17 00:00:00 2001 From: joaosaffran <joao.saff...@microsoft.com> Date: Tue, 8 Jul 2025 17:06:19 +0000 Subject: [PATCH 3/7] format --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 13ac6a28d44f7..c34f31fbe35e5 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -18,7 +18,6 @@ #include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" -#include "llvm/Support/Casting.h" #define DEBUG_TYPE "dxil-post-optimization-validation" @@ -167,14 +166,12 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, for (const ResourceInfo &CBuf : DRM.cbuffers()) { ResourceInfo::ResourceBinding Binding = CBuf.getBinding(); - if (!Validation.checkCRegBinding(Binding)) reportRegNotBound(M, "cbuffer", Binding); } for (const ResourceInfo &SRV : DRM.srvs()) { ResourceInfo::ResourceBinding Binding = SRV.getBinding(); - if (!Validation.checkTRegBinding(Binding)) reportRegNotBound(M, "srv", Binding); else { @@ -188,7 +185,6 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, for (const ResourceInfo &UAV : DRM.uavs()) { ResourceInfo::ResourceBinding Binding = UAV.getBinding(); - if (!Validation.checkURegBinding(Binding)) reportRegNotBound(M, "uav", Binding); else { @@ -202,7 +198,6 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, for (const ResourceInfo &Sampler : DRM.samplers()) { ResourceInfo::ResourceBinding Binding = Sampler.getBinding(); - if (!Validation.checkSamplerBinding(Binding)) reportRegNotBound(M, "sampler", Binding); } >From aea75dac9df35611a5e8d46be8091621985e8ca7 Mon Sep 17 00:00:00 2001 From: joaosaffran <joao.saff...@microsoft.com> Date: Tue, 8 Jul 2025 20:51:49 +0000 Subject: [PATCH 4/7] fix test --- .../rootsignature-validation-textures.ll | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll new file mode 100644 index 0000000000000..8c407fdd60205 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll @@ -0,0 +1,87 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 +; CHECK: error: register srv (space=0, register=0) is bound to a texture or typed buffer. + +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- --------- +; B texture f32 buf T0 t0 1 +; Out UAV struct r/w U0 u0 1 +; +; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl' +target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" +target triple = "dxilv1.5-unknown-shadermodel6.5-compute" + +%"Buffer<float>" = type { float } +%"RWStructuredBuffer<int32_t>" = type { i32 } + +@.str = private unnamed_addr constant [4 x i8] c"Out\00", align 1 +@.str.2 = private unnamed_addr constant [2 x i8] c"B\00", align 1 +@B = external constant %"Buffer<float>" +@Out = external constant %"RWStructuredBuffer<int32_t>" + +; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) +define void @CSMain() local_unnamed_addr #0 { +entry: + %0 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str) + %1 = tail call target("dx.TypedBuffer", float, 0, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_0_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str.2) + %2 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %1, i32 0) + %3 = extractvalue { float, i1 } %2, 0 + %conv.i = fptosi float %3 to i32 + call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0) %0, i32 0, i32 0, i32 %conv.i) + ret void +} + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32, i32, i32, i32, i1, ptr) #1 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare target("dx.TypedBuffer", float, 0, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_0_0_0t(i32, i32, i32, i32, i1, ptr) #1 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0), i32) #1 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32) #1 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) +declare { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32) #2 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(write) +declare void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0), i32, i32, i32) #3 + +attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="true" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) } +attributes #2 = { nocallback nofree nosync nounwind willreturn memory(read) } +attributes #3 = { nocallback nofree nosync nounwind willreturn memory(write) } + +!dx.rootsignatures = !{!0} +!llvm.module.flags = !{!4, !5} +!dx.valver = !{!6} +!llvm.ident = !{!7} +!dx.shaderModel = !{!8} +!dx.version = !{!9} +!dx.resources = !{!10} +!dx.entryPoints = !{!17} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3} +!2 = !{!"RootSRV", i32 0, i32 0, i32 0, i32 4} +!3 = !{!"RootUAV", i32 0, i32 0, i32 0, i32 2} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 7, !"frame-pointer", i32 2} +!6 = !{i32 1, i32 8} +!7 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"} +!8 = !{!"cs", i32 6, i32 5} +!9 = !{i32 1, i32 5} +!10 = !{!11, !14, null, null} +!11 = !{!12} +!12 = !{i32 0, ptr @B, !"B", i32 0, i32 0, i32 1, i32 10, i32 0, !13} +!13 = !{i32 0, i32 9} +!14 = !{!15} +!15 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !16} +!16 = !{i32 1, i32 4} +!17 = !{ptr @CSMain, !"CSMain", null, !10, !18} +!18 = !{i32 0, i64 16, i32 4, !19} +!19 = !{i32 8, i32 8, i32 1} >From 5af919957fbe8dd2617ffb8452ef7aa65309a886 Mon Sep 17 00:00:00 2001 From: joaosaffran <joao.saff...@microsoft.com> Date: Mon, 14 Jul 2025 23:32:44 +0000 Subject: [PATCH 5/7] update --- .../DXILPostOptimizationValidation.cpp | 49 +++++++++++++++++++ .../rootsignature-validation-textures-fail.ll | 31 ++++++++++++ .../DirectX/rootsignature-validation.ll | 30 +++--------- 3 files changed, 86 insertions(+), 24 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index c34f31fbe35e5..06f917867987a 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -13,11 +13,13 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" +#include "llvm/Support/Casting.h" #define DEBUG_TYPE "dxil-post-optimization-validation" @@ -90,7 +92,11 @@ reportInvalidHandleTyBoundInRs(Module &M, Twine Type, ResourceInfo::ResourceBinding Binding) { SmallString<128> Message; raw_svector_ostream OS(Message); +<<<<<<< Updated upstream OS << "register " << Type << " (space=" << Binding.Space +======= + OS << "resource " << Type << " at register (space=" << Binding.Space +>>>>>>> Stashed changes << ", register=" << Binding.LowerBound << ")" << " is bound to a texture or typed buffer."; M.getContext().diagnose(DiagnosticInfoGeneric(Message)); @@ -146,6 +152,37 @@ getRootSignature(RootSignatureBindingInfo &RSBI, return RootSigDesc; } +<<<<<<< Updated upstream +======= +static void reportInvalidRegistersBinding( + Module &M, + const std::vector<llvm::dxil::ResourceInfo::ResourceBinding> &Bindings, + iterator_range<SmallVector<dxil::ResourceInfo>::iterator> &Resources) { + for (auto Res = Resources.begin(), End = Resources.end(); Res != End; Res++) { + bool Bound = false; + ResourceInfo::ResourceBinding ResBinding = Res->getBinding(); + for (const auto &Binding : Bindings) { + if (ResBinding.Space == Binding.Space && + ResBinding.LowerBound >= Binding.LowerBound && + ResBinding.LowerBound < Binding.LowerBound + Binding.Size) { + Bound = true; + break; + } + } + if (!Bound) { + reportRegNotBound(M, Res->getName(), Res->getBinding()); + } else { + TargetExtType *Handle = Res->getHandleTy(); + auto *TypedBuffer = dyn_cast_or_null<TypedBufferExtType>(Handle); + auto *Texture = dyn_cast_or_null<TextureExtType>(Handle); + + if (TypedBuffer != nullptr || Texture != nullptr) + reportInvalidHandleTyBoundInRs(M, Res->getName(), Res->getBinding()); + } + } +} + +>>>>>>> Stashed changes static void reportErrors(Module &M, DXILResourceMap &DRM, DXILResourceBindingInfo &DRBI, RootSignatureBindingInfo &RSBI, @@ -170,6 +207,7 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, reportRegNotBound(M, "cbuffer", Binding); } +<<<<<<< Updated upstream for (const ResourceInfo &SRV : DRM.srvs()) { ResourceInfo::ResourceBinding Binding = SRV.getBinding(); if (!Validation.checkTRegBinding(Binding)) @@ -201,6 +239,17 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, if (!Validation.checkSamplerBinding(Binding)) reportRegNotBound(M, "sampler", Binding); } +======= + reportInvalidRegistersBinding( + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), Cbufs); + reportInvalidRegistersBinding( + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), UAVs); + reportInvalidRegistersBinding( + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler), + Samplers); + reportInvalidRegistersBinding( + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), SRVs); +>>>>>>> Stashed changes } } } // namespace 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..4f4015702b713 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll @@ -0,0 +1,31 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s +; CHECK: error: resource TB at register (space=0, register=0) is bound to a texture or typed buffer. + + +; Root Signature( +; CBV(b3, space=1, visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX) +; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) + +@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.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @TB.str) + + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3, !5, !7} +!2 = !{!"RootCBV", i32 0, i32 3, i32 1, i32 4} +!3 = !{!"DescriptorTable", i32 0, !4} +!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 0} +!5 = !{!"DescriptorTable", i32 0, !6} +!6 = !{!"Sampler", i32 5, i32 3, i32 2, i32 -1, i32 0} +!7 = !{!"DescriptorTable", i32 0, !8} +!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll index eaf8512c284a7..b8515506c8853 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -43,30 +43,12 @@ declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx ; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) define void @CSMain() local_unnamed_addr #1 { entry: - %CB.cb_h.i.i = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32 1, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str) - store target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, ptr @CB.cb, align 4 - %0 = tail call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str) - %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str.2) - %2 = tail call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 -2, i32 1, i32 0, i1 false, ptr nonnull @.str.4) - %3 = tail call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @.str.6) - %4 = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 1, i32 1, i32 0, i1 false, ptr @.str.10) - %5 = call { float, float, float, float } @llvm.dx.resource.load.cbufferrow.4.f32.f32.f32.f32.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) %CB.cb_h.i.i, i32 0) - %6 = extractvalue { float, float, float, float } %5, 0 - %7 = call { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0) %0, i32 0, i32 0) - %8 = extractvalue { i32, i1 } %7, 0 - %conv.i = sitofp i32 %8 to float - %add.i = fadd reassoc nnan ninf nsz arcp afn float %6, %conv.i - %9 = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %2, i32 0, i32 0) - %10 = extractvalue { float, i1 } %9, 0 - %add2.i = fadd reassoc nnan ninf nsz arcp afn float %add.i, %10 - %11 = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %3, i32 0, i32 0) - %12 = extractvalue { float, i1 } %11, 0 - %add4.i = fadd reassoc nnan ninf nsz arcp afn float %add2.i, %12 - %13 = call { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0) %4, i32 0, i32 0) - %14 = extractvalue { float, i1 } %13, 0 - %add6.i = fadd reassoc nnan ninf nsz arcp afn float %add4.i, %14 - %conv7.i = fptosi float %add6.i to i32 - call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0) %1, i32 0, i32 0, i32 %conv7.i) + + %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 1, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str) + %Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str) + %SB = tail call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @SB.str) + %RWB = tail call target("dx.RawBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @RWB.str) + ret void } >From 91ff1bf501ec158422102f10875c11cbe8d55f5c Mon Sep 17 00:00:00 2001 From: joaosaffran <joao.saff...@microsoft.com> Date: Tue, 15 Jul 2025 00:21:44 +0000 Subject: [PATCH 6/7] clean up --- .../DXILPostOptimizationValidation.cpp | 2 - .../rootsignature-validation-textures.ll | 87 ------------------- 2 files changed, 89 deletions(-) delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 91605b7ba9943..7fefdb65a75d9 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -12,13 +12,11 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" -#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" -#include "llvm/Support/Casting.h" #define DEBUG_TYPE "dxil-post-optimization-validation" diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll deleted file mode 100644 index 8c407fdd60205..0000000000000 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll +++ /dev/null @@ -1,87 +0,0 @@ -; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 -; CHECK: error: register srv (space=0, register=0) is bound to a texture or typed buffer. - -; -; Resource Bindings: -; -; Name Type Format Dim ID HLSL Bind Count -; ------------------------------ ---------- ------- ----------- ------- -------------- --------- -; B texture f32 buf T0 t0 1 -; Out UAV struct r/w U0 u0 1 -; -; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation-Textures.hlsl' -target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" -target triple = "dxilv1.5-unknown-shadermodel6.5-compute" - -%"Buffer<float>" = type { float } -%"RWStructuredBuffer<int32_t>" = type { i32 } - -@.str = private unnamed_addr constant [4 x i8] c"Out\00", align 1 -@.str.2 = private unnamed_addr constant [2 x i8] c"B\00", align 1 -@B = external constant %"Buffer<float>" -@Out = external constant %"RWStructuredBuffer<int32_t>" - -; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) -define void @CSMain() local_unnamed_addr #0 { -entry: - %0 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str) - %1 = tail call target("dx.TypedBuffer", float, 0, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_0_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str.2) - %2 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %1, i32 0) - %3 = extractvalue { float, i1 } %2, 0 - %conv.i = fptosi float %3 to i32 - call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0) %0, i32 0, i32 0, i32 %conv.i) - ret void -} - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_1_0t(i32, i32, i32, i32, i1, ptr) #1 - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare target("dx.TypedBuffer", float, 0, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_0_0_0t(i32, i32, i32, i32, i1, ptr) #1 - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0), i32) #1 - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32) #1 - -; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) -declare { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0), i32) #2 - -; Function Attrs: nocallback nofree nosync nounwind willreturn memory(write) -declare void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_i32_1_0t.i32(target("dx.RawBuffer", i32, 1, 0), i32, i32, i32) #3 - -attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="true" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) } -attributes #2 = { nocallback nofree nosync nounwind willreturn memory(read) } -attributes #3 = { nocallback nofree nosync nounwind willreturn memory(write) } - -!dx.rootsignatures = !{!0} -!llvm.module.flags = !{!4, !5} -!dx.valver = !{!6} -!llvm.ident = !{!7} -!dx.shaderModel = !{!8} -!dx.version = !{!9} -!dx.resources = !{!10} -!dx.entryPoints = !{!17} - -!0 = !{ptr @CSMain, !1, i32 2} -!1 = !{!2, !3} -!2 = !{!"RootSRV", i32 0, i32 0, i32 0, i32 4} -!3 = !{!"RootUAV", i32 0, i32 0, i32 0, i32 2} -!4 = !{i32 1, !"wchar_size", i32 4} -!5 = !{i32 7, !"frame-pointer", i32 2} -!6 = !{i32 1, i32 8} -!7 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"} -!8 = !{!"cs", i32 6, i32 5} -!9 = !{i32 1, i32 5} -!10 = !{!11, !14, null, null} -!11 = !{!12} -!12 = !{i32 0, ptr @B, !"B", i32 0, i32 0, i32 1, i32 10, i32 0, !13} -!13 = !{i32 0, i32 9} -!14 = !{!15} -!15 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !16} -!16 = !{i32 1, i32 4} -!17 = !{ptr @CSMain, !"CSMain", null, !10, !18} -!18 = !{i32 0, i64 16, i32 4, !19} -!19 = !{i32 8, i32 8, i32 1} >From 9f3888ead4ed2934400cbf4ef3b92bdccc56645b Mon Sep 17 00:00:00 2001 From: joaosaffran <joao.saff...@microsoft.com> Date: Tue, 15 Jul 2025 18:17:45 +0000 Subject: [PATCH 7/7] adding root constants --- .../DXILPostOptimizationValidation.cpp | 18 +++++++++++++++ .../rootsignature-validation-constants.ll | 22 +++++++++++++++++++ ...rootsignature-validation-fail-constants.ll | 22 +++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index c01f52e07d230..eb3ad6a6e56ee 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/IR/DiagnosticInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicsDirectX.h" @@ -153,6 +155,22 @@ initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, continue; switch (Type) { + case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): { + dxbc::RTS0::v1::RootConstants Const = + RSD.ParametersContainer.getConstant(Loc); + + llvm::dxil::ResourceInfo::ResourceBinding Binding; + Binding.LowerBound = Const.ShaderRegister; + Binding.Space = Const.RegisterSpace; + Binding.Size = 1; + + // Root Constants Bind to CBuffers + Validation.addBinding(llvm::to_underlying(dxbc::DescriptorRangeType::CBV), + Binding); + + 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-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll new file mode 100644 index 0000000000000..3c33f1dc6bdf0 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll @@ -0,0 +1,22 @@ +; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 +; expected-no-diagnostics +; Root Signature(RootConstants(num32BitConstants=4, b2)) + +%__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: +; cbuffer CB : register(b2, space0) { +; float a; +; } + %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, i1 false, ptr nonnull @CB.str) + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2} +!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll new file mode 100644 index 0000000000000..b7e1172c7304a --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll @@ -0,0 +1,22 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s +; CHECK: error: register CB (space=666, register=2) is not defined in Root Signature +; Root Signature(RootConstants(num32BitConstants=4, b2)) + +%__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: +; cbuffer CB : register(b2, space666) { +; float a; +; } + %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 666, i32 2, i32 1, i32 0, i1 false, ptr nonnull @CB.str) + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2} +!2 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4} _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits