From 0e8828c291d6e7e35ed3c0bce0504d8f731f9667 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 19:28:01 +0000 Subject: [PATCH 001/143] refactoring --- .../lib/Target/DirectX/DXContainerGlobals.cpp | 2 +- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 12 ++--- llvm/lib/Target/DirectX/DXILRootSignature.h | 45 ++++++++++++++----- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 9c38901f6821f..83f787da66403 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -160,7 +160,7 @@ void DXContainerGlobals::addRootSignature(Module &M, assert(MMI.EntryPropertyVec.size() == 1); - auto &RSA = getAnalysis(); + auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; const auto &FuncRs = RSA.find(EntryFunction); diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 29e78fcce5262..4094df160ef6f 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -554,9 +554,9 @@ analyzeModule(Module &M) { AnalysisKey RootSignatureAnalysis::Key; -SmallDenseMap -RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { - return analyzeModule(M); +RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M, + ModuleAnalysisManager &AM) { + return RootSignatureBindingInfo(analyzeModule(M)); } //===----------------------------------------------------------------------===// @@ -564,8 +564,7 @@ RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, ModuleAnalysisManager &AM) { - SmallDenseMap &RSDMap = - AM.getResult(M); + RootSignatureBindingInfo &RSDMap = AM.getResult(M); OS << "Root Signature Definitions" << "\n"; @@ -636,7 +635,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===----------------------------------------------------------------------===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { - FuncToRsMap = analyzeModule(M); + FuncToRsMap = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); return false; } diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index b45cebc15fd39..fef933811f840 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -33,16 +33,43 @@ enum class RootSignatureElementKind { CBV = 5, DescriptorTable = 6, }; + +class RootSignatureBindingInfo { + private: + SmallDenseMap FuncToRsMap; + + public: + using iterator = + SmallDenseMap::iterator; + + RootSignatureBindingInfo () = default; + RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; + + iterator find(const Function *F) { return FuncToRsMap.find(F); } + + iterator end() { return FuncToRsMap.end(); } + + std::optional getDescForFunction(const Function* F) { + const auto FuncRs = find(F); + if (FuncRs == end()) + return std::nullopt; + + return FuncRs->second; + } + +}; + class RootSignatureAnalysis : public AnalysisInfoMixin { friend AnalysisInfoMixin; static AnalysisKey Key; public: - RootSignatureAnalysis() = default; - using Result = SmallDenseMap; +RootSignatureAnalysis() = default; - SmallDenseMap + using Result = RootSignatureBindingInfo; + + RootSignatureBindingInfo run(Module &M, ModuleAnalysisManager &AM); }; @@ -52,20 +79,16 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { /// passes which run through the legacy pass manager. class RootSignatureAnalysisWrapper : public ModulePass { private: - SmallDenseMap FuncToRsMap; + std::unique_ptr FuncToRsMap; public: static char ID; + using Result = RootSignatureBindingInfo; RootSignatureAnalysisWrapper() : ModulePass(ID) {} - using iterator = - SmallDenseMap::iterator; - - iterator find(const Function *F) { return FuncToRsMap.find(F); } - - iterator end() { return FuncToRsMap.end(); } - + RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} + bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override; From 2edd215e118e9dc947b1a6d2bc52bb8b6c78e3b2 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 19:28:01 +0000 Subject: [PATCH 002/143] refactoring --- llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 7 +++---- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 12 +++++++++--- llvm/lib/Target/DirectX/DXILRootSignature.h | 10 +++++++--- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 83f787da66403..6c8ae8eaaea77 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -162,16 +162,15 @@ void DXContainerGlobals::addRootSignature(Module &M, auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; - const auto &FuncRs = RSA.find(EntryFunction); + const auto &RS = RSA.getDescForFunction(EntryFunction); - if (FuncRs == RSA.end()) + if (!RS) return; - const RootSignatureDesc &RS = FuncRs->second; SmallString<256> Data; raw_svector_ostream OS(Data); - RS.write(OS); + RS->write(OS); Constant *Constant = ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false); diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 4094df160ef6f..12b0f0b74837a 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -28,6 +28,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include +#include #include #include @@ -554,9 +555,12 @@ analyzeModule(Module &M) { AnalysisKey RootSignatureAnalysis::Key; -RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M, - ModuleAnalysisManager &AM) { - return RootSignatureBindingInfo(analyzeModule(M)); +RootSignatureAnalysis::Result +RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { + if (!AnalysisResult) + AnalysisResult = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); + return *AnalysisResult; } //===----------------------------------------------------------------------===// @@ -635,6 +639,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===----------------------------------------------------------------------===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { + if (HasRun) + return false; FuncToRsMap = std::make_unique( RootSignatureBindingInfo(analyzeModule(M))); return false; diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index fef933811f840..c143d45a13d88 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -19,6 +19,7 @@ #include "llvm/IR/PassManager.h" #include "llvm/MC/DXContainerRootSignature.h" #include "llvm/Pass.h" +#include #include namespace llvm { @@ -68,9 +69,11 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { RootSignatureAnalysis() = default; using Result = RootSignatureBindingInfo; - - RootSignatureBindingInfo - run(Module &M, ModuleAnalysisManager &AM); + + Result run(Module &M, ModuleAnalysisManager &AM); + +private: + std::unique_ptr AnalysisResult; }; /// Wrapper pass for the legacy pass manager. @@ -80,6 +83,7 @@ RootSignatureAnalysis() = default; class RootSignatureAnalysisWrapper : public ModulePass { private: std::unique_ptr FuncToRsMap; + bool HasRun = false; public: static char ID; From 242545e5f40ccbf698e7f6935d8d9efa86cf5cb4 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Wed, 2 Jul 2025 21:10:21 +0000 Subject: [PATCH 003/143] clean up --- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 8 +++----- llvm/lib/Target/DirectX/DXILRootSignature.h | 2 -- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 12b0f0b74837a..5a53ea8a3631b 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -28,7 +28,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include -#include #include #include @@ -639,10 +638,9 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===----------------------------------------------------------------------===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { - if (HasRun) - return false; - FuncToRsMap = std::make_unique( - RootSignatureBindingInfo(analyzeModule(M))); + if (!FuncToRsMap) + FuncToRsMap = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); return false; } diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index c143d45a13d88..8a057404e01c1 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -19,7 +19,6 @@ #include "llvm/IR/PassManager.h" #include "llvm/MC/DXContainerRootSignature.h" #include "llvm/Pass.h" -#include #include namespace llvm { @@ -83,7 +82,6 @@ RootSignatureAnalysis() = default; class RootSignatureAnalysisWrapper : public ModulePass { private: std::unique_ptr FuncToRsMap; - bool HasRun = false; public: static char ID; From 3f8dec410b55a610f41cec9d7b38c15c52f82837 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Wed, 2 Jul 2025 21:22:55 +0000 Subject: [PATCH 004/143] format --- llvm/lib/Target/DirectX/DXILRootSignature.h | 25 +++++++++++---------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 8a057404e01c1..60ae7c0a6b2b1 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -35,28 +35,30 @@ enum class RootSignatureElementKind { }; class RootSignatureBindingInfo { - private: - SmallDenseMap FuncToRsMap; +private: + SmallDenseMap FuncToRsMap; - public: +public: using iterator = - SmallDenseMap::iterator; + SmallDenseMap::iterator; - RootSignatureBindingInfo () = default; - RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; + RootSignatureBindingInfo() = default; + RootSignatureBindingInfo( + SmallDenseMap Map) + : FuncToRsMap(Map){}; iterator find(const Function *F) { return FuncToRsMap.find(F); } iterator end() { return FuncToRsMap.end(); } - std::optional getDescForFunction(const Function* F) { + std::optional + getDescForFunction(const Function *F) { const auto FuncRs = find(F); if (FuncRs == end()) return std::nullopt; return FuncRs->second; } - }; class RootSignatureAnalysis : public AnalysisInfoMixin { @@ -64,8 +66,7 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { static AnalysisKey Key; public: - -RootSignatureAnalysis() = default; + RootSignatureAnalysis() = default; using Result = RootSignatureBindingInfo; @@ -89,8 +90,8 @@ class RootSignatureAnalysisWrapper : public ModulePass { RootSignatureAnalysisWrapper() : ModulePass(ID) {} - RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} - + RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; } + bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override; From 3b1ce3bee8112f55b22ed55c2881bd128793b3e2 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Wed, 2 Jul 2025 21:49:19 +0000 Subject: [PATCH 005/143] formating --- llvm/lib/Target/DirectX/DXILRootSignature.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 60ae7c0a6b2b1..41c2251c5f1e2 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -45,7 +45,7 @@ class RootSignatureBindingInfo { RootSignatureBindingInfo() = default; RootSignatureBindingInfo( SmallDenseMap Map) - : FuncToRsMap(Map){}; + : FuncToRsMap(Map) {}; iterator find(const Function *F) { return FuncToRsMap.find(F); } From f5720afd4c34075e17c2220dd92d0f10a60bbb43 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Fri, 4 Jul 2025 02:10:03 +0000 Subject: [PATCH 006/143] fix import issues --- llvm/lib/Target/DirectX/DXILRootSignature.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 41c2251c5f1e2..e02f47ff60ae8 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -10,6 +10,8 @@ /// Root Signatures. /// //===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H +#define LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H #include "llvm/ADT/DenseMap.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" @@ -45,7 +47,7 @@ class RootSignatureBindingInfo { RootSignatureBindingInfo() = default; RootSignatureBindingInfo( SmallDenseMap Map) - : FuncToRsMap(Map) {}; + : FuncToRsMap(Map){}; iterator find(const Function *F) { return FuncToRsMap.find(F); } @@ -109,3 +111,4 @@ class RootSignatureAnalysisPrinter } // namespace dxil } // namespace llvm +#endif From ea54904cdc29c624cd40ecff7f4ce5fe0af17af6 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Fri, 4 Jul 2025 19:28:15 +0000 Subject: [PATCH 007/143] formating --- llvm/lib/Target/DirectX/DXILRootSignature.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index e02f47ff60ae8..3832182277050 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -47,7 +47,7 @@ class RootSignatureBindingInfo { RootSignatureBindingInfo() = default; RootSignatureBindingInfo( SmallDenseMap Map) - : FuncToRsMap(Map){}; + : FuncToRsMap(Map) {}; iterator find(const Function *F) { return FuncToRsMap.find(F); } From a49aa19297811e5800ffce364d8d6a225109d93f Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 19:28:01 +0000 Subject: [PATCH 008/143] refactoring --- .../lib/Target/DirectX/DXContainerGlobals.cpp | 4 ++- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 14 +++----- llvm/lib/Target/DirectX/DXILRootSignature.h | 33 +++++++++---------- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 6c8ae8eaaea77..e076283b65193 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -160,11 +160,13 @@ void DXContainerGlobals::addRootSignature(Module &M, assert(MMI.EntryPropertyVec.size() == 1); + auto &RSA = getAnalysis().getRSInfo(); auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; const auto &RS = RSA.getDescForFunction(EntryFunction); + const auto &RS = RSA.getDescForFunction(EntryFunction); - if (!RS) + if (!RS ) return; SmallString<256> Data; diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 5a53ea8a3631b..4094df160ef6f 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -554,12 +554,9 @@ analyzeModule(Module &M) { AnalysisKey RootSignatureAnalysis::Key; -RootSignatureAnalysis::Result -RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { - if (!AnalysisResult) - AnalysisResult = std::make_unique( - RootSignatureBindingInfo(analyzeModule(M))); - return *AnalysisResult; +RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M, + ModuleAnalysisManager &AM) { + return RootSignatureBindingInfo(analyzeModule(M)); } //===----------------------------------------------------------------------===// @@ -638,9 +635,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===----------------------------------------------------------------------===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { - if (!FuncToRsMap) - FuncToRsMap = std::make_unique( - RootSignatureBindingInfo(analyzeModule(M))); + FuncToRsMap = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); return false; } diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 3832182277050..24b1a8d3d2abe 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -37,30 +37,28 @@ enum class RootSignatureElementKind { }; class RootSignatureBindingInfo { -private: - SmallDenseMap FuncToRsMap; + private: + SmallDenseMap FuncToRsMap; -public: + public: using iterator = - SmallDenseMap::iterator; + SmallDenseMap::iterator; - RootSignatureBindingInfo() = default; - RootSignatureBindingInfo( - SmallDenseMap Map) - : FuncToRsMap(Map) {}; + RootSignatureBindingInfo () = default; + RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; iterator find(const Function *F) { return FuncToRsMap.find(F); } iterator end() { return FuncToRsMap.end(); } - std::optional - getDescForFunction(const Function *F) { + std::optional getDescForFunction(const Function* F) { const auto FuncRs = find(F); if (FuncRs == end()) return std::nullopt; return FuncRs->second; } + }; class RootSignatureAnalysis : public AnalysisInfoMixin { @@ -68,14 +66,13 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { static AnalysisKey Key; public: - RootSignatureAnalysis() = default; - - using Result = RootSignatureBindingInfo; - Result run(Module &M, ModuleAnalysisManager &AM); +RootSignatureAnalysis() = default; -private: - std::unique_ptr AnalysisResult; + using Result = RootSignatureBindingInfo; + + RootSignatureBindingInfo + run(Module &M, ModuleAnalysisManager &AM); }; /// Wrapper pass for the legacy pass manager. @@ -92,8 +89,8 @@ class RootSignatureAnalysisWrapper : public ModulePass { RootSignatureAnalysisWrapper() : ModulePass(ID) {} - RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; } - + RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} + bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override; From d90676feb6bfc0ca8bbdaee5c347ecc49e396b5b Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 21:37:11 +0000 Subject: [PATCH 009/143] init refactoring --- .../SemaHLSL/RootSignature-Validation.hlsl | 42 +++++++++++++++++ .../lib/Target/DirectX/DXContainerGlobals.cpp | 2 +- .../DXILPostOptimizationValidation.cpp | 47 +++++++++++++++++-- llvm/lib/Target/DirectX/DXILRootSignature.h | 30 ++++++------ 4 files changed, 102 insertions(+), 19 deletions(-) create mode 100644 clang/test/SemaHLSL/RootSignature-Validation.hlsl diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl new file mode 100644 index 0000000000000..8a4a97f87cb65 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl @@ -0,0 +1,42 @@ +// RUN: %clang_dxc -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify + +#define ROOT_SIGNATURE \ + "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ + "CBV(b0, visibility=SHADER_VISIBILITY_ALL), " \ + "DescriptorTable(SRV(t0, numDescriptors=3), visibility=SHADER_VISIBILITY_PIXEL), " \ + "DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_PIXEL), " \ + "DescriptorTable(UAV(u0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL)" + +cbuffer CB : register(b3, space2) { + float a; +} + +StructuredBuffer In : register(t0); +RWStructuredBuffer Out : register(u0); + +RWBuffer UAV : register(u3); + +RWBuffer UAV1 : register(u2), UAV2 : register(u4); + +RWBuffer UAV3 : register(space5); + +float f : register(c5); + +int4 intv : register(c2); + +double dar[5] : register(c3); + +struct S { + int a; +}; + +S s : register(c10); + +// Compute Shader for UAV testing +[numthreads(8, 8, 1)] +[RootSignature(ROOT_SIGNATURE)] +void CSMain(uint3 id : SV_DispatchThreadID) +{ + In[0] = id; + Out[0] = In[0]; +} diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index e076283b65193..5c763c24a210a 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -166,7 +166,7 @@ void DXContainerGlobals::addRootSignature(Module &M, const auto &RS = RSA.getDescForFunction(EntryFunction); const auto &RS = RSA.getDescForFunction(EntryFunction); - if (!RS ) + if (!RS) return; SmallString<256> Data; diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 398dcbb8d1737..daf53fefe5f17 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -7,11 +7,14 @@ //===----------------------------------------------------------------------===// #include "DXILPostOptimizationValidation.h" +#include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.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" @@ -85,7 +88,9 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } static void reportErrors(Module &M, DXILResourceMap &DRM, - DXILResourceBindingInfo &DRBI) { + DXILResourceBindingInfo &DRBI, + RootSignatureBindingInfo &RSBI, + dxil::ModuleMetadataInfo &MMI) { if (DRM.hasInvalidCounterDirection()) reportInvalidDirection(M, DRM); @@ -94,6 +99,30 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in " "DXILResourceImplicitBinding pass"); + // Assuming this is used to validate only the root signature assigned to the + // entry function. + std::optional RootSigDesc = + RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); + if (!RootSigDesc) + return; + + for (const mcdxbc::RootParameterInfo &Info : + RootSigDesc->ParametersContainer) { + const auto &[Type, Loc] = + RootSigDesc->ParametersContainer.getTypeAndLocForParameter( + Info.Location); + switch (Type) { + case llvm::to_underlying(dxbc::RootParameterType::CBV): + dxbc::RTS0::v2::RootDescriptor Desc = + RootSigDesc->ParametersContainer.getRootDescriptor(Loc); + + llvm::dxil::ResourceInfo::ResourceBinding Binding; + Binding.LowerBound = Desc.ShaderRegister; + Binding.Space = Desc.RegisterSpace; + Binding.Size = 1; + break; + } + } } } // namespace @@ -101,7 +130,10 @@ PreservedAnalyses DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) { DXILResourceMap &DRM = MAM.getResult(M); DXILResourceBindingInfo &DRBI = MAM.getResult(M); - reportErrors(M, DRM, DRBI); + RootSignatureBindingInfo &RSBI = MAM.getResult(M); + ModuleMetadataInfo &MMI = MAM.getResult(M); + + reportErrors(M, DRM, DRBI, RSBI, MMI); return PreservedAnalyses::all(); } @@ -113,7 +145,13 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { getAnalysis().getResourceMap(); DXILResourceBindingInfo &DRBI = getAnalysis().getBindingInfo(); - reportErrors(M, DRM, DRBI); + + RootSignatureBindingInfo &RSBI = + getAnalysis().getRSInfo(); + dxil::ModuleMetadataInfo &MMI = + getAnalysis().getModuleMetadata(); + + reportErrors(M, DRM, DRBI, RSBI, MMI); return false; } StringRef getPassName() const override { @@ -125,10 +163,13 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { AU.addRequired(); AU.addRequired(); + AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); + AU.addPreserved(); } }; char DXILPostOptimizationValidationLegacy::ID = 0; diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 24b1a8d3d2abe..ecfc577d1b97d 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -37,28 +37,30 @@ enum class RootSignatureElementKind { }; class RootSignatureBindingInfo { - private: - SmallDenseMap FuncToRsMap; +private: + SmallDenseMap FuncToRsMap; - public: +public: using iterator = - SmallDenseMap::iterator; + SmallDenseMap::iterator; - RootSignatureBindingInfo () = default; - RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; + RootSignatureBindingInfo() = default; + RootSignatureBindingInfo( + SmallDenseMap Map) + : FuncToRsMap(Map){}; iterator find(const Function *F) { return FuncToRsMap.find(F); } iterator end() { return FuncToRsMap.end(); } - std::optional getDescForFunction(const Function* F) { + std::optional + getDescForFunction(const Function *F) { const auto FuncRs = find(F); if (FuncRs == end()) return std::nullopt; return FuncRs->second; } - }; class RootSignatureAnalysis : public AnalysisInfoMixin { @@ -66,13 +68,11 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { static AnalysisKey Key; public: - -RootSignatureAnalysis() = default; + RootSignatureAnalysis() = default; using Result = RootSignatureBindingInfo; - - RootSignatureBindingInfo - run(Module &M, ModuleAnalysisManager &AM); + + RootSignatureBindingInfo run(Module &M, ModuleAnalysisManager &AM); }; /// Wrapper pass for the legacy pass manager. @@ -89,8 +89,8 @@ class RootSignatureAnalysisWrapper : public ModulePass { RootSignatureAnalysisWrapper() : ModulePass(ID) {} - RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} - + RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; } + bool runOnModule(Module &M) override; void getAnalysisUsage(AnalysisUsage &AU) const override; From a04eb9ff37d20499f05c7b1cc0ab3187f729609b Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Wed, 2 Jul 2025 17:58:56 +0000 Subject: [PATCH 010/143] adding validation --- .../SemaHLSL/RootSignature-Validation.hlsl | 28 ++++--------- .../DXILPostOptimizationValidation.cpp | 42 +++++++++++++++---- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl index 8a4a97f87cb65..62ba704b95c7d 100644 --- a/clang/test/SemaHLSL/RootSignature-Validation.hlsl +++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl @@ -1,42 +1,30 @@ -// RUN: %clang_dxc -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify #define ROOT_SIGNATURE \ "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ - "CBV(b0, visibility=SHADER_VISIBILITY_ALL), " \ - "DescriptorTable(SRV(t0, numDescriptors=3), visibility=SHADER_VISIBILITY_PIXEL), " \ - "DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_PIXEL), " \ - "DescriptorTable(UAV(u0, numDescriptors=1), visibility=SHADER_VISIBILITY_ALL)" + "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_ALL), " \ + "DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" cbuffer CB : register(b3, space2) { float a; } -StructuredBuffer In : register(t0); +StructuredBuffer In : register(t0, space0); RWStructuredBuffer Out : register(u0); RWBuffer UAV : register(u3); RWBuffer UAV1 : register(u2), UAV2 : register(u4); -RWBuffer UAV3 : register(space5); +RWBuffer UAV3 : register(space0); -float f : register(c5); -int4 intv : register(c2); - -double dar[5] : register(c3); - -struct S { - int a; -}; - -S s : register(c10); // Compute Shader for UAV testing [numthreads(8, 8, 1)] [RootSignature(ROOT_SIGNATURE)] -void CSMain(uint3 id : SV_DispatchThreadID) +void CSMain(uint id : SV_GroupID) { - In[0] = id; - Out[0] = In[0]; + Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; } diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index daf53fefe5f17..3e542e502c2d5 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -10,6 +10,7 @@ #include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" +#include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" @@ -86,7 +87,9 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } } - + uint64_t combine_uint32_to_uint64(uint32_t high, uint32_t low) { + return (static_cast(high) << 32) | low; + } static void reportErrors(Module &M, DXILResourceMap &DRM, DXILResourceBindingInfo &DRBI, RootSignatureBindingInfo &RSBI, @@ -101,18 +104,24 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, "DXILResourceImplicitBinding pass"); // Assuming this is used to validate only the root signature assigned to the // entry function. + //Start test stuff + if(MMI.EntryPropertyVec.size() == 0) + return; + std::optional RootSigDesc = RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); if (!RootSigDesc) return; - for (const mcdxbc::RootParameterInfo &Info : - RootSigDesc->ParametersContainer) { + using MapT = llvm::IntervalMap>; + MapT::Allocator Allocator; + MapT BindingsMap(Allocator); + auto RSD = *RootSigDesc; + for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) { const auto &[Type, Loc] = - RootSigDesc->ParametersContainer.getTypeAndLocForParameter( - Info.Location); + RootSigDesc->ParametersContainer.getTypeAndLocForParameter(I); switch (Type) { - case llvm::to_underlying(dxbc::RootParameterType::CBV): + case llvm::to_underlying(dxbc::RootParameterType::CBV):{ dxbc::RTS0::v2::RootDescriptor Desc = RootSigDesc->ParametersContainer.getRootDescriptor(Loc); @@ -120,8 +129,27 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, Binding.LowerBound = Desc.ShaderRegister; Binding.Space = Desc.RegisterSpace; Binding.Size = 1; + + BindingsMap.insert(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1), Binding); break; } + // case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):{ + // mcdxbc::DescriptorTable Table = + // RootSigDesc->ParametersContainer.getDescriptorTable(Loc); + // for (const dxbc::RTS0::v2::DescriptorRange &Range : Table){ + // Range. + // } + + // break; + // } + } + + } + + for(const auto &CBuf : DRM.cbuffers()) { + auto Binding = CBuf.getBinding(); + if(!BindingsMap.overlaps(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1))) + auto X = 1; } } } // namespace @@ -146,7 +174,7 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { DXILResourceBindingInfo &DRBI = getAnalysis().getBindingInfo(); - RootSignatureBindingInfo &RSBI = + RootSignatureBindingInfo& RSBI = getAnalysis().getRSInfo(); dxil::ModuleMetadataInfo &MMI = getAnalysis().getModuleMetadata(); From 5994b8f8f4ea24115a66c0046c8fc344905b41d4 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Wed, 2 Jul 2025 21:19:37 +0000 Subject: [PATCH 011/143] clean --- .../DXILPostOptimizationValidation.cpp | 6 +---- .../DirectX/DXILPostOptimizationValidation.h | 3 +++ llvm/lib/Target/DirectX/DXILRootSignature.h | 24 +++++++++---------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 3e542e502c2d5..4c29b56304391 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -10,12 +10,9 @@ #include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" -#include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.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" @@ -173,8 +170,7 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { getAnalysis().getResourceMap(); DXILResourceBindingInfo &DRBI = getAnalysis().getBindingInfo(); - - RootSignatureBindingInfo& RSBI = + RootSignatureBindingInfo &RSBI = getAnalysis().getRSInfo(); dxil::ModuleMetadataInfo &MMI = getAnalysis().getModuleMetadata(); diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h index cb5e624514272..151843daf068d 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h @@ -14,6 +14,9 @@ #ifndef LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H #define LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H +#include "DXILRootSignature.h" +#include "llvm/ADT/IntervalMap.h" +#include "llvm/Analysis/DXILResource.h" #include "llvm/IR/PassManager.h" namespace llvm { diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index ecfc577d1b97d..d0d5c7785bda3 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -37,30 +37,28 @@ enum class RootSignatureElementKind { }; class RootSignatureBindingInfo { -private: - SmallDenseMap FuncToRsMap; + private: + SmallDenseMap FuncToRsMap; -public: + public: using iterator = - SmallDenseMap::iterator; + SmallDenseMap::iterator; - RootSignatureBindingInfo() = default; - RootSignatureBindingInfo( - SmallDenseMap Map) - : FuncToRsMap(Map){}; +RootSignatureBindingInfo () = default; + RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; iterator find(const Function *F) { return FuncToRsMap.find(F); } iterator end() { return FuncToRsMap.end(); } - std::optional - getDescForFunction(const Function *F) { + std::optional getDescForFunction(const Function *F) { const auto FuncRs = find(F); if (FuncRs == end()) return std::nullopt; return FuncRs->second; } + }; class RootSignatureAnalysis : public AnalysisInfoMixin { @@ -68,7 +66,7 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { static AnalysisKey Key; public: - RootSignatureAnalysis() = default; +RootSignatureAnalysis() = default; using Result = RootSignatureBindingInfo; @@ -88,8 +86,8 @@ class RootSignatureAnalysisWrapper : public ModulePass { using Result = RootSignatureBindingInfo; RootSignatureAnalysisWrapper() : ModulePass(ID) {} - - RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; } + + RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} bool runOnModule(Module &M) override; From e8b14bf32e47cf8c059d2f492e57a602375ceeaa Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Fri, 4 Jul 2025 02:03:26 +0000 Subject: [PATCH 012/143] implementing --- .../RootSignature-Validation-Fail.hlsl | 35 ++++ .../SemaHLSL/RootSignature-Validation.hlsl | 11 +- .../DXILPostOptimizationValidation.cpp | 166 +++++++++++++----- .../DirectX/DXILPostOptimizationValidation.h | 88 ++++++++++ llvm/lib/Target/DirectX/DXILRootSignature.h | 24 +-- .../RootSignature-DescriptorTable.ll | 4 +- 6 files changed, 271 insertions(+), 57 deletions(-) create mode 100644 clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl new file mode 100644 index 0000000000000..b590ed67e7085 --- /dev/null +++ b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl @@ -0,0 +1,35 @@ +// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s + +// CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature +// CHECK: error: register srv (space=0, register=0) is not defined in Root Signature +// CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature + + +#define ROOT_SIGNATURE \ + "CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL), " \ + "DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX), " \ + "DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL), " \ + "DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" + +cbuffer CB : register(b3, space665) { + float a; +} + +StructuredBuffer In : register(t0, space0); +RWStructuredBuffer Out : register(u0); + +RWBuffer UAV : register(u4294967295); + +RWBuffer UAV1 : register(u2), UAV2 : register(u4); + +RWBuffer UAV3 : register(space0); + + + +// Compute Shader for UAV testing +[numthreads(8, 8, 1)] +[RootSignature(ROOT_SIGNATURE)] +void CSMain(uint id : SV_GroupID) +{ + Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; +} diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl index 62ba704b95c7d..5a7f5baf00619 100644 --- a/clang/test/SemaHLSL/RootSignature-Validation.hlsl +++ b/clang/test/SemaHLSL/RootSignature-Validation.hlsl @@ -1,19 +1,22 @@ +// RUN: %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 + +// expected-no-diagnostics + #define ROOT_SIGNATURE \ - "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ "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_ALL), " \ + "DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX), " \ "DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" -cbuffer CB : register(b3, space2) { +cbuffer CB : register(b3, space1) { float a; } StructuredBuffer In : register(t0, space0); RWStructuredBuffer Out : register(u0); -RWBuffer UAV : register(u3); +RWBuffer UAV : register(u4294967294); RWBuffer UAV1 : register(u2), UAV2 : register(u4); diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 4c29b56304391..23bb5d1a7f651 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -84,9 +84,57 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } } - uint64_t combine_uint32_to_uint64(uint32_t high, uint32_t low) { - return (static_cast(high) << 32) | low; + +static void reportRegNotBound(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 not defined in Root Signature"; + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); +} + +static dxbc::ShaderVisibility +tripleToVisibility(llvm::Triple::EnvironmentType ET) { + assert((ET == Triple::Pixel || ET == Triple::Vertex || + ET == Triple::Geometry || ET == Triple::Hull || + ET == Triple::Domain || ET == Triple::Mesh || + ET == Triple::Compute) && + "Invalid Triple to shader stage conversion"); + + switch (ET) { + case Triple::Pixel: + return dxbc::ShaderVisibility::Pixel; + case Triple::Vertex: + return dxbc::ShaderVisibility::Vertex; + case Triple::Geometry: + return dxbc::ShaderVisibility::Geometry; + case Triple::Hull: + return dxbc::ShaderVisibility::Hull; + case Triple::Domain: + return dxbc::ShaderVisibility::Domain; + case Triple::Mesh: + return dxbc::ShaderVisibility::Mesh; + case Triple::Compute: + return dxbc::ShaderVisibility::All; + default: + llvm_unreachable("Invalid triple to shader stage conversion"); } +} + +std::optional +getRootSignature(RootSignatureBindingInfo &RSBI, + dxil::ModuleMetadataInfo &MMI) { + if (MMI.EntryPropertyVec.size() == 0) + return std::nullopt; + std::optional RootSigDesc = + RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); + if (!RootSigDesc) + return std::nullopt; + return RootSigDesc; +} + static void reportErrors(Module &M, DXILResourceMap &DRM, DXILResourceBindingInfo &DRBI, RootSignatureBindingInfo &RSBI, @@ -99,57 +147,95 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in " "DXILResourceImplicitBinding pass"); - // Assuming this is used to validate only the root signature assigned to the - // entry function. - //Start test stuff - if(MMI.EntryPropertyVec.size() == 0) - return; - std::optional RootSigDesc = - RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); - if (!RootSigDesc) - return; + if (auto RSD = getRootSignature(RSBI, MMI)) { + + RootSignatureBindingValidation Validation; + Validation.addRsBindingInfo(*RSD, tripleToVisibility(MMI.ShaderProfile)); + + for (const auto &CBuf : DRM.cbuffers()) { + ResourceInfo::ResourceBinding Binding = CBuf.getBinding(); + if (!Validation.checkCregBinding(Binding)) + reportRegNotBound(M, "cbuffer", Binding); + } + + for (const auto &CBuf : DRM.srvs()) { + ResourceInfo::ResourceBinding Binding = CBuf.getBinding(); + if (!Validation.checkTRegBinding(Binding)) + reportRegNotBound(M, "srv", Binding); + } - using MapT = llvm::IntervalMap>; - MapT::Allocator Allocator; - MapT BindingsMap(Allocator); - auto RSD = *RootSigDesc; - for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) { + for (const auto &CBuf : DRM.uavs()) { + ResourceInfo::ResourceBinding Binding = CBuf.getBinding(); + if (!Validation.checkURegBinding(Binding)) + reportRegNotBound(M, "uav", Binding); + } + } +} +} // namespace + +void RootSignatureBindingValidation::addRsBindingInfo( + mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) { + for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) { const auto &[Type, Loc] = - RootSigDesc->ParametersContainer.getTypeAndLocForParameter(I); + RSD.ParametersContainer.getTypeAndLocForParameter(I); + + const auto &Header = RSD.ParametersContainer.getHeader(I); switch (Type) { - case llvm::to_underlying(dxbc::RootParameterType::CBV):{ + 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 = - RootSigDesc->ParametersContainer.getRootDescriptor(Loc); + RSD.ParametersContainer.getRootDescriptor(Loc); - llvm::dxil::ResourceInfo::ResourceBinding Binding; - Binding.LowerBound = Desc.ShaderRegister; - Binding.Space = Desc.RegisterSpace; - Binding.Size = 1; + if (Header.ShaderVisibility == + llvm::to_underlying(dxbc::ShaderVisibility::All) || + Header.ShaderVisibility == llvm::to_underlying(Visibility)) + addRange(Desc, Type); + break; + } + case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): { + const mcdxbc::DescriptorTable &Table = + RSD.ParametersContainer.getDescriptorTable(Loc); - BindingsMap.insert(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1), Binding); + for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { + if (Range.RangeType == + llvm::to_underlying(dxbc::DescriptorRangeType::Sampler)) + continue; + + if (Header.ShaderVisibility == + llvm::to_underlying(dxbc::ShaderVisibility::All) || + Header.ShaderVisibility == llvm::to_underlying(Visibility)) + addRange(Range); + } break; } - // case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):{ - // mcdxbc::DescriptorTable Table = - // RootSigDesc->ParametersContainer.getDescriptorTable(Loc); - // for (const dxbc::RTS0::v2::DescriptorRange &Range : Table){ - // Range. - // } - - // break; - // } } - } +} - for(const auto &CBuf : DRM.cbuffers()) { - auto Binding = CBuf.getBinding(); - if(!BindingsMap.overlaps(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1))) - auto X = 1; - } +bool RootSignatureBindingValidation::checkCregBinding( + ResourceInfo::ResourceBinding Binding) { + return CRegBindingsMap.overlaps( + combineUint32ToUint64(Binding.Space, Binding.LowerBound), + combineUint32ToUint64(Binding.Space, + Binding.LowerBound + Binding.Size - 1)); +} + +bool RootSignatureBindingValidation::checkTRegBinding( + ResourceInfo::ResourceBinding Binding) { + return TRegBindingsMap.overlaps( + combineUint32ToUint64(Binding.Space, Binding.LowerBound), + combineUint32ToUint64(Binding.Space, Binding.LowerBound + Binding.Size)); +} + +bool RootSignatureBindingValidation::checkURegBinding( + ResourceInfo::ResourceBinding Binding) { + return URegBindingsMap.overlaps( + combineUint32ToUint64(Binding.Space, Binding.LowerBound), + combineUint32ToUint64(Binding.Space, + Binding.LowerBound + Binding.Size - 1)); } -} // namespace PreservedAnalyses DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) { diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h index 151843daf068d..58113bf9f93c7 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h @@ -21,6 +21,94 @@ namespace llvm { +static uint64_t combineUint32ToUint64(uint32_t High, uint32_t Low) { + return (static_cast(High) << 32) | Low; +} + +class RootSignatureBindingValidation { + using MapT = + llvm::IntervalMap>; + +private: + MapT::Allocator Allocator; + MapT CRegBindingsMap; + MapT TRegBindingsMap; + MapT URegBindingsMap; + + void addRange(const dxbc::RTS0::v2::RootDescriptor &Desc, uint32_t Type) { + assert((Type == llvm::to_underlying(dxbc::RootParameterType::CBV) || + Type == llvm::to_underlying(dxbc::RootParameterType::SRV) || + Type == llvm::to_underlying(dxbc::RootParameterType::UAV)) && + "Invalid Type"); + + llvm::dxil::ResourceInfo::ResourceBinding Binding; + Binding.LowerBound = Desc.ShaderRegister; + Binding.Space = Desc.RegisterSpace; + Binding.Size = 1; + + uint64_t LowRange = + combineUint32ToUint64(Binding.Space, Binding.LowerBound); + uint64_t HighRange = combineUint32ToUint64( + Binding.Space, Binding.LowerBound + Binding.Size - 1); + + switch (Type) { + + case llvm::to_underlying(dxbc::RootParameterType::CBV): + CRegBindingsMap.insert(LowRange, HighRange, Binding); + return; + case llvm::to_underlying(dxbc::RootParameterType::SRV): + TRegBindingsMap.insert(LowRange, HighRange, Binding); + return; + case llvm::to_underlying(dxbc::RootParameterType::UAV): + URegBindingsMap.insert(LowRange, HighRange, Binding); + return; + } + llvm_unreachable("Invalid Type in add Range Method"); + } + + void addRange(const dxbc::RTS0::v2::DescriptorRange &Range) { + + llvm::dxil::ResourceInfo::ResourceBinding Binding; + Binding.LowerBound = Range.BaseShaderRegister; + Binding.Space = Range.RegisterSpace; + Binding.Size = Range.NumDescriptors; + + uint64_t LowRange = + combineUint32ToUint64(Binding.Space, Binding.LowerBound); + uint64_t HighRange = combineUint32ToUint64( + Binding.Space, Binding.LowerBound + Binding.Size - 1); + + switch (Range.RangeType) { + case llvm::to_underlying(dxbc::DescriptorRangeType::CBV): + CRegBindingsMap.insert(LowRange, HighRange, Binding); + return; + case llvm::to_underlying(dxbc::DescriptorRangeType::SRV): + TRegBindingsMap.insert(LowRange, HighRange, Binding); + return; + case llvm::to_underlying(dxbc::DescriptorRangeType::UAV): + URegBindingsMap.insert(LowRange, HighRange, Binding); + return; + } + llvm_unreachable("Invalid Type in add Range Method"); + } + +public: + RootSignatureBindingValidation() + : Allocator(), CRegBindingsMap(Allocator), TRegBindingsMap(Allocator), + URegBindingsMap(Allocator) {} + + void addRsBindingInfo(mcdxbc::RootSignatureDesc &RSD, + dxbc::ShaderVisibility Visibility); + + bool checkCregBinding(dxil::ResourceInfo::ResourceBinding Binding); + + bool checkTRegBinding(dxil::ResourceInfo::ResourceBinding Binding); + + bool checkURegBinding(dxil::ResourceInfo::ResourceBinding Binding); +}; + class DXILPostOptimizationValidation : public PassInfoMixin { public: diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index d0d5c7785bda3..ecfc577d1b97d 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -37,28 +37,30 @@ enum class RootSignatureElementKind { }; class RootSignatureBindingInfo { - private: - SmallDenseMap FuncToRsMap; +private: + SmallDenseMap FuncToRsMap; - public: +public: using iterator = - SmallDenseMap::iterator; + SmallDenseMap::iterator; -RootSignatureBindingInfo () = default; - RootSignatureBindingInfo(SmallDenseMap Map) : FuncToRsMap(Map) {}; + RootSignatureBindingInfo() = default; + RootSignatureBindingInfo( + SmallDenseMap Map) + : FuncToRsMap(Map){}; iterator find(const Function *F) { return FuncToRsMap.find(F); } iterator end() { return FuncToRsMap.end(); } - std::optional getDescForFunction(const Function *F) { + std::optional + getDescForFunction(const Function *F) { const auto FuncRs = find(F); if (FuncRs == end()) return std::nullopt; return FuncRs->second; } - }; class RootSignatureAnalysis : public AnalysisInfoMixin { @@ -66,7 +68,7 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { static AnalysisKey Key; public: -RootSignatureAnalysis() = default; + RootSignatureAnalysis() = default; using Result = RootSignatureBindingInfo; @@ -86,8 +88,8 @@ class RootSignatureAnalysisWrapper : public ModulePass { using Result = RootSignatureBindingInfo; RootSignatureAnalysisWrapper() : ModulePass(ID) {} - - RootSignatureBindingInfo& getRSInfo() {return *FuncToRsMap;} + + RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; } bool runOnModule(Module &M) override; diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll index b516d66180247..8e9b4b43b11a6 100644 --- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable.ll @@ -16,7 +16,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } !2 = !{ ptr @main, !3, i32 2 } ; function, root signature !3 = !{ !5 } ; list of root signature elements !5 = !{ !"DescriptorTable", i32 0, !6, !7 } -!6 = !{ !"SRV", i32 0, i32 1, i32 0, i32 -1, i32 4 } +!6 = !{ !"SRV", i32 1, i32 1, i32 0, i32 -1, i32 4 } !7 = !{ !"UAV", i32 5, i32 1, i32 10, i32 5, i32 2 } ; DXC: - Name: RTS0 @@ -35,7 +35,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } ; DXC-NEXT: RangesOffset: 44 ; DXC-NEXT: Ranges: ; DXC-NEXT: - RangeType: 0 -; DXC-NEXT: NumDescriptors: 0 +; DXC-NEXT: NumDescriptors: 1 ; DXC-NEXT: BaseShaderRegister: 1 ; DXC-NEXT: RegisterSpace: 0 ; DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 From 8f40e83ab0db147e90070f15708d0a0f4e1a9d1f Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Fri, 4 Jul 2025 19:24:25 +0000 Subject: [PATCH 013/143] finish implementing && fix tests --- .../DXILPostOptimizationValidation.cpp | 45 +++++----------- .../DirectX/DXILPostOptimizationValidation.h | 54 ++++++++++++++----- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 5 +- ...criptorTable-AllValidFlagCombinationsV1.ll | 4 +- llvm/test/CodeGen/DirectX/llc-pipeline.ll | 1 + 5 files changed, 59 insertions(+), 50 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 23bb5d1a7f651..a52a04323514c 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -153,23 +153,29 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, RootSignatureBindingValidation Validation; Validation.addRsBindingInfo(*RSD, tripleToVisibility(MMI.ShaderProfile)); - for (const auto &CBuf : DRM.cbuffers()) { + for (const ResourceInfo &CBuf : DRM.cbuffers()) { ResourceInfo::ResourceBinding Binding = CBuf.getBinding(); - if (!Validation.checkCregBinding(Binding)) + if (!Validation.checkCRegBinding(Binding)) reportRegNotBound(M, "cbuffer", Binding); } - for (const auto &CBuf : DRM.srvs()) { - ResourceInfo::ResourceBinding Binding = CBuf.getBinding(); + for (const ResourceInfo &SRV : DRM.srvs()) { + ResourceInfo::ResourceBinding Binding = SRV.getBinding(); if (!Validation.checkTRegBinding(Binding)) reportRegNotBound(M, "srv", Binding); } - for (const auto &CBuf : DRM.uavs()) { - ResourceInfo::ResourceBinding Binding = CBuf.getBinding(); + for (const ResourceInfo &UAV : DRM.uavs()) { + ResourceInfo::ResourceBinding Binding = UAV.getBinding(); if (!Validation.checkURegBinding(Binding)) reportRegNotBound(M, "uav", Binding); } + + for (const ResourceInfo &Sampler : DRM.samplers()) { + ResourceInfo::ResourceBinding Binding = Sampler.getBinding(); + if (!Validation.checkSamplerBinding(Binding)) + reportRegNotBound(M, "sampler", Binding); + } } } } // namespace @@ -199,10 +205,6 @@ void RootSignatureBindingValidation::addRsBindingInfo( RSD.ParametersContainer.getDescriptorTable(Loc); for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { - if (Range.RangeType == - llvm::to_underlying(dxbc::DescriptorRangeType::Sampler)) - continue; - if (Header.ShaderVisibility == llvm::to_underlying(dxbc::ShaderVisibility::All) || Header.ShaderVisibility == llvm::to_underlying(Visibility)) @@ -214,29 +216,6 @@ void RootSignatureBindingValidation::addRsBindingInfo( } } -bool RootSignatureBindingValidation::checkCregBinding( - ResourceInfo::ResourceBinding Binding) { - return CRegBindingsMap.overlaps( - combineUint32ToUint64(Binding.Space, Binding.LowerBound), - combineUint32ToUint64(Binding.Space, - Binding.LowerBound + Binding.Size - 1)); -} - -bool RootSignatureBindingValidation::checkTRegBinding( - ResourceInfo::ResourceBinding Binding) { - return TRegBindingsMap.overlaps( - combineUint32ToUint64(Binding.Space, Binding.LowerBound), - combineUint32ToUint64(Binding.Space, Binding.LowerBound + Binding.Size)); -} - -bool RootSignatureBindingValidation::checkURegBinding( - ResourceInfo::ResourceBinding Binding) { - return URegBindingsMap.overlaps( - combineUint32ToUint64(Binding.Space, Binding.LowerBound), - combineUint32ToUint64(Binding.Space, - Binding.LowerBound + Binding.Size - 1)); -} - PreservedAnalyses DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) { DXILResourceMap &DRM = MAM.getResult(M); diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h index 58113bf9f93c7..0fa0285425d7e 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h @@ -36,12 +36,13 @@ class RootSignatureBindingValidation { MapT CRegBindingsMap; MapT TRegBindingsMap; MapT URegBindingsMap; + MapT SamplersBindingsMap; void addRange(const dxbc::RTS0::v2::RootDescriptor &Desc, uint32_t Type) { assert((Type == llvm::to_underlying(dxbc::RootParameterType::CBV) || Type == llvm::to_underlying(dxbc::RootParameterType::SRV) || Type == llvm::to_underlying(dxbc::RootParameterType::UAV)) && - "Invalid Type"); + "Invalid Type in add Range Method"); llvm::dxil::ResourceInfo::ResourceBinding Binding; Binding.LowerBound = Desc.ShaderRegister; @@ -53,19 +54,20 @@ class RootSignatureBindingValidation { uint64_t HighRange = combineUint32ToUint64( Binding.Space, Binding.LowerBound + Binding.Size - 1); + assert(LowRange <= HighRange && "Invalid range configuration"); + switch (Type) { case llvm::to_underlying(dxbc::RootParameterType::CBV): CRegBindingsMap.insert(LowRange, HighRange, Binding); - return; + break; case llvm::to_underlying(dxbc::RootParameterType::SRV): TRegBindingsMap.insert(LowRange, HighRange, Binding); - return; + break; case llvm::to_underlying(dxbc::RootParameterType::UAV): URegBindingsMap.insert(LowRange, HighRange, Binding); - return; + break; } - llvm_unreachable("Invalid Type in add Range Method"); } void addRange(const dxbc::RTS0::v2::DescriptorRange &Range) { @@ -80,33 +82,59 @@ class RootSignatureBindingValidation { uint64_t HighRange = combineUint32ToUint64( Binding.Space, Binding.LowerBound + Binding.Size - 1); + assert(LowRange <= HighRange && "Invalid range configuration"); + switch (Range.RangeType) { case llvm::to_underlying(dxbc::DescriptorRangeType::CBV): CRegBindingsMap.insert(LowRange, HighRange, Binding); - return; + break; case llvm::to_underlying(dxbc::DescriptorRangeType::SRV): TRegBindingsMap.insert(LowRange, HighRange, Binding); - return; + break; case llvm::to_underlying(dxbc::DescriptorRangeType::UAV): URegBindingsMap.insert(LowRange, HighRange, Binding); - return; + break; + case llvm::to_underlying(dxbc::DescriptorRangeType::Sampler): + SamplersBindingsMap.insert(LowRange, HighRange, Binding); + break; } - llvm_unreachable("Invalid Type in add Range Method"); } public: RootSignatureBindingValidation() : Allocator(), CRegBindingsMap(Allocator), TRegBindingsMap(Allocator), - URegBindingsMap(Allocator) {} + URegBindingsMap(Allocator), SamplersBindingsMap(Allocator) {} void addRsBindingInfo(mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility); - bool checkCregBinding(dxil::ResourceInfo::ResourceBinding Binding); + bool checkCRegBinding(dxil::ResourceInfo::ResourceBinding Binding) { + return CRegBindingsMap.overlaps( + combineUint32ToUint64(Binding.Space, Binding.LowerBound), + combineUint32ToUint64(Binding.Space, + Binding.LowerBound + Binding.Size - 1)); + } - bool checkTRegBinding(dxil::ResourceInfo::ResourceBinding Binding); + bool checkTRegBinding(dxil::ResourceInfo::ResourceBinding Binding) { + return TRegBindingsMap.overlaps( + combineUint32ToUint64(Binding.Space, Binding.LowerBound), + combineUint32ToUint64(Binding.Space, + Binding.LowerBound + Binding.Size - 1)); + } - bool checkURegBinding(dxil::ResourceInfo::ResourceBinding Binding); + bool checkURegBinding(dxil::ResourceInfo::ResourceBinding Binding) { + return URegBindingsMap.overlaps( + combineUint32ToUint64(Binding.Space, Binding.LowerBound), + combineUint32ToUint64(Binding.Space, + Binding.LowerBound + Binding.Size - 1)); + } + + bool checkSamplerBinding(dxil::ResourceInfo::ResourceBinding Binding) { + return SamplersBindingsMap.overlaps( + combineUint32ToUint64(Binding.Space, Binding.LowerBound), + combineUint32ToUint64(Binding.Space, + Binding.LowerBound + Binding.Size - 1)); + } }; class DXILPostOptimizationValidation diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 4094df160ef6f..2a68a4c324a09 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -635,8 +635,9 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===----------------------------------------------------------------------===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { - FuncToRsMap = std::make_unique( - RootSignatureBindingInfo(analyzeModule(M))); + if (!FuncToRsMap) + FuncToRsMap = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); return false; } diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll index 9d89dbdd9107b..053721de1eb1f 100644 --- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll @@ -13,7 +13,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } !2 = !{ ptr @main, !3, i32 1 } ; function, root signature !3 = !{ !5 } ; list of root signature elements !5 = !{ !"DescriptorTable", i32 0, !6, !7 } -!6 = !{ !"Sampler", i32 0, i32 1, i32 0, i32 -1, i32 1 } +!6 = !{ !"Sampler", i32 1, i32 1, i32 0, i32 -1, i32 1 } !7 = !{ !"UAV", i32 5, i32 1, i32 10, i32 5, i32 3 } @@ -33,7 +33,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } ; DXC-NEXT: RangesOffset: 44 ; DXC-NEXT: Ranges: ; DXC-NEXT: - RangeType: 3 -; DXC-NEXT: NumDescriptors: 0 +; DXC-NEXT: NumDescriptors: 1 ; DXC-NEXT: BaseShaderRegister: 1 ; DXC-NEXT: RegisterSpace: 0 ; DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll index 2b29fd30a7a56..8d75249dc6ecb 100644 --- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll +++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll @@ -31,6 +31,7 @@ ; CHECK-NEXT: DXIL Module Metadata analysis ; CHECK-NEXT: DXIL Shader Flag Analysis ; CHECK-NEXT: DXIL Translate Metadata +; CHECK-NEXT: DXIL Root Signature Analysis ; CHECK-NEXT: DXIL Post Optimization Validation ; CHECK-NEXT: DXIL Op Lowering ; CHECK-NEXT: DXIL Prepare Module From 28350b2dfe2a896b2199260953c1d061550badba Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Sat, 5 Jul 2025 00:35:07 +0000 Subject: [PATCH 014/143] fix issue --- llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 5c763c24a210a..6c8ae8eaaea77 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -160,11 +160,9 @@ void DXContainerGlobals::addRootSignature(Module &M, assert(MMI.EntryPropertyVec.size() == 1); - auto &RSA = getAnalysis().getRSInfo(); auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; const auto &RS = RSA.getDescForFunction(EntryFunction); - const auto &RS = RSA.getDescForFunction(EntryFunction); if (!RS) return; From 4fd2e0bfdda5f87a3204982aa01d8b158945eadf Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Sat, 5 Jul 2025 00:37:12 +0000 Subject: [PATCH 015/143] sync parent --- llvm/lib/Target/DirectX/DXILRootSignature.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index ecfc577d1b97d..3832182277050 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -47,7 +47,7 @@ class RootSignatureBindingInfo { RootSignatureBindingInfo() = default; RootSignatureBindingInfo( SmallDenseMap Map) - : FuncToRsMap(Map){}; + : FuncToRsMap(Map) {}; iterator find(const Function *F) { return FuncToRsMap.find(F); } @@ -72,7 +72,10 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { using Result = RootSignatureBindingInfo; - RootSignatureBindingInfo run(Module &M, ModuleAnalysisManager &AM); + Result run(Module &M, ModuleAnalysisManager &AM); + +private: + std::unique_ptr AnalysisResult; }; /// Wrapper pass for the legacy pass manager. From e25ee87104bbb7013da38761df2beee7c98f4a9a Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Sat, 5 Jul 2025 00:39:18 +0000 Subject: [PATCH 016/143] sync parent --- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 2a68a4c324a09..5a53ea8a3631b 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -554,9 +554,12 @@ analyzeModule(Module &M) { AnalysisKey RootSignatureAnalysis::Key; -RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M, - ModuleAnalysisManager &AM) { - return RootSignatureBindingInfo(analyzeModule(M)); +RootSignatureAnalysis::Result +RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { + if (!AnalysisResult) + AnalysisResult = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); + return *AnalysisResult; } //===----------------------------------------------------------------------===// From 01a558be2b36a6bb00e1027c4d042c7bacd4ed5a Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 7 Jul 2025 19:26:24 +0000 Subject: [PATCH 017/143] 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(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(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(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(Sampler.getHandleTy())) + reportTextureBoundInRs(M, "sampler", Binding); + if (!Validation.checkSamplerBinding(Binding)) reportRegNotBound(M, "sampler", Binding); } From 881dd365da77a817dd2be4f2aed2426b15a38d24 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 7 Jul 2025 20:14:49 +0000 Subject: [PATCH 018/143] address comments --- llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 3 ++- llvm/lib/Target/DirectX/DXILRootSignature.h | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 6c8ae8eaaea77..b6e8ce7d78b23 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -162,7 +162,8 @@ void DXContainerGlobals::addRootSignature(Module &M, auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; - const auto &RS = RSA.getDescForFunction(EntryFunction); + const std::optional &RS = + RSA.getDescForFunction(EntryFunction); if (!RS) return; diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 3832182277050..e975ceb22ea54 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -47,7 +47,7 @@ class RootSignatureBindingInfo { RootSignatureBindingInfo() = default; RootSignatureBindingInfo( SmallDenseMap Map) - : FuncToRsMap(Map) {}; + : FuncToRsMap(Map){}; iterator find(const Function *F) { return FuncToRsMap.find(F); } @@ -88,8 +88,6 @@ class RootSignatureAnalysisWrapper : public ModulePass { public: static char ID; - using Result = RootSignatureBindingInfo; - RootSignatureAnalysisWrapper() : ModulePass(ID) {} RootSignatureBindingInfo &getRSInfo() { return *FuncToRsMap; } From 43eb04ecebd44ec86a688abc9f067db0dfce2620 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 8 Jul 2025 02:01:02 +0000 Subject: [PATCH 019/143] 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 Out : register(u0); +Buffer 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 In : register(t0, space0); RWStructuredBuffer Out : register(u0); -RWBuffer UAV : register(u4294967294); +RWStructuredBuffer UAV : register(u4294967294); -RWBuffer UAV1 : register(u2), UAV2 : register(u4); +RWStructuredBuffer UAV1 : register(u2), UAV2 : register(u4); -RWBuffer UAV3 : register(space0); +RWStructuredBuffer 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(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(SRV.getHandleTy())) - reportTextureBoundInRs(M, "srv", Binding); - if (!Validation.checkTRegBinding(Binding)) reportRegNotBound(M, "srv", Binding); + else { + const auto *Handle = + dyn_cast_or_null(SRV.getHandleTy()); + + if (!Handle) + reportInvalidHandleTyBoundInRs(M, "srv", Binding); + } } for (const ResourceInfo &UAV : DRM.uavs()) { ResourceInfo::ResourceBinding Binding = UAV.getBinding(); - if (auto *TB = dyn_cast(UAV.getHandleTy())) - reportTextureBoundInRs(M, "uav", Binding); - if (!Validation.checkURegBinding(Binding)) reportRegNotBound(M, "uav", Binding); + else { + const auto *Handle = + dyn_cast_or_null(UAV.getHandleTy()); + + if (!Handle) + reportInvalidHandleTyBoundInRs(M, "srv", Binding); + } } for (const ResourceInfo &Sampler : DRM.samplers()) { ResourceInfo::ResourceBinding Binding = Sampler.getBinding(); - if (auto *TB = dyn_cast(Sampler.getHandleTy())) - reportTextureBoundInRs(M, "sampler", Binding); - if (!Validation.checkSamplerBinding(Binding)) reportRegNotBound(M, "sampler", Binding); } From c16f15b4cd469a3f6efc2e4b0e098190d7fd0787 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 8 Jul 2025 17:00:28 +0000 Subject: [PATCH 020/143] fix test --- clang/test/SemaHLSL/RootSignature-Validation.hlsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 In : register(t0, space0); RWStructuredBuffer Out : register(u0); -RWBuffer UAV : register(u4294967294); +RWStructuredBuffer UAV : register(u4294967294); -RWBuffer UAV1 : register(u2), UAV2 : register(u4); +RWStructuredBuffer UAV1 : register(u2), UAV2 : register(u4); -RWBuffer UAV3 : register(space0); +RWStructuredBuffer UAV3 : register(space0); From d7b4cf44541866a47160ac005e85223b3b7b076d Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 8 Jul 2025 17:06:19 +0000 Subject: [PATCH 021/143] 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 c7d5be77bd7c5421aca2e105dbab84854e335703 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 8 Jul 2025 17:18:15 +0000 Subject: [PATCH 022/143] format --- llvm/lib/Target/DirectX/DXILRootSignature.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index e975ceb22ea54..41c63939f93a6 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -47,7 +47,7 @@ class RootSignatureBindingInfo { RootSignatureBindingInfo() = default; RootSignatureBindingInfo( SmallDenseMap Map) - : FuncToRsMap(Map){}; + : FuncToRsMap(Map) {}; iterator find(const Function *F) { return FuncToRsMap.find(F); } From cc5afaefcafe97e92547c42c43c8747c0c7981fe Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 8 Jul 2025 19:02:00 +0000 Subject: [PATCH 023/143] address changes --- llvm/lib/Target/DirectX/DXILRootSignature.cpp | 12 ++++-------- llvm/lib/Target/DirectX/DXILRootSignature.h | 3 --- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index 5a53ea8a3631b..3848ad63dc468 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -556,10 +556,7 @@ AnalysisKey RootSignatureAnalysis::Key; RootSignatureAnalysis::Result RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) { - if (!AnalysisResult) - AnalysisResult = std::make_unique( - RootSignatureBindingInfo(analyzeModule(M))); - return *AnalysisResult; + return RootSignatureBindingInfo(analyzeModule(M)); } //===----------------------------------------------------------------------===// @@ -638,15 +635,14 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M, //===----------------------------------------------------------------------===// bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { - if (!FuncToRsMap) - FuncToRsMap = std::make_unique( - RootSignatureBindingInfo(analyzeModule(M))); + FuncToRsMap = std::make_unique( + RootSignatureBindingInfo(analyzeModule(M))); return false; } void RootSignatureAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addRequired(); + AU.addPreserved(); } char RootSignatureAnalysisWrapper::ID = 0; diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 41c63939f93a6..07dbd51bed391 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -73,9 +73,6 @@ class RootSignatureAnalysis : public AnalysisInfoMixin { using Result = RootSignatureBindingInfo; Result run(Module &M, ModuleAnalysisManager &AM); - -private: - std::unique_ptr AnalysisResult; }; /// Wrapper pass for the legacy pass manager. From 571a0ef25df4ffffe56cdc7d7274ebe9d23996be Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 8 Jul 2025 20:31:43 +0000 Subject: [PATCH 024/143] fix tests --- .../RootSignature-Validation-Fail.hlsl | 35 ---- .../SemaHLSL/RootSignature-Validation.hlsl | 33 ---- .../DirectX/rootsignature-validation-fail.ll | 160 ++++++++++++++++++ .../DirectX/rootsignature-validation.ll | 149 ++++++++++++++++ 4 files changed, 309 insertions(+), 68 deletions(-) delete mode 100644 clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl delete mode 100644 clang/test/SemaHLSL/RootSignature-Validation.hlsl create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation.ll diff --git a/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl b/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl deleted file mode 100644 index b590ed67e7085..0000000000000 --- a/clang/test/SemaHLSL/RootSignature-Validation-Fail.hlsl +++ /dev/null @@ -1,35 +0,0 @@ -// RUN: not %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 | FileCheck %s - -// CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature -// CHECK: error: register srv (space=0, register=0) is not defined in Root Signature -// CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature - - -#define ROOT_SIGNATURE \ - "CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL), " \ - "DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX), " \ - "DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL), " \ - "DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL)" - -cbuffer CB : register(b3, space665) { - float a; -} - -StructuredBuffer In : register(t0, space0); -RWStructuredBuffer Out : register(u0); - -RWBuffer UAV : register(u4294967295); - -RWBuffer UAV1 : register(u2), UAV2 : register(u4); - -RWBuffer UAV3 : register(space0); - - - -// Compute Shader for UAV testing -[numthreads(8, 8, 1)] -[RootSignature(ROOT_SIGNATURE)] -void CSMain(uint id : SV_GroupID) -{ - Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; -} diff --git a/clang/test/SemaHLSL/RootSignature-Validation.hlsl b/clang/test/SemaHLSL/RootSignature-Validation.hlsl deleted file mode 100644 index c4ea897c6f490..0000000000000 --- a/clang/test/SemaHLSL/RootSignature-Validation.hlsl +++ /dev/null @@ -1,33 +0,0 @@ -// RUN: %clang_dxc -T cs_6_6 -E CSMain %s 2>&1 - -// expected-no-diagnostics - - -#define 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)" - -cbuffer CB : register(b3, space1) { - float a; -} - -StructuredBuffer In : register(t0, space0); -RWStructuredBuffer Out : register(u0); - -RWStructuredBuffer UAV : register(u4294967294); - -RWStructuredBuffer UAV1 : register(u2), UAV2 : register(u4); - -RWStructuredBuffer UAV3 : register(space0); - - - -// Compute Shader for UAV testing -[numthreads(8, 8, 1)] -[RootSignature(ROOT_SIGNATURE)] -void CSMain(uint id : SV_GroupID) -{ - Out[0] = a + id + In[0] + UAV[0] + UAV1[0] + UAV3[0]; -} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll new file mode 100644 index 0000000000000..54802c9e7ed22 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll @@ -0,0 +1,160 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 + +; CHECK: error: register cbuffer (space=665, register=3) is not defined in Root Signature +; CHECK: error: register srv (space=0, register=0) is not defined in Root Signature +; CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature + +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- --------- +; In texture struct r/o T0 t0 1 +; Out UAV struct r/w U0 u0 1 +; UAV3 UAV f32 buf U1 u1 1 +; UAV1 UAV f32 buf U2 u2 1 +; UAV UAV f32 buf U3 u4294967295 1 +; CB cbuffer NA NA CB0 cb3,space665 1 +; +; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation-Fail.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" + +%__cblayout_CB = type <{ float }> +%"StructuredBuffer" = type { i32 } +%"RWStructuredBuffer" = type { i32 } +%"RWBuffer" = type { float } +%CBuffer.CB = type { float } + +@CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) poison +@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 +@.str = private unnamed_addr constant [3 x i8] c"In\00", align 1 +@.str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1 +@.str.4 = private unnamed_addr constant [4 x i8] c"UAV\00", align 1 +@.str.6 = private unnamed_addr constant [5 x i8] c"UAV1\00", align 1 +@.str.10 = private unnamed_addr constant [5 x i8] c"UAV3\00", align 1 +@In = external constant %"StructuredBuffer" +@Out = external constant %"RWStructuredBuffer" +@UAV3 = external constant %"RWBuffer" +@UAV1 = external constant %"RWBuffer" +@UAV = external constant %"RWBuffer" +@CB = external constant %CBuffer.CB + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32, i32, i32, i32, i1, ptr) #0 + +; 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 665, 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.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 -1, i32 1, i32 0, i1 false, ptr nonnull @.str.4) + %3 = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @.str.6) + %4 = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 1, i32 1, i32 0, i1 false, ptr @.str.10) + %5 = tail call i32 @llvm.dx.group.id(i32 0) + %6 = 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) + %7 = extractvalue { float, float, float, float } %6, 0 + %conv.i = uitofp i32 %5 to float + %add.i = fadd reassoc nnan ninf nsz arcp afn float %7, %conv.i + %8 = 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) + %9 = extractvalue { i32, i1 } %8, 0 + %conv1.i = sitofp i32 %9 to float + %add2.i = fadd reassoc nnan ninf nsz arcp afn float %add.i, %conv1.i + %10 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %2, i32 0) + %11 = extractvalue { float, i1 } %10, 0 + %add4.i = fadd reassoc nnan ninf nsz arcp afn float %add2.i, %11 + %12 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %3, i32 0) + %13 = extractvalue { float, i1 } %12, 0 + %add6.i = fadd reassoc nnan ninf nsz arcp afn float %add4.i, %13 + %14 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %4, i32 0) + %15 = extractvalue { float, i1 } %14, 0 + %add8.i = fadd reassoc nnan ninf nsz arcp afn float %add6.i, %15 + %conv9.i = fptosi float %add8.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 %conv9.i) + ret void +} + +; Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) +declare i32 @llvm.dx.group.id(i32) #2 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32, i32, i32, i32, i1, ptr) #0 + +; 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) #0 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32, i32, i32, i32, i1, ptr) #0 + +; 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) #0 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32) #0 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #0 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) +declare { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32, i32) #3 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) +declare { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #3 + +; 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) #4 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) +declare { 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)), i32) #3 + +; uselistorder directives +uselistorder ptr @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 } +uselistorder ptr @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 } + +attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) } +attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #2 = { mustprogress nofree nosync nounwind willreturn memory(none) } +attributes #3 = { nocallback nofree nosync nounwind willreturn memory(read) } +attributes #4 = { nocallback nofree nosync nounwind willreturn memory(write) } + +!dx.rootsignatures = !{!0} +!llvm.module.flags = !{!9, !10} +!dx.valver = !{!11} +!llvm.ident = !{!12} +!dx.shaderModel = !{!13} +!dx.version = !{!14} +!dx.resources = !{!15} +!dx.entryPoints = !{!27} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3, !5, !7} +!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} +!3 = !{!"DescriptorTable", i32 1, !4} +!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} +!5 = !{!"DescriptorTable", i32 0, !6} +!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} +!7 = !{!"DescriptorTable", i32 0, !8} +!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{i32 7, !"frame-pointer", i32 2} +!11 = !{i32 1, i32 8} +!12 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"} +!13 = !{!"cs", i32 6, i32 5} +!14 = !{i32 1, i32 5} +!15 = !{!16, !19, !25, null} +!16 = !{!17} +!17 = !{i32 0, ptr @In, !"In", i32 0, i32 0, i32 1, i32 12, i32 0, !18} +!18 = !{i32 1, i32 4} +!19 = !{!20, !21, !23, !24} +!20 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !18} +!21 = !{i32 1, ptr @UAV3, !"UAV3", i32 0, i32 1, i32 1, i32 10, i1 false, i1 false, i1 false, !22} +!22 = !{i32 0, i32 9} +!23 = !{i32 2, ptr @UAV1, !"UAV1", i32 0, i32 2, i32 1, i32 10, i1 false, i1 false, i1 false, !22} +!24 = !{i32 3, ptr @UAV, !"UAV", i32 0, i32 -1, i32 1, i32 10, i1 false, i1 false, i1 false, !22} +!25 = !{!26} +!26 = !{i32 0, ptr @CB, !"CB", i32 665, i32 3, i32 1, i32 4, null} +!27 = !{ptr @CSMain, !"CSMain", null, !15, !28} +!28 = !{i32 0, i64 16, i32 4, !29} +!29 = !{i32 8, i32 8, i32 1} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll new file mode 100644 index 0000000000000..eaf8512c284a7 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -0,0 +1,149 @@ +; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 +; expected-no-diagnostics + +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- --------- +; In texture struct r/o T0 t0 1 +; Out UAV struct r/w U0 u0 1 +; UAV3 UAV struct r/w U1 u1 1 +; UAV1 UAV struct r/w U2 u2 1 +; UAV UAV struct r/w U3 u4294967294 1 +; CB cbuffer NA NA CB0 cb3,space1 1 +; +; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation.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" + +%__cblayout_CB = type <{ float }> +%"StructuredBuffer" = type { i32 } +%"RWStructuredBuffer" = type { i32 } +%"RWStructuredBuffer" = type { float } +%CBuffer.CB = type { float } + +@CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) poison +@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 +@.str = private unnamed_addr constant [3 x i8] c"In\00", align 1 +@.str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1 +@.str.4 = private unnamed_addr constant [4 x i8] c"UAV\00", align 1 +@.str.6 = private unnamed_addr constant [5 x i8] c"UAV1\00", align 1 +@.str.10 = private unnamed_addr constant [5 x i8] c"UAV3\00", align 1 +@In = external constant %"StructuredBuffer" +@Out = external constant %"RWStructuredBuffer" +@UAV3 = external constant %"RWStructuredBuffer" +@UAV1 = external constant %"RWStructuredBuffer" +@UAV = external constant %"RWStructuredBuffer" +@CB = external constant %CBuffer.CB + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32, i32, i32, i32, i1, ptr) #0 + +; 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) + ret void +} + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32, i32, i32, i32, i1, ptr) #0 + +; 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) #0 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1, ptr) #0 + +; 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) #0 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32) #0 + +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) +declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32) #0 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) +declare { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32, i32) #2 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) +declare { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32, 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 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) +declare { 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)), i32) #2 + +; uselistorder directives +uselistorder ptr @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t, { 2, 1, 0 } +uselistorder ptr @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t, { 2, 1, 0 } + +attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) } +attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #2 = { nocallback nofree nosync nounwind willreturn memory(read) } +attributes #3 = { nocallback nofree nosync nounwind willreturn memory(write) } + +!dx.rootsignatures = !{!0} +!llvm.module.flags = !{!9, !10} +!dx.valver = !{!11} +!llvm.ident = !{!12} +!dx.shaderModel = !{!13} +!dx.version = !{!14} +!dx.resources = !{!15} +!dx.entryPoints = !{!26} + +!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 4} +!5 = !{!"DescriptorTable", i32 1, !6} +!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} +!7 = !{!"DescriptorTable", i32 0, !8} +!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{i32 7, !"frame-pointer", i32 2} +!11 = !{i32 1, i32 8} +!12 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"} +!13 = !{!"cs", i32 6, i32 5} +!14 = !{i32 1, i32 5} +!15 = !{!16, !19, !24, null} +!16 = !{!17} +!17 = !{i32 0, ptr @In, !"In", i32 0, i32 0, i32 1, i32 12, i32 0, !18} +!18 = !{i32 1, i32 4} +!19 = !{!20, !21, !22, !23} +!20 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !18} +!21 = !{i32 1, ptr @UAV3, !"UAV3", i32 0, i32 1, i32 1, i32 12, i1 false, i1 false, i1 false, !18} +!22 = !{i32 2, ptr @UAV1, !"UAV1", i32 0, i32 2, i32 1, i32 12, i1 false, i1 false, i1 false, !18} +!23 = !{i32 3, ptr @UAV, !"UAV", i32 0, i32 -2, i32 1, i32 12, i1 false, i1 false, i1 false, !18} +!24 = !{!25} +!25 = !{i32 0, ptr @CB, !"CB", i32 1, i32 3, i32 1, i32 4, null} +!26 = !{ptr @CSMain, !"CSMain", null, !15, !27} +!27 = !{i32 0, i64 16, i32 4, !28} +!28 = !{i32 8, i32 8, i32 1} From aea75dac9df35611a5e8d46be8091621985e8ca7 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 8 Jul 2025 20:51:49 +0000 Subject: [PATCH 025/143] 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" = type { float } +%"RWStructuredBuffer" = 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" +@Out = external constant %"RWStructuredBuffer" + +; 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 e0bc8623dba624c1d3b01bd73102b258df5cc006 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 8 Jul 2025 21:18:45 +0000 Subject: [PATCH 026/143] add preserved --- llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 2 +- llvm/test/CodeGen/DirectX/llc-pipeline.ll | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index b6e8ce7d78b23..a6dfc11c9c44c 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -62,10 +62,10 @@ class DXContainerGlobals : public llvm::ModulePass { void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); AU.addRequired(); - AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); + AU.addPreserved(); } }; diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll index 8d75249dc6ecb..e8612f4213539 100644 --- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll +++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll @@ -40,7 +40,6 @@ ; CHECK-ASM-NEXT: Print Module IR ; CHECK-OBJ-NEXT: DXIL Embedder -; CHECK-OBJ-NEXT: DXIL Root Signature Analysis ; CHECK-OBJ-NEXT: DXContainer Global Emitter ; CHECK-OBJ-NEXT: FunctionPass Manager ; CHECK-OBJ-NEXT: Lazy Machine Block Frequency Analysis From b5a0b32a43b04f9f20efb879a7b8644e937cfaf7 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 10 Jul 2025 17:46:07 +0000 Subject: [PATCH 027/143] addressing comments --- llvm/lib/Target/DirectX/DXILRootSignature.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 07dbd51bed391..ccffa3fd0a3e2 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -106,4 +106,4 @@ class RootSignatureAnalysisPrinter } // namespace dxil } // namespace llvm -#endif +#endif // LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H From 5ccb842c9ba0cf558a30361793f8c33996c5f526 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Fri, 11 Jul 2025 06:27:26 +0000 Subject: [PATCH 028/143] updating --- .../lib/Target/DirectX/DXContainerGlobals.cpp | 2 +- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 2 + .../DXILPostOptimizationValidation.cpp | 160 +++++++++++------- .../DirectX/DXILPostOptimizationValidation.h | 149 +++++----------- llvm/lib/Target/DirectX/DXILPrepare.cpp | 1 - llvm/lib/Target/DirectX/DXILRootSignature.cpp | 3 +- llvm/test/CodeGen/DirectX/llc-pipeline.ll | 1 - .../DirectX/rootsignature-validation-fail.ll | 143 +--------------- 8 files changed, 147 insertions(+), 314 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index a6dfc11c9c44c..97cbb76da2a55 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -65,7 +65,7 @@ class DXContainerGlobals : public llvm::ModulePass { AU.addRequired(); AU.addRequired(); AU.addRequired(); - AU.addPreserved(); + AU.addRequired(); } }; diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 0ec15a629d0a2..db7719e129ad0 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -9,6 +9,7 @@ #include "DXILOpLowering.h" #include "DXILConstants.h" #include "DXILOpBuilder.h" +#include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/SmallVector.h" @@ -945,6 +946,7 @@ class DXILOpLoweringLegacy : public ModulePass { AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); + AU.addPreserved(); } }; char DXILOpLoweringLegacy::ID = 0; diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index a52a04323514c..30a4cc6070971 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -10,9 +10,12 @@ #include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/iterator_range.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" @@ -123,6 +126,70 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) { } } +static uint32_t parameterToRangeType(uint32_t Type) { + switch (Type) { + case llvm::to_underlying(dxbc::RootParameterType::CBV): + return llvm::to_underlying(dxbc::DescriptorRangeType::CBV); + break; + case llvm::to_underlying(dxbc::RootParameterType::SRV): + return llvm::to_underlying(dxbc::DescriptorRangeType::SRV); + break; + case llvm::to_underlying(dxbc::RootParameterType::UAV): + return llvm::to_underlying(dxbc::DescriptorRangeType::UAV); + break; + default: + llvm_unreachable("Root Parameter Type has no Range Type equivalent"); + } +} + +static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) { + + RootSignatureBindingValidation Validation; + + 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); + if (Header.ShaderVisibility != + llvm::to_underlying(dxbc::ShaderVisibility::All) && + Header.ShaderVisibility != llvm::to_underlying(Visibility)) + continue; + + 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); + + llvm::dxil::ResourceInfo::ResourceBinding Binding; + Binding.LowerBound = Desc.ShaderRegister; + Binding.Space = Desc.RegisterSpace; + Binding.Size = 1; + + Validation.addBinding(parameterToRangeType(Type), Binding); + 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) { + llvm::dxil::ResourceInfo::ResourceBinding Binding; + Binding.LowerBound = Range.BaseShaderRegister; + Binding.Space = Range.RegisterSpace; + Binding.Size = Range.NumDescriptors; + Validation.addBinding(Range.RangeType, Binding); + } + break; + } + } + } + + return Validation; +} + std::optional getRootSignature(RootSignatureBindingInfo &RSBI, dxil::ModuleMetadataInfo &MMI) { @@ -135,6 +202,27 @@ getRootSignature(RootSignatureBindingInfo &RSBI, return RootSigDesc; } +static void reportUnboundRegisters( + Module &M, + const std::vector &Bindings, + iterator_range::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()); + } + } +} + static void reportErrors(Module &M, DXILResourceMap &DRM, DXILResourceBindingInfo &DRBI, RootSignatureBindingInfo &RSBI, @@ -150,72 +238,21 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, if (auto RSD = getRootSignature(RSBI, MMI)) { - RootSignatureBindingValidation Validation; - Validation.addRsBindingInfo(*RSD, tripleToVisibility(MMI.ShaderProfile)); - - 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); - } + RootSignatureBindingValidation Validation = initRsBindingValdation(*RSD, tripleToVisibility(MMI.ShaderProfile)); - for (const ResourceInfo &UAV : DRM.uavs()) { - ResourceInfo::ResourceBinding Binding = UAV.getBinding(); - if (!Validation.checkURegBinding(Binding)) - reportRegNotBound(M, "uav", Binding); - } + auto Cbufs = DRM.cbuffers(); + auto SRVs = DRM.srvs(); + auto UAVs = DRM.uavs(); + auto Samplers = DRM.samplers(); - for (const ResourceInfo &Sampler : DRM.samplers()) { - ResourceInfo::ResourceBinding Binding = Sampler.getBinding(); - if (!Validation.checkSamplerBinding(Binding)) - reportRegNotBound(M, "sampler", Binding); - } + reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), Cbufs); + reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), UAVs); + reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler), Samplers); + reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), SRVs); } } } // namespace -void RootSignatureBindingValidation::addRsBindingInfo( - mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) { - 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); - - if (Header.ShaderVisibility == - llvm::to_underlying(dxbc::ShaderVisibility::All) || - Header.ShaderVisibility == llvm::to_underlying(Visibility)) - addRange(Desc, Type); - 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) { - if (Header.ShaderVisibility == - llvm::to_underlying(dxbc::ShaderVisibility::All) || - Header.ShaderVisibility == llvm::to_underlying(Visibility)) - addRange(Range); - } - break; - } - } - } -} - PreservedAnalyses DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) { DXILResourceMap &DRM = MAM.getResult(M); @@ -252,8 +289,8 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { AU.addRequired(); AU.addRequired(); - AU.addRequired(); AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); @@ -269,6 +306,7 @@ INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE, INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass) +INITIALIZE_PASS_DEPENDENCY(RootSignatureAnalysisWrapper) INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE, "DXIL Post Optimization Validation", false, false) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h index 0fa0285425d7e..9a6fe258b02c7 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h @@ -15,126 +15,55 @@ #define LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H #include "DXILRootSignature.h" -#include "llvm/ADT/IntervalMap.h" +#include "llvm/ADT/STLForwardCompat.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/DXILResource.h" +#include "llvm/BinaryFormat/DXContainer.h" #include "llvm/IR/PassManager.h" +#include namespace llvm { -static uint64_t combineUint32ToUint64(uint32_t High, uint32_t Low) { - return (static_cast(High) << 32) | Low; -} - class RootSignatureBindingValidation { - using MapT = - llvm::IntervalMap>; - private: - MapT::Allocator Allocator; - MapT CRegBindingsMap; - MapT TRegBindingsMap; - MapT URegBindingsMap; - MapT SamplersBindingsMap; - - void addRange(const dxbc::RTS0::v2::RootDescriptor &Desc, uint32_t Type) { - assert((Type == llvm::to_underlying(dxbc::RootParameterType::CBV) || - Type == llvm::to_underlying(dxbc::RootParameterType::SRV) || - Type == llvm::to_underlying(dxbc::RootParameterType::UAV)) && - "Invalid Type in add Range Method"); - - llvm::dxil::ResourceInfo::ResourceBinding Binding; - Binding.LowerBound = Desc.ShaderRegister; - Binding.Space = Desc.RegisterSpace; - Binding.Size = 1; - - uint64_t LowRange = - combineUint32ToUint64(Binding.Space, Binding.LowerBound); - uint64_t HighRange = combineUint32ToUint64( - Binding.Space, Binding.LowerBound + Binding.Size - 1); + llvm::SmallVector Bindings; + struct TypeRange { + uint32_t Start; + uint32_t End; + }; + std::unordered_map Ranges; - assert(LowRange <= HighRange && "Invalid range configuration"); - - switch (Type) { - - case llvm::to_underlying(dxbc::RootParameterType::CBV): - CRegBindingsMap.insert(LowRange, HighRange, Binding); - break; - case llvm::to_underlying(dxbc::RootParameterType::SRV): - TRegBindingsMap.insert(LowRange, HighRange, Binding); - break; - case llvm::to_underlying(dxbc::RootParameterType::UAV): - URegBindingsMap.insert(LowRange, HighRange, Binding); - break; +public: + void addBinding(const uint32_t& Type, const dxil::ResourceInfo::ResourceBinding& Binding) { + auto It = Ranges.find(Type); + + if (It == Ranges.end()) { + uint32_t InsertPos = Bindings.size(); + Bindings.push_back(Binding); + Ranges[Type] = {InsertPos, InsertPos + 1}; + } else { + uint32_t InsertPos = It->second.End; + Bindings.insert(Bindings.begin() + InsertPos, Binding); + + It->second.End++; + + for (auto& [type, range] : Ranges) { + if (range.Start > InsertPos) { + range.Start++; + range.End++; + } + } + } } - } - - void addRange(const dxbc::RTS0::v2::DescriptorRange &Range) { - - llvm::dxil::ResourceInfo::ResourceBinding Binding; - Binding.LowerBound = Range.BaseShaderRegister; - Binding.Space = Range.RegisterSpace; - Binding.Size = Range.NumDescriptors; - - uint64_t LowRange = - combineUint32ToUint64(Binding.Space, Binding.LowerBound); - uint64_t HighRange = combineUint32ToUint64( - Binding.Space, Binding.LowerBound + Binding.Size - 1); - - assert(LowRange <= HighRange && "Invalid range configuration"); - - switch (Range.RangeType) { - case llvm::to_underlying(dxbc::DescriptorRangeType::CBV): - CRegBindingsMap.insert(LowRange, HighRange, Binding); - break; - case llvm::to_underlying(dxbc::DescriptorRangeType::SRV): - TRegBindingsMap.insert(LowRange, HighRange, Binding); - break; - case llvm::to_underlying(dxbc::DescriptorRangeType::UAV): - URegBindingsMap.insert(LowRange, HighRange, Binding); - break; - case llvm::to_underlying(dxbc::DescriptorRangeType::Sampler): - SamplersBindingsMap.insert(LowRange, HighRange, Binding); - break; + + llvm::ArrayRef getBindingsOfType(const dxbc::DescriptorRangeType& Type) const { + auto It = Ranges.find(llvm::to_underlying(Type)); + if (It == Ranges.end()) { + return {}; + } + return llvm::ArrayRef(Bindings.data() + It->second.Start, + It->second.End - It->second.Start); } - } - -public: - RootSignatureBindingValidation() - : Allocator(), CRegBindingsMap(Allocator), TRegBindingsMap(Allocator), - URegBindingsMap(Allocator), SamplersBindingsMap(Allocator) {} - - void addRsBindingInfo(mcdxbc::RootSignatureDesc &RSD, - dxbc::ShaderVisibility Visibility); - - bool checkCRegBinding(dxil::ResourceInfo::ResourceBinding Binding) { - return CRegBindingsMap.overlaps( - combineUint32ToUint64(Binding.Space, Binding.LowerBound), - combineUint32ToUint64(Binding.Space, - Binding.LowerBound + Binding.Size - 1)); - } - - bool checkTRegBinding(dxil::ResourceInfo::ResourceBinding Binding) { - return TRegBindingsMap.overlaps( - combineUint32ToUint64(Binding.Space, Binding.LowerBound), - combineUint32ToUint64(Binding.Space, - Binding.LowerBound + Binding.Size - 1)); - } - - bool checkURegBinding(dxil::ResourceInfo::ResourceBinding Binding) { - return URegBindingsMap.overlaps( - combineUint32ToUint64(Binding.Space, Binding.LowerBound), - combineUint32ToUint64(Binding.Space, - Binding.LowerBound + Binding.Size - 1)); - } - - bool checkSamplerBinding(dxil::ResourceInfo::ResourceBinding Binding) { - return SamplersBindingsMap.overlaps( - combineUint32ToUint64(Binding.Space, Binding.LowerBound), - combineUint32ToUint64(Binding.Space, - Binding.LowerBound + Binding.Size - 1)); - } }; class DXILPostOptimizationValidation diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp index c8866bfefdfc5..9c3eba83eba7c 100644 --- a/llvm/lib/Target/DirectX/DXILPrepare.cpp +++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp @@ -300,7 +300,6 @@ class DXILPrepareModule : public ModulePass { DXILPrepareModule() : ModulePass(ID) {} void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); - AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index dfc81626da01f..70cb8bc47e00c 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -684,7 +684,7 @@ bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { void RootSignatureAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addPreserved(); + AU.addRequired(); } char RootSignatureAnalysisWrapper::ID = 0; @@ -692,6 +692,7 @@ char RootSignatureAnalysisWrapper::ID = 0; INITIALIZE_PASS_BEGIN(RootSignatureAnalysisWrapper, "dxil-root-signature-analysis", "DXIL Root Signature Analysis", true, true) +INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass) INITIALIZE_PASS_END(RootSignatureAnalysisWrapper, "dxil-root-signature-analysis", "DXIL Root Signature Analysis", true, true) diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll index 6c5e9be63da58..e8612f4213539 100644 --- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll +++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll @@ -34,7 +34,6 @@ ; CHECK-NEXT: DXIL Root Signature Analysis ; CHECK-NEXT: DXIL Post Optimization Validation ; CHECK-NEXT: DXIL Op Lowering -; CHECK-NEXT: DXIL Root Signature Analysis ; CHECK-NEXT: DXIL Prepare Module ; CHECK-ASM-NEXT: DXIL Metadata Pretty Printer diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll index 54802c9e7ed22..e52647fe888b1 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll @@ -1,132 +1,18 @@ -; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 +; 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=665, register=3) is not defined in Root Signature -; CHECK: error: register srv (space=0, register=0) is not defined in Root Signature -; CHECK: error: register uav (space=0, register=4294967295) is not defined in Root Signature - -; -; Resource Bindings: -; -; Name Type Format Dim ID HLSL Bind Count -; ------------------------------ ---------- ------- ----------- ------- -------------- --------- -; In texture struct r/o T0 t0 1 -; Out UAV struct r/w U0 u0 1 -; UAV3 UAV f32 buf U1 u1 1 -; UAV1 UAV f32 buf U2 u2 1 -; UAV UAV f32 buf U3 u4294967295 1 -; CB cbuffer NA NA CB0 cb3,space665 1 -; -; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation-Fail.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" +; CHECK: error: register CB (space=665, register=3) is not defined in Root Signature %__cblayout_CB = type <{ float }> -%"StructuredBuffer" = type { i32 } -%"RWStructuredBuffer" = type { i32 } -%"RWBuffer" = type { float } -%CBuffer.CB = type { float } -@CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) poison @CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 -@.str = private unnamed_addr constant [3 x i8] c"In\00", align 1 -@.str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1 -@.str.4 = private unnamed_addr constant [4 x i8] c"UAV\00", align 1 -@.str.6 = private unnamed_addr constant [5 x i8] c"UAV1\00", align 1 -@.str.10 = private unnamed_addr constant [5 x i8] c"UAV3\00", align 1 -@In = external constant %"StructuredBuffer" -@Out = external constant %"RWStructuredBuffer" -@UAV3 = external constant %"RWBuffer" -@UAV1 = external constant %"RWBuffer" -@UAV = external constant %"RWBuffer" -@CB = external constant %CBuffer.CB - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32, i32, i32, i32, i1, ptr) #0 -; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) -define void @CSMain() local_unnamed_addr #1 { +define void @CSMain() "hlsl.shader"="compute" { 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 665, 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.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 -1, i32 1, i32 0, i1 false, ptr nonnull @.str.4) - %3 = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 2, i32 1, i32 0, i1 false, ptr nonnull @.str.6) - %4 = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 1, i32 1, i32 0, i1 false, ptr @.str.10) - %5 = tail call i32 @llvm.dx.group.id(i32 0) - %6 = 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) - %7 = extractvalue { float, float, float, float } %6, 0 - %conv.i = uitofp i32 %5 to float - %add.i = fadd reassoc nnan ninf nsz arcp afn float %7, %conv.i - %8 = 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) - %9 = extractvalue { i32, i1 } %8, 0 - %conv1.i = sitofp i32 %9 to float - %add2.i = fadd reassoc nnan ninf nsz arcp afn float %add.i, %conv1.i - %10 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %2, i32 0) - %11 = extractvalue { float, i1 } %10, 0 - %add4.i = fadd reassoc nnan ninf nsz arcp afn float %add2.i, %11 - %12 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %3, i32 0) - %13 = extractvalue { float, i1 } %12, 0 - %add6.i = fadd reassoc nnan ninf nsz arcp afn float %add4.i, %13 - %14 = call { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0) %4, i32 0) - %15 = extractvalue { float, i1 } %14, 0 - %add8.i = fadd reassoc nnan ninf nsz arcp afn float %add6.i, %15 - %conv9.i = fptosi float %add8.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 %conv9.i) + %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str) ret void } -; Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) -declare i32 @llvm.dx.group.id(i32) #2 - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32, i32, i32, i32, i1, ptr) #0 - -; 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) #0 - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32, i32, i32, i32, i1, ptr) #0 - -; 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) #0 - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32) #0 - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #0 - -; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) -declare { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32, i32) #3 - -; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) -declare { float, i1 } @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t(target("dx.TypedBuffer", float, 1, 0, 0), i32) #3 - -; 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) #4 - -; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) -declare { 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)), i32) #3 - -; uselistorder directives -uselistorder ptr @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 } -uselistorder ptr @llvm.dx.resource.load.typedbuffer.f32.tdx.TypedBuffer_f32_1_0_0t, { 2, 1, 0 } - -attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) } -attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -attributes #2 = { mustprogress nofree nosync nounwind willreturn memory(none) } -attributes #3 = { nocallback nofree nosync nounwind willreturn memory(read) } -attributes #4 = { nocallback nofree nosync nounwind willreturn memory(write) } - !dx.rootsignatures = !{!0} -!llvm.module.flags = !{!9, !10} -!dx.valver = !{!11} -!llvm.ident = !{!12} -!dx.shaderModel = !{!13} -!dx.version = !{!14} -!dx.resources = !{!15} -!dx.entryPoints = !{!27} !0 = !{ptr @CSMain, !1, i32 2} !1 = !{!2, !3, !5, !7} @@ -137,24 +23,3 @@ attributes #4 = { nocallback nofree nosync nounwind willreturn memory(write) } !6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} !7 = !{!"DescriptorTable", i32 0, !8} !8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2} -!9 = !{i32 1, !"wchar_size", i32 4} -!10 = !{i32 7, !"frame-pointer", i32 2} -!11 = !{i32 1, i32 8} -!12 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"} -!13 = !{!"cs", i32 6, i32 5} -!14 = !{i32 1, i32 5} -!15 = !{!16, !19, !25, null} -!16 = !{!17} -!17 = !{i32 0, ptr @In, !"In", i32 0, i32 0, i32 1, i32 12, i32 0, !18} -!18 = !{i32 1, i32 4} -!19 = !{!20, !21, !23, !24} -!20 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !18} -!21 = !{i32 1, ptr @UAV3, !"UAV3", i32 0, i32 1, i32 1, i32 10, i1 false, i1 false, i1 false, !22} -!22 = !{i32 0, i32 9} -!23 = !{i32 2, ptr @UAV1, !"UAV1", i32 0, i32 2, i32 1, i32 10, i1 false, i1 false, i1 false, !22} -!24 = !{i32 3, ptr @UAV, !"UAV", i32 0, i32 -1, i32 1, i32 10, i1 false, i1 false, i1 false, !22} -!25 = !{!26} -!26 = !{i32 0, ptr @CB, !"CB", i32 665, i32 3, i32 1, i32 4, null} -!27 = !{ptr @CSMain, !"CSMain", null, !15, !28} -!28 = !{i32 0, i64 16, i32 4, !29} -!29 = !{i32 8, i32 8, i32 1} From 5423aba8038731f6159266304fa8cad983b6af7c Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 14 Jul 2025 18:40:30 +0000 Subject: [PATCH 029/143] format --- .../DXILPostOptimizationValidation.cpp | 50 ++++++++------ .../DirectX/DXILPostOptimizationValidation.h | 68 ++++++++++--------- 2 files changed, 64 insertions(+), 54 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 30a4cc6070971..035a5bd225ac8 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -130,19 +130,21 @@ static uint32_t parameterToRangeType(uint32_t Type) { switch (Type) { case llvm::to_underlying(dxbc::RootParameterType::CBV): return llvm::to_underlying(dxbc::DescriptorRangeType::CBV); - break; + break; case llvm::to_underlying(dxbc::RootParameterType::SRV): - return llvm::to_underlying(dxbc::DescriptorRangeType::SRV); - break; + return llvm::to_underlying(dxbc::DescriptorRangeType::SRV); + break; case llvm::to_underlying(dxbc::RootParameterType::UAV): - return llvm::to_underlying(dxbc::DescriptorRangeType::UAV); - break; + return llvm::to_underlying(dxbc::DescriptorRangeType::UAV); + break; default: llvm_unreachable("Root Parameter Type has no Range Type equivalent"); } } -static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) { +static RootSignatureBindingValidation +initRsBindingValdation(const mcdxbc::RootSignatureDesc &RSD, + dxbc::ShaderVisibility Visibility) { RootSignatureBindingValidation Validation; @@ -152,10 +154,10 @@ static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootS const auto &Header = RSD.ParametersContainer.getHeader(I); if (Header.ShaderVisibility != - llvm::to_underlying(dxbc::ShaderVisibility::All) && - Header.ShaderVisibility != llvm::to_underlying(Visibility)) - continue; - + llvm::to_underlying(dxbc::ShaderVisibility::All) && + Header.ShaderVisibility != llvm::to_underlying(Visibility)) + continue; + switch (Type) { case llvm::to_underlying(dxbc::RootParameterType::SRV): case llvm::to_underlying(dxbc::RootParameterType::UAV): @@ -167,7 +169,7 @@ static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootS Binding.LowerBound = Desc.ShaderRegister; Binding.Space = Desc.RegisterSpace; Binding.Size = 1; - + Validation.addBinding(parameterToRangeType(Type), Binding); break; } @@ -176,11 +178,11 @@ static RootSignatureBindingValidation initRsBindingValdation(const mcdxbc::RootS RSD.ParametersContainer.getDescriptorTable(Loc); for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { - llvm::dxil::ResourceInfo::ResourceBinding Binding; - Binding.LowerBound = Range.BaseShaderRegister; - Binding.Space = Range.RegisterSpace; - Binding.Size = Range.NumDescriptors; - Validation.addBinding(Range.RangeType, Binding); + llvm::dxil::ResourceInfo::ResourceBinding Binding; + Binding.LowerBound = Range.BaseShaderRegister; + Binding.Space = Range.RegisterSpace; + Binding.Size = Range.NumDescriptors; + Validation.addBinding(Range.RangeType, Binding); } break; } @@ -238,17 +240,23 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, if (auto RSD = getRootSignature(RSBI, MMI)) { - RootSignatureBindingValidation Validation = initRsBindingValdation(*RSD, tripleToVisibility(MMI.ShaderProfile)); + RootSignatureBindingValidation Validation = + initRsBindingValdation(*RSD, tripleToVisibility(MMI.ShaderProfile)); auto Cbufs = DRM.cbuffers(); auto SRVs = DRM.srvs(); auto UAVs = DRM.uavs(); auto Samplers = DRM.samplers(); - reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), Cbufs); - reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), UAVs); - reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler), Samplers); - reportUnboundRegisters(M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), SRVs); + reportUnboundRegisters( + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), Cbufs); + reportUnboundRegisters( + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), UAVs); + reportUnboundRegisters( + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler), + Samplers); + reportUnboundRegisters( + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), SRVs); } } } // namespace diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h index 9a6fe258b02c7..f0e4c4d9d7164 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h @@ -26,44 +26,46 @@ namespace llvm { class RootSignatureBindingValidation { private: - llvm::SmallVector Bindings; - struct TypeRange { - uint32_t Start; - uint32_t End; - }; - std::unordered_map Ranges; + llvm::SmallVector Bindings; + struct TypeRange { + uint32_t Start; + uint32_t End; + }; + std::unordered_map Ranges; public: - void addBinding(const uint32_t& Type, const dxil::ResourceInfo::ResourceBinding& Binding) { - auto It = Ranges.find(Type); - - if (It == Ranges.end()) { - uint32_t InsertPos = Bindings.size(); - Bindings.push_back(Binding); - Ranges[Type] = {InsertPos, InsertPos + 1}; - } else { - uint32_t InsertPos = It->second.End; - Bindings.insert(Bindings.begin() + InsertPos, Binding); - - It->second.End++; - - for (auto& [type, range] : Ranges) { - if (range.Start > InsertPos) { - range.Start++; - range.End++; - } - } + void addBinding(const uint32_t &Type, + const dxil::ResourceInfo::ResourceBinding &Binding) { + auto It = Ranges.find(Type); + + if (It == Ranges.end()) { + uint32_t InsertPos = Bindings.size(); + Bindings.push_back(Binding); + Ranges[Type] = {InsertPos, InsertPos + 1}; + } else { + uint32_t InsertPos = It->second.End; + Bindings.insert(Bindings.begin() + InsertPos, Binding); + + It->second.End++; + + for (auto &[type, range] : Ranges) { + if (range.Start > InsertPos) { + range.Start++; + range.End++; } + } } - - llvm::ArrayRef getBindingsOfType(const dxbc::DescriptorRangeType& Type) const { - auto It = Ranges.find(llvm::to_underlying(Type)); - if (It == Ranges.end()) { - return {}; - } - return llvm::ArrayRef(Bindings.data() + It->second.Start, - It->second.End - It->second.Start); + } + + llvm::ArrayRef + getBindingsOfType(const dxbc::DescriptorRangeType &Type) const { + auto It = Ranges.find(llvm::to_underlying(Type)); + if (It == Ranges.end()) { + return {}; } + return llvm::ArrayRef( + Bindings.data() + It->second.Start, It->second.End - It->second.Start); + } }; class DXILPostOptimizationValidation From a7637a7848b6a3bfd60ab366568f6f708878287e Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 14 Jul 2025 19:31:23 +0000 Subject: [PATCH 030/143] adding tests --- .../DXILPostOptimizationValidation.cpp | 7 - ... rootsignature-validation-fail-cbuffer.ll} | 9 ++ .../rootsignature-validation-fail-sampler.ll | 31 ++++ .../rootsignature-validation-fail-srv.ll | 30 ++++ .../rootsignature-validation-fail-uav.ll | 30 ++++ .../DirectX/rootsignature-validation.ll | 148 +++--------------- 6 files changed, 119 insertions(+), 136 deletions(-) rename llvm/test/CodeGen/DirectX/{rootsignature-validation-fail.ll => rootsignature-validation-fail-cbuffer.ll} (70%) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 035a5bd225ac8..f9218d571365c 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -7,15 +7,11 @@ //===----------------------------------------------------------------------===// #include "DXILPostOptimizationValidation.h" -#include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" -#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/iterator_range.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" @@ -130,13 +126,10 @@ static uint32_t parameterToRangeType(uint32_t Type) { switch (Type) { case llvm::to_underlying(dxbc::RootParameterType::CBV): return llvm::to_underlying(dxbc::DescriptorRangeType::CBV); - break; case llvm::to_underlying(dxbc::RootParameterType::SRV): return llvm::to_underlying(dxbc::DescriptorRangeType::SRV); - break; case llvm::to_underlying(dxbc::RootParameterType::UAV): return llvm::to_underlying(dxbc::DescriptorRangeType::UAV); - break; default: llvm_unreachable("Root Parameter Type has no Range Type equivalent"); } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll similarity index 70% rename from llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll rename to llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll index e52647fe888b1..cd8a87d04f31a 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll @@ -2,12 +2,21 @@ ; CHECK: error: register CB (space=665, register=3) is not defined in Root Signature +; Root Signature( +; CBV(b3, space=666, 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) + %__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(b3, space665) { +; float a; +; } %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str) ret void } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll new file mode 100644 index 0000000000000..8e7e0de96ccff --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.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: register Smp (space=2, register=3) is not defined in Root Signature + +; Root Signature( +; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) +; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) + +@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: +; SamplerState S1 : register(s3, space2); + %Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str) + + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3, !5, !7} +!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} +!3 = !{!"DescriptorTable", i32 1, !4} +!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} +!5 = !{!"DescriptorTable", i32 0, !6} +!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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-fail-srv.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll new file mode 100644 index 0000000000000..166ac51a7d0de --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll @@ -0,0 +1,30 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s + +; CHECK: error: register SB (space=0, register=0) is not defined in Root Signature + +; Root Signature( +; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) +; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) + +@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: +; StructuredBuffer In : register(t0, space0); + %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) + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3, !5, !7} +!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} +!3 = !{!"DescriptorTable", i32 1, !4} +!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} +!5 = !{!"DescriptorTable", i32 0, !6} +!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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-fail-uav.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll new file mode 100644 index 0000000000000..8a1daea8f7d24 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll @@ -0,0 +1,30 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s + +; CHECK: error: register RWB (space=0, register=4294967295) is not defined in Root Signature + +; Root Signature( +; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) +; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) + +@RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: +; RWBuffer UAV : register(u4294967295); + %RWB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 -1, i32 1, i32 0, i1 false, ptr nonnull @RWB.str) + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3, !5, !7} +!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} +!3 = !{!"DescriptorTable", i32 1, !4} +!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} +!5 = !{!"DescriptorTable", i32 0, !6} +!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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..750679bf743c5 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -1,149 +1,39 @@ ; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 ; expected-no-diagnostics -; -; Resource Bindings: -; -; Name Type Format Dim ID HLSL Bind Count -; ------------------------------ ---------- ------- ----------- ------- -------------- --------- -; In texture struct r/o T0 t0 1 -; Out UAV struct r/w U0 u0 1 -; UAV3 UAV struct r/w U1 u1 1 -; UAV1 UAV struct r/w U2 u2 1 -; UAV UAV struct r/w U3 u4294967294 1 -; CB cbuffer NA NA CB0 cb3,space1 1 -; -; ModuleID = '../clang/test/SemaHLSL/RootSignature-Validation.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" + +; 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) %__cblayout_CB = type <{ float }> -%"StructuredBuffer" = type { i32 } -%"RWStructuredBuffer" = type { i32 } -%"RWStructuredBuffer" = type { float } -%CBuffer.CB = type { float } -@CB.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) poison @CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 -@.str = private unnamed_addr constant [3 x i8] c"In\00", align 1 -@.str.2 = private unnamed_addr constant [4 x i8] c"Out\00", align 1 -@.str.4 = private unnamed_addr constant [4 x i8] c"UAV\00", align 1 -@.str.6 = private unnamed_addr constant [5 x i8] c"UAV1\00", align 1 -@.str.10 = private unnamed_addr constant [5 x i8] c"UAV3\00", align 1 -@In = external constant %"StructuredBuffer" -@Out = external constant %"RWStructuredBuffer" -@UAV3 = external constant %"RWStructuredBuffer" -@UAV1 = external constant %"RWStructuredBuffer" -@UAV = external constant %"RWStructuredBuffer" -@CB = external constant %CBuffer.CB - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding.tdx.CBuffer_tdx.Layout_s___cblayout_CBs_4_0tt(i32, i32, i32, i32, i1, ptr) #0 +@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 +@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1 +@RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1 -; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) -define void @CSMain() local_unnamed_addr #1 { +define void @CSMain() "hlsl.shader"="compute" { 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) - ret void -} - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32, i32, i32, i32, i1, ptr) #0 - -; 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) #0 - -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32, i32, i32, i32, i1, ptr) #0 - -; 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) #0 -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32) #0 + %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.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 @RWB.str) -; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(none) -declare ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32) #0 - -; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) -declare { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_0_0t(target("dx.RawBuffer", i32, 0, 0), i32, i32) #2 - -; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) -declare { float, i1 } @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t(target("dx.RawBuffer", float, 1, 0), i32, 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 - -; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) -declare { 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)), i32) #2 - -; uselistorder directives -uselistorder ptr @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t, { 2, 1, 0 } -uselistorder ptr @llvm.dx.resource.load.rawbuffer.f32.tdx.RawBuffer_f32_1_0t, { 2, 1, 0 } - -attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) } -attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="8,8,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -attributes #2 = { nocallback nofree nosync nounwind willreturn memory(read) } -attributes #3 = { nocallback nofree nosync nounwind willreturn memory(write) } + ret void +} !dx.rootsignatures = !{!0} -!llvm.module.flags = !{!9, !10} -!dx.valver = !{!11} -!llvm.ident = !{!12} -!dx.shaderModel = !{!13} -!dx.version = !{!14} -!dx.resources = !{!15} -!dx.entryPoints = !{!26} !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 4} -!5 = !{!"DescriptorTable", i32 1, !6} -!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} +!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} -!9 = !{i32 1, !"wchar_size", i32 4} -!10 = !{i32 7, !"frame-pointer", i32 2} -!11 = !{i32 1, i32 8} -!12 = !{!"clang version 21.0.0git (https://github.com/joaosaffran/llvm-project.git c16f15b4cd469a3f6efc2e4b0e098190d7fd0787)"} -!13 = !{!"cs", i32 6, i32 5} -!14 = !{i32 1, i32 5} -!15 = !{!16, !19, !24, null} -!16 = !{!17} -!17 = !{i32 0, ptr @In, !"In", i32 0, i32 0, i32 1, i32 12, i32 0, !18} -!18 = !{i32 1, i32 4} -!19 = !{!20, !21, !22, !23} -!20 = !{i32 0, ptr @Out, !"Out", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, !18} -!21 = !{i32 1, ptr @UAV3, !"UAV3", i32 0, i32 1, i32 1, i32 12, i1 false, i1 false, i1 false, !18} -!22 = !{i32 2, ptr @UAV1, !"UAV1", i32 0, i32 2, i32 1, i32 12, i1 false, i1 false, i1 false, !18} -!23 = !{i32 3, ptr @UAV, !"UAV", i32 0, i32 -2, i32 1, i32 12, i1 false, i1 false, i1 false, !18} -!24 = !{!25} -!25 = !{i32 0, ptr @CB, !"CB", i32 1, i32 3, i32 1, i32 4, null} -!26 = !{ptr @CSMain, !"CSMain", null, !15, !27} -!27 = !{i32 0, i64 16, i32 4, !28} -!28 = !{i32 8, i32 8, i32 1} From da42c0c2f6af1ee68f85779fe307bda2a7af597f Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 14 Jul 2025 20:30:37 +0000 Subject: [PATCH 031/143] clean up --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h index f0e4c4d9d7164..cabf3d95e66e9 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h @@ -20,7 +20,6 @@ #include "llvm/Analysis/DXILResource.h" #include "llvm/BinaryFormat/DXContainer.h" #include "llvm/IR/PassManager.h" -#include namespace llvm { From 5af919957fbe8dd2617ffb8452ef7aa65309a886 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 14 Jul 2025 23:32:44 +0000 Subject: [PATCH 032/143] 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 &Bindings, + iterator_range::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(Handle); + auto *Texture = dyn_cast_or_null(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 Date: Tue, 15 Jul 2025 00:21:44 +0000 Subject: [PATCH 033/143] 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" = type { float } -%"RWStructuredBuffer" = 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" -@Out = external constant %"RWStructuredBuffer" - -; 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 edb015dcae3bfb5d3168321b288d0b8cd1451ff9 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 15 Jul 2025 00:37:40 +0000 Subject: [PATCH 034/143] address comments --- .../DXILPostOptimizationValidation.cpp | 32 ++++++++++--------- .../DirectX/DXILPostOptimizationValidation.h | 8 ++--- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index f9218d571365c..c01f52e07d230 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -10,6 +10,7 @@ #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" #include "llvm/IR/DiagnosticInfo.h" @@ -136,8 +137,8 @@ static uint32_t parameterToRangeType(uint32_t Type) { } static RootSignatureBindingValidation -initRsBindingValdation(const mcdxbc::RootSignatureDesc &RSD, - dxbc::ShaderVisibility Visibility) { +initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, + dxbc::ShaderVisibility Visibility) { RootSignatureBindingValidation Validation; @@ -199,15 +200,17 @@ getRootSignature(RootSignatureBindingInfo &RSBI, static void reportUnboundRegisters( Module &M, - const std::vector &Bindings, - iterator_range::iterator> &Resources) { + const llvm::ArrayRef &Bindings, + const iterator_range::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) { + ResBinding.LowerBound + ResBinding.Size - 1 < + Binding.LowerBound + Binding.Size) { Bound = true; break; } @@ -234,22 +237,20 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, if (auto RSD = getRootSignature(RSBI, MMI)) { RootSignatureBindingValidation Validation = - initRsBindingValdation(*RSD, tripleToVisibility(MMI.ShaderProfile)); - - auto Cbufs = DRM.cbuffers(); - auto SRVs = DRM.srvs(); - auto UAVs = DRM.uavs(); - auto Samplers = DRM.samplers(); + initRSBindingValidation(*RSD, tripleToVisibility(MMI.ShaderProfile)); reportUnboundRegisters( - M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), Cbufs); + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), + DRM.cbuffers()); reportUnboundRegisters( - M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), UAVs); + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), + DRM.uavs()); reportUnboundRegisters( M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler), - Samplers); + DRM.samplers()); reportUnboundRegisters( - M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), SRVs); + M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), + DRM.srvs()); } } } // namespace @@ -307,6 +308,7 @@ INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE, INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass) INITIALIZE_PASS_DEPENDENCY(RootSignatureAnalysisWrapper) INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE, "DXIL Post Optimization Validation", false, false) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h index cabf3d95e66e9..789bbe4573964 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h @@ -47,10 +47,10 @@ class RootSignatureBindingValidation { It->second.End++; - for (auto &[type, range] : Ranges) { - if (range.Start > InsertPos) { - range.Start++; - range.End++; + for (auto &[Type, Range] : Ranges) { + if (Range.Start > InsertPos) { + Range.Start++; + Range.End++; } } } From 9f3888ead4ed2934400cbf4ef3b92bdccc56645b Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 15 Jul 2025 18:17:45 +0000 Subject: [PATCH 035/143] 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} From 578a03bd33359497d0aa4820f2ceacad0b5c24e2 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 15 Jul 2025 21:28:24 +0000 Subject: [PATCH 036/143] clean --- llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 97cbb76da2a55..b6e8ce7d78b23 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -62,10 +62,10 @@ class DXContainerGlobals : public llvm::ModulePass { void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); - AU.addRequired(); } }; From b4a0e16bf068d35d563c5fc02bbe7f9875528b92 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 17 Jul 2025 00:10:17 +0000 Subject: [PATCH 037/143] moving code arround --- .../Frontend/HLSL/RootSignatureValidations.h | 46 ++++++ .../llvm/MC/DXContainerRootSignature.h | 3 + .../HLSL/RootSignatureValidations.cpp | 26 ++++ .../DXILPostOptimizationValidation.cpp | 140 +++++++++++------- .../DirectX/DXILPostOptimizationValidation.h | 50 ------- .../rootsignature-validation-fail-cbuffer.ll | 2 +- ...rootsignature-validation-fail-constants.ll | 2 +- .../rootsignature-validation-fail-sampler.ll | 2 +- .../rootsignature-validation-fail-srv.ll | 2 +- .../rootsignature-validation-fail-uav.ll | 2 +- 10 files changed, 164 insertions(+), 111 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index ea63a253b6661..e298cb4250db9 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -16,6 +16,7 @@ #include "llvm/ADT/IntervalMap.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" +#include "llvm/Support/DXILABI.h" namespace llvm { namespace hlsl { @@ -136,6 +137,51 @@ struct OverlappingRanges { llvm::SmallVector findOverlappingRanges(llvm::SmallVector &Infos); +class RootSignatureBindingValidation { +private: + llvm::SmallVector Bindings; + struct TypeRange { + uint32_t Start; + uint32_t End; + }; + std::unordered_map Ranges; + +public: + void addBinding(dxil::ResourceClass Type, const RangeInfo &Binding) { + auto It = Ranges.find(Type); + + if (It == Ranges.end()) { + uint32_t InsertPos = Bindings.size(); + Bindings.push_back(Binding); + Ranges[Type] = {InsertPos, InsertPos + 1}; + } else { + uint32_t InsertPos = It->second.End; + Bindings.insert(Bindings.begin() + InsertPos, Binding); + + It->second.End++; + + for (auto &[Type, Range] : Ranges) { + if (Range.Start > InsertPos) { + Range.Start++; + Range.End++; + } + } + } + } + + llvm::ArrayRef + getBindingsOfType(const dxil::ResourceClass &Type) const { + auto It = Ranges.find(Type); + if (It == Ranges.end()) { + return {}; + } + return llvm::ArrayRef(Bindings.data() + It->second.Start, + It->second.End - It->second.Start); + } +}; +llvm::SmallVector +findUnboundRanges(const llvm::SmallVectorImpl &Ranges, + const llvm::ArrayRef &Bindings); } // namespace rootsig } // namespace hlsl } // namespace llvm diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h index 4b6b42f7d74f7..eb4524d547892 100644 --- a/llvm/include/llvm/MC/DXContainerRootSignature.h +++ b/llvm/include/llvm/MC/DXContainerRootSignature.h @@ -5,6 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +#ifndef LLVM_MC_DXCONTAINERROOTSIGNATURE_H +#define LLVM_MC_DXCONTAINERROOTSIGNATURE_H #include "llvm/BinaryFormat/DXContainer.h" #include @@ -116,3 +118,4 @@ struct RootSignatureDesc { }; } // namespace mcdxbc } // namespace llvm +#endif // LLVM_MC_DXCONTAINERROOTSIGNATURE_H diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 278c42e97667b..77492eaf13aee 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -316,6 +316,32 @@ findOverlappingRanges(llvm::SmallVector &Infos) { return Overlaps; } +llvm::SmallVector +findUnboundRanges(const llvm::SmallVectorImpl &Ranges, + const llvm::ArrayRef &Bindings) { + llvm::SmallVector Unbounds; + for (const auto &Range : Ranges) { + bool Bound = false; + // hlsl::rootsig::RangeInfo Range; + // Range.Space = ResBinding.Space; + // Range.LowerBound = ResBinding.LowerBound; + // Range.UpperBound = Range.LowerBound + ResBinding.Size - 1; + + for (const auto &Binding : Bindings) { + if (Range.Space == Binding.Space && + Range.LowerBound >= Binding.LowerBound && + Range.UpperBound <= Binding.UpperBound) { + Bound = true; + break; + } + } + if (!Bound) { + Unbounds.push_back(Range); + } + } + return Unbounds; +} + } // namespace rootsig } // namespace hlsl } // namespace llvm diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index eb3ad6a6e56ee..9b89646050e17 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "DXILPostOptimizationValidation.h" +#include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/STLForwardCompat.h" @@ -15,11 +16,14 @@ #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" #include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" +#include "llvm/MC/DXContainerRootSignature.h" +#include "llvm/Support/DXILABI.h" #define DEBUG_TYPE "dxil-post-optimization-validation" @@ -27,6 +31,48 @@ using namespace llvm; using namespace llvm::dxil; namespace { +static const char *ResourceClassToString(llvm::dxil::ResourceClass Class) { + switch (Class) { + case ResourceClass::SRV: + return "SRV"; + case ResourceClass::UAV: + return "UAV"; + case ResourceClass::CBuffer: + return "CBuffer"; + case ResourceClass::Sampler: + return "Sampler"; + } +} + +static ResourceClass RangeToResourceClass(uint32_t RangeType) { + using namespace dxbc; + switch (static_cast(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; + } +} + +ResourceClass ParameterToResourceClass(uint32_t Type) { + using namespace dxbc; + switch (Type) { + case llvm::to_underlying(RootParameterType::Constants32Bit): + return ResourceClass::CBuffer; + case llvm::to_underlying(RootParameterType::SRV): + return ResourceClass::SRV; + case llvm::to_underlying(RootParameterType::UAV): + return ResourceClass::UAV; + case llvm::to_underlying(RootParameterType::CBV): + return ResourceClass::CBuffer; + default: + llvm_unreachable("Unknown RootParameterType"); + } +} static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) { for (const auto &UAV : DRM.uavs()) { @@ -87,12 +133,13 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } -static void reportRegNotBound(Module &M, Twine Type, - ResourceInfo::ResourceBinding Binding) { +static void reportRegNotBound(Module &M, + llvm::hlsl::rootsig::RangeInfo Unbound) { SmallString<128> Message; raw_svector_ostream OS(Message); - OS << "register " << Type << " (space=" << Binding.Space - << ", register=" << Binding.LowerBound << ")" + OS << "register " << ResourceClassToString(Unbound.Class) + << " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound + << ")" << " is not defined in Root Signature"; M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } @@ -125,24 +172,11 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) { } } -static uint32_t parameterToRangeType(uint32_t Type) { - switch (Type) { - case llvm::to_underlying(dxbc::RootParameterType::CBV): - return llvm::to_underlying(dxbc::DescriptorRangeType::CBV); - case llvm::to_underlying(dxbc::RootParameterType::SRV): - return llvm::to_underlying(dxbc::DescriptorRangeType::SRV); - case llvm::to_underlying(dxbc::RootParameterType::UAV): - return llvm::to_underlying(dxbc::DescriptorRangeType::UAV); - default: - llvm_unreachable("Root Parameter Type has no Range Type equivalent"); - } -} - -static RootSignatureBindingValidation +static hlsl::rootsig::RootSignatureBindingValidation initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) { - RootSignatureBindingValidation Validation; + hlsl::rootsig::RootSignatureBindingValidation Validation; for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) { const auto &[Type, Loc] = @@ -159,14 +193,13 @@ initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, dxbc::RTS0::v1::RootConstants Const = RSD.ParametersContainer.getConstant(Loc); - llvm::dxil::ResourceInfo::ResourceBinding Binding; + hlsl::rootsig::RangeInfo Binding; Binding.LowerBound = Const.ShaderRegister; Binding.Space = Const.RegisterSpace; - Binding.Size = 1; + Binding.UpperBound = Binding.LowerBound; // Root Constants Bind to CBuffers - Validation.addBinding(llvm::to_underlying(dxbc::DescriptorRangeType::CBV), - Binding); + Validation.addBinding(ResourceClass::CBuffer, Binding); break; } @@ -177,12 +210,12 @@ initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, dxbc::RTS0::v2::RootDescriptor Desc = RSD.ParametersContainer.getRootDescriptor(Loc); - llvm::dxil::ResourceInfo::ResourceBinding Binding; + hlsl::rootsig::RangeInfo Binding; Binding.LowerBound = Desc.ShaderRegister; Binding.Space = Desc.RegisterSpace; - Binding.Size = 1; + Binding.UpperBound = Binding.LowerBound; - Validation.addBinding(parameterToRangeType(Type), Binding); + Validation.addBinding(ParameterToResourceClass(Type), Binding); break; } case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): { @@ -190,11 +223,11 @@ initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, RSD.ParametersContainer.getDescriptorTable(Loc); for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { - llvm::dxil::ResourceInfo::ResourceBinding Binding; + hlsl::rootsig::RangeInfo Binding; Binding.LowerBound = Range.BaseShaderRegister; Binding.Space = Range.RegisterSpace; - Binding.Size = Range.NumDescriptors; - Validation.addBinding(Range.RangeType, Binding); + Binding.UpperBound = Binding.LowerBound + Range.NumDescriptors - 1; + Validation.addBinding(RangeToResourceClass(Range.RangeType), Binding); } break; } @@ -218,25 +251,26 @@ getRootSignature(RootSignatureBindingInfo &RSBI, static void reportUnboundRegisters( Module &M, - const llvm::ArrayRef &Bindings, + const llvm::hlsl::rootsig::RootSignatureBindingValidation &Validation, + ResourceClass Class, const iterator_range::iterator> &Resources) { + SmallVector Ranges; 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 + ResBinding.Size - 1 < - Binding.LowerBound + Binding.Size) { - Bound = true; - break; - } - } - if (!Bound) { - reportRegNotBound(M, Res->getName(), Res->getBinding()); - } + hlsl::rootsig::RangeInfo Range; + Range.Space = ResBinding.Space; + Range.LowerBound = ResBinding.LowerBound; + Range.UpperBound = Range.LowerBound + ResBinding.Size - 1; + Range.Class = Class; + Ranges.push_back(Range); } + + SmallVector Unbounds = + hlsl::rootsig::findUnboundRanges(Ranges, + Validation.getBindingsOfType(Class)); + for (const auto &Unbound : Unbounds) + reportRegNotBound(M, Unbound); } static void reportErrors(Module &M, DXILResourceMap &DRM, @@ -254,21 +288,15 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, if (auto RSD = getRootSignature(RSBI, MMI)) { - RootSignatureBindingValidation Validation = + llvm::hlsl::rootsig::RootSignatureBindingValidation Validation = initRSBindingValidation(*RSD, tripleToVisibility(MMI.ShaderProfile)); - reportUnboundRegisters( - M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::CBV), - DRM.cbuffers()); - reportUnboundRegisters( - M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::UAV), - DRM.uavs()); - reportUnboundRegisters( - M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::Sampler), - DRM.samplers()); - reportUnboundRegisters( - M, Validation.getBindingsOfType(dxbc::DescriptorRangeType::SRV), - DRM.srvs()); + 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()); } } } // namespace diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h index 789bbe4573964..2535c6979c5d5 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h @@ -14,59 +14,9 @@ #ifndef LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H #define LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H -#include "DXILRootSignature.h" -#include "llvm/ADT/STLForwardCompat.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/DXILResource.h" -#include "llvm/BinaryFormat/DXContainer.h" #include "llvm/IR/PassManager.h" namespace llvm { - -class RootSignatureBindingValidation { -private: - llvm::SmallVector Bindings; - struct TypeRange { - uint32_t Start; - uint32_t End; - }; - std::unordered_map Ranges; - -public: - void addBinding(const uint32_t &Type, - const dxil::ResourceInfo::ResourceBinding &Binding) { - auto It = Ranges.find(Type); - - if (It == Ranges.end()) { - uint32_t InsertPos = Bindings.size(); - Bindings.push_back(Binding); - Ranges[Type] = {InsertPos, InsertPos + 1}; - } else { - uint32_t InsertPos = It->second.End; - Bindings.insert(Bindings.begin() + InsertPos, Binding); - - It->second.End++; - - for (auto &[Type, Range] : Ranges) { - if (Range.Start > InsertPos) { - Range.Start++; - Range.End++; - } - } - } - } - - llvm::ArrayRef - getBindingsOfType(const dxbc::DescriptorRangeType &Type) const { - auto It = Ranges.find(llvm::to_underlying(Type)); - if (It == Ranges.end()) { - return {}; - } - return llvm::ArrayRef( - Bindings.data() + It->second.Start, It->second.End - It->second.Start); - } -}; - class DXILPostOptimizationValidation : public PassInfoMixin { public: diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll index cd8a87d04f31a..ac97d79c6a2eb 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll @@ -1,6 +1,6 @@ ; 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=665, register=3) is not defined in Root Signature +; CHECK: error: register CBuffer (space=665, register=3) is not defined in Root Signature ; Root Signature( ; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll index b7e1172c7304a..fadc0db046ec7 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.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: register CB (space=666, register=2) is not defined in Root Signature +; CHECK: error: register CBuffer (space=666, register=2) is not defined in Root Signature ; Root Signature(RootConstants(num32BitConstants=4, b2)) %__cblayout_CB = type <{ float }> diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll index 8e7e0de96ccff..2ec3505cbec41 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll @@ -1,6 +1,6 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s -; CHECK: error: register Smp (space=2, register=3) is not defined in Root Signature +; CHECK: error: register Sampler (space=2, register=3) is not defined in Root Signature ; Root Signature( ; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll index 166ac51a7d0de..32098a45ce97c 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll @@ -1,6 +1,6 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s -; CHECK: error: register SB (space=0, register=0) is not defined in Root Signature +; CHECK: error: register SRV (space=0, register=0) is not defined in Root Signature ; Root Signature( ; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll index 8a1daea8f7d24..2bc54f811d62e 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll @@ -1,6 +1,6 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s -; CHECK: error: register RWB (space=0, register=4294967295) is not defined in Root Signature +; CHECK: error: register UAV (space=0, register=4294967295) is not defined in Root Signature ; Root Signature( ; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) From ef1463806a4d965d38c2b41e3b626644dda75b10 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 17 Jul 2025 00:34:12 +0000 Subject: [PATCH 038/143] clean --- llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h | 1 - llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 5 ----- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h | 1 + 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index e298cb4250db9..b334bf0996ae9 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -16,7 +16,6 @@ #include "llvm/ADT/IntervalMap.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" -#include "llvm/Support/DXILABI.h" namespace llvm { namespace hlsl { diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 9b89646050e17..3a6ccf9145d5a 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -10,20 +10,15 @@ #include "DXILRootSignature.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" #include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" -#include "llvm/MC/DXContainerRootSignature.h" -#include "llvm/Support/DXILABI.h" #define DEBUG_TYPE "dxil-post-optimization-validation" diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h index 2535c6979c5d5..cb5e624514272 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h @@ -17,6 +17,7 @@ #include "llvm/IR/PassManager.h" namespace llvm { + class DXILPostOptimizationValidation : public PassInfoMixin { public: From 662c3a84f05f2bd78be2ab6f78fbd63678d90fa6 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 21 Jul 2025 22:24:26 +0000 Subject: [PATCH 039/143] addressing comments --- llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h | 2 +- llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp | 2 +- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 2 +- .../CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll | 2 +- .../CodeGen/DirectX/rootsignature-validation-fail-constants.ll | 2 +- .../CodeGen/DirectX/rootsignature-validation-fail-sampler.ll | 2 +- llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll | 2 +- llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index b334bf0996ae9..4bc7771a0f83d 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -179,7 +179,7 @@ class RootSignatureBindingValidation { } }; llvm::SmallVector -findUnboundRanges(const llvm::SmallVectorImpl &Ranges, +findUnboundRanges(const llvm::ArrayRef &Ranges, const llvm::ArrayRef &Bindings); } // namespace rootsig } // namespace hlsl diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 77492eaf13aee..b7204a4bf82a3 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -317,7 +317,7 @@ findOverlappingRanges(llvm::SmallVector &Infos) { } llvm::SmallVector -findUnboundRanges(const llvm::SmallVectorImpl &Ranges, +findUnboundRanges(const llvm::ArrayRef &Ranges, const llvm::ArrayRef &Bindings) { llvm::SmallVector Unbounds; for (const auto &Range : Ranges) { diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 3a6ccf9145d5a..ba357f95ea8d8 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -135,7 +135,7 @@ static void reportRegNotBound(Module &M, OS << "register " << ResourceClassToString(Unbound.Class) << " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound << ")" - << " is not defined in Root Signature"; + << " does not have a binding in the Root Signature"; M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll index ac97d79c6a2eb..e5133810c0f32 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll @@ -1,6 +1,6 @@ ; 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=665, register=3) is not defined in Root Signature +; CHECK: error: register CBuffer (space=665, register=3) does not have a binding in the Root Signature ; Root Signature( ; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll index fadc0db046ec7..dc7657e79ec97 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.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: register CBuffer (space=666, register=2) is not defined in Root Signature +; CHECK: error: register CBuffer (space=666, register=2) does not have a binding in the Root Signature ; Root Signature(RootConstants(num32BitConstants=4, b2)) %__cblayout_CB = type <{ float }> diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll index 2ec3505cbec41..152c363fdf75b 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll @@ -1,6 +1,6 @@ ; 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=2, register=3) is not defined in Root Signature +; CHECK: error: register Sampler (space=2, register=3) does not have a binding in the Root Signature ; Root Signature( ; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll index 32098a45ce97c..ebefa7b1a3d85 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll @@ -1,6 +1,6 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s -; CHECK: error: register SRV (space=0, register=0) is not defined in Root Signature +; CHECK: error: register SRV (space=0, register=0) does not have a binding in the Root Signature ; Root Signature( ; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll index 2bc54f811d62e..1bd0f6da62478 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll @@ -1,6 +1,6 @@ ; 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=4294967295) is not defined in Root Signature +; CHECK: error: register UAV (space=0, register=4294967295) does not have a binding in the Root Signature ; Root Signature( ; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) From 848501da71dd90e1d7dfe25f4ba25890ba487dad Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 21 Jul 2025 23:24:21 +0000 Subject: [PATCH 040/143] address comments --- .../DXILPostOptimizationValidation.cpp | 68 +++++++++++++++++-- .../rootsignature-validation-textures-fail.ll | 15 +--- .../rootsignature-validation-textures.ll | 23 +++++++ ...otsignature-validation-typedbuffer-fail.ll | 12 +--- .../rootsignature-validation-typedbuffer.ll | 23 +++++++ 5 files changed, 113 insertions(+), 28 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index a62c2b7e2b2c4..211e639c44a55 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -10,6 +10,7 @@ #include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -248,6 +249,44 @@ initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, return Validation; } +static SmallVector +getRootDescriptorsBindingInfo(const mcdxbc::RootSignatureDesc &RSD, + dxbc::ShaderVisibility Visibility) { + + SmallVector RDs; + + 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); + if (Header.ShaderVisibility != + llvm::to_underlying(dxbc::ShaderVisibility::All) && + Header.ShaderVisibility != llvm::to_underlying(Visibility)) + continue; + + 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); + + ResourceInfo::ResourceBinding Binding; + Binding.LowerBound = Desc.ShaderRegister; + Binding.Space = Desc.RegisterSpace; + Binding.Size = 1; + + RDs.push_back(Binding); + break; + } + } + } + + return RDs; +} + std::optional getRootSignature(RootSignatureBindingInfo &RSBI, dxil::ModuleMetadataInfo &MMI) { @@ -261,10 +300,22 @@ getRootSignature(RootSignatureBindingInfo &RSBI, } static void reportInvalidHandleTy( - Module &M, + Module &M, const llvm::ArrayRef &RDs, const iterator_range::iterator> &Resources) { for (auto Res = Resources.begin(), End = Resources.end(); Res != End; Res++) { + llvm::dxil::ResourceInfo::ResourceBinding Binding = Res->getBinding(); + bool IsBound = false; + for (const auto &RD : RDs) { + if (Binding.overlapsWith(RD)) { + IsBound = true; + break; + } + } + + if (!IsBound) + continue; + TargetExtType *Handle = Res->getHandleTy(); auto *TypedBuffer = dyn_cast_or_null(Handle); auto *Texture = dyn_cast_or_null(Handle); @@ -312,9 +363,9 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, "DXILResourceImplicitBinding pass"); if (auto RSD = getRootSignature(RSBI, MMI)) { - + dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); llvm::hlsl::rootsig::RootSignatureBindingValidation Validation = - initRSBindingValidation(*RSD, tripleToVisibility(MMI.ShaderProfile)); + initRSBindingValidation(*RSD, Visibility); reportUnboundRegisters(M, Validation, ResourceClass::CBuffer, DRM.cbuffers()); @@ -323,10 +374,13 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, 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()); + SmallVector RDs = + getRootDescriptorsBindingInfo(*RSD, Visibility); + + reportInvalidHandleTy(M, RDs, DRM.cbuffers()); + reportInvalidHandleTy(M, RDs, DRM.srvs()); + reportInvalidHandleTy(M, RDs, DRM.uavs()); + reportInvalidHandleTy(M, RDs, DRM.samplers()); } } } // namespace diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll index 81d1a1a0ab0c5..a534b6c956e84 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll @@ -3,10 +3,7 @@ ; 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) +; UAV(b0, space=0, visibility=SHADER_VISIBILITY_ALL) @TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 @@ -21,11 +18,5 @@ entry: !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} +!1 = !{!2} +!2 = !{!"RootUAV", i32 0, i32 0, i32 0, i32 4} 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..fc66ef6ae309f --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll @@ -0,0 +1,23 @@ +; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 + + + +; Root Signature( +; DescriptorTable(UAV(b0, space=0, 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.Texture", 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 = !{!3} +!3 = !{!"DescriptorTable", i32 0, !4} +!4 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll index 81d1a1a0ab0c5..46ee29258dbdc 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll @@ -13,7 +13,7 @@ define void @CSMain() "hlsl.shader"="compute" { entry: - %TB = tail call target("dx.Texture", 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) + %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 } @@ -21,11 +21,5 @@ entry: !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} +!1 = !{!2} +!2 = !{!"RootUAV", i32 0, i32 0, i32 0, i32 4} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll new file mode 100644 index 0000000000000..0260e0cc9121d --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll @@ -0,0 +1,23 @@ +; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 + + + +; Root Signature( +; DescriptorTable(UAV(b0, space=0, 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 = !{!3} +!3 = !{!"DescriptorTable", i32 0, !4} +!4 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0} From 8d97116dc7bf9a052f69d4ee30b9c31c13852065 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 21 Jul 2025 23:25:03 +0000 Subject: [PATCH 041/143] format test --- .../test/CodeGen/DirectX/rootsignature-validation-textures.ll | 4 +--- .../CodeGen/DirectX/rootsignature-validation-typedbuffer.ll | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll index fc66ef6ae309f..f20ccd04c49c6 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll @@ -1,7 +1,5 @@ ; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 - - - +; expected-no-diagnostics ; Root Signature( ; DescriptorTable(UAV(b0, space=0, visibility=SHADER_VISIBILITY_ALL)) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll index 0260e0cc9121d..a880cbdc8f442 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll @@ -1,7 +1,5 @@ ; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 - - - +; expected-no-diagnostics ; Root Signature( ; DescriptorTable(UAV(b0, space=0, visibility=SHADER_VISIBILITY_ALL)) From 9c34f3fdf76c43495780666da4d22568dc914689 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Mon, 21 Jul 2025 23:33:54 +0000 Subject: [PATCH 042/143] fix test --- llvm/test/CodeGen/DirectX/rootsignature-validation.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll index 6a279ea123911..ca46168ed1fa3 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -21,7 +21,7 @@ entry: %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) + %RWB = tail call target("dx.TypedBuffer", 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 2c30cd907db474fc636b6e06e868dcb8046b652e Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 22 Jul 2025 17:01:38 +0000 Subject: [PATCH 043/143] addressing comments --- .../DXILPostOptimizationValidation.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index a564f8f150ef9..cf4dd47ad83ef 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -301,23 +301,16 @@ static void reportInvalidHandleTy( &Resources) { for (auto Res = Resources.begin(), End = Resources.end(); Res != End; Res++) { llvm::dxil::ResourceInfo::ResourceBinding Binding = Res->getBinding(); - bool IsBound = false; for (const auto &RD : RDs) { if (Binding.overlapsWith(RD)) { - IsBound = true; - break; + TargetExtType *Handle = Res->getHandleTy(); + auto *TypedBuffer = dyn_cast_or_null(Handle); + auto *Texture = dyn_cast_or_null(Handle); + + if (TypedBuffer != nullptr || Texture != nullptr) + reportInvalidHandleTyBoundInRs(M, Res->getName(), Res->getBinding()); } } - - if (!IsBound) - continue; - - TargetExtType *Handle = Res->getHandleTy(); - auto *TypedBuffer = dyn_cast_or_null(Handle); - auto *Texture = dyn_cast_or_null(Handle); - - if (TypedBuffer != nullptr || Texture != nullptr) - reportInvalidHandleTyBoundInRs(M, Res->getName(), Res->getBinding()); } } From 260633c526c0c405a4df012c7f785adbff4f4271 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Fri, 25 Jul 2025 13:22:44 -0700 Subject: [PATCH 044/143] address comments --- llvm/include/llvm/Analysis/DXILResource.h | 14 +++++++++++++ .../Frontend/HLSL/RootSignatureValidations.h | 21 +++++++++---------- llvm/lib/Analysis/DXILResource.cpp | 14 ------------- .../HLSL/RootSignatureValidations.cpp | 3 +-- .../DXILPostOptimizationValidation.cpp | 16 ++------------ 5 files changed, 27 insertions(+), 41 deletions(-) diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index 9e2dc1ad771cf..b06c9c7394c09 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -32,6 +32,20 @@ class DXILResourceTypeMap; namespace dxil { +inline StringRef getResourceClassName(ResourceClass RC) { + switch (RC) { + case ResourceClass::SRV: + return "SRV"; + case ResourceClass::UAV: + return "UAV"; + case ResourceClass::CBuffer: + return "CBuffer"; + case ResourceClass::Sampler: + return "Sampler"; + } + llvm_unreachable("Unhandled ResourceClass"); +} + // Returns the resource name from dx_resource_handlefrombinding or // dx_resource_handlefromimplicitbinding call LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI); diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 4bc7771a0f83d..2e74d6d216ab8 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -153,17 +153,17 @@ class RootSignatureBindingValidation { uint32_t InsertPos = Bindings.size(); Bindings.push_back(Binding); Ranges[Type] = {InsertPos, InsertPos + 1}; - } else { - uint32_t InsertPos = It->second.End; - Bindings.insert(Bindings.begin() + InsertPos, Binding); + return; + } + uint32_t InsertPos = It->second.End; + Bindings.insert(Bindings.begin() + InsertPos, Binding); - It->second.End++; + It->second.End++; - for (auto &[Type, Range] : Ranges) { - if (Range.Start > InsertPos) { - Range.Start++; - Range.End++; - } + for (auto &[Type, Range] : Ranges) { + if (Range.Start > InsertPos) { + Range.Start++; + Range.End++; } } } @@ -171,9 +171,8 @@ class RootSignatureBindingValidation { llvm::ArrayRef getBindingsOfType(const dxil::ResourceClass &Type) const { auto It = Ranges.find(Type); - if (It == Ranges.end()) { + if (It == Ranges.end()) return {}; - } return llvm::ArrayRef(Bindings.data() + It->second.Start, It->second.End - It->second.Start); } diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp index 2da6468ec3dcf..04e6ef0e1c1bf 100644 --- a/llvm/lib/Analysis/DXILResource.cpp +++ b/llvm/lib/Analysis/DXILResource.cpp @@ -29,20 +29,6 @@ using namespace llvm; using namespace dxil; -static StringRef getResourceClassName(ResourceClass RC) { - switch (RC) { - case ResourceClass::SRV: - return "SRV"; - case ResourceClass::UAV: - return "UAV"; - case ResourceClass::CBuffer: - return "CBuffer"; - case ResourceClass::Sampler: - return "Sampler"; - } - llvm_unreachable("Unhandled ResourceClass"); -} - static StringRef getResourceKindName(ResourceKind RK) { switch (RK) { case ResourceKind::Texture1D: diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index b7204a4bf82a3..5984fe2a43f5f 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -335,9 +335,8 @@ findUnboundRanges(const llvm::ArrayRef &Ranges, break; } } - if (!Bound) { + if (!Bound) Unbounds.push_back(Range); - } } return Unbounds; } diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index ba357f95ea8d8..b5b2c20f2b9ce 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -11,6 +11,7 @@ #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" #include "llvm/Frontend/HLSL/RootSignatureValidations.h" @@ -26,19 +27,6 @@ using namespace llvm; using namespace llvm::dxil; namespace { -static const char *ResourceClassToString(llvm::dxil::ResourceClass Class) { - switch (Class) { - case ResourceClass::SRV: - return "SRV"; - case ResourceClass::UAV: - return "UAV"; - case ResourceClass::CBuffer: - return "CBuffer"; - case ResourceClass::Sampler: - return "Sampler"; - } -} - static ResourceClass RangeToResourceClass(uint32_t RangeType) { using namespace dxbc; switch (static_cast(RangeType)) { @@ -132,7 +120,7 @@ static void reportRegNotBound(Module &M, llvm::hlsl::rootsig::RangeInfo Unbound) { SmallString<128> Message; raw_svector_ostream OS(Message); - OS << "register " << ResourceClassToString(Unbound.Class) + OS << "register " << getResourceClassName(Unbound.Class) << " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound << ")" << " does not have a binding in the Root Signature"; From 6db6224726db1a2394ac8d61cf46b69234490df7 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Fri, 1 Aug 2025 02:50:08 +0000 Subject: [PATCH 045/143] update code --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 4 + .../Frontend/HLSL/RootSignatureValidations.h | 45 -------- llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 17 +++ .../DXILPostOptimizationValidation.cpp | 108 +++++++----------- .../rootsignature-validation-fail-uav.ll | 8 +- 5 files changed, 69 insertions(+), 113 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index 70a2eeb632f1b..a97dc3bd13ce0 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -17,6 +17,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DXILABI.h" #include "llvm/Support/ErrorHandling.h" +#include namespace llvm { namespace hlsl { @@ -57,6 +58,7 @@ class BindingInfo { } // Size == -1 means unbounded array LLVM_ABI std::optional findAvailableBinding(int32_t Size); + LLVM_ABI bool isBound(BindingRange B); }; struct BindingSpaces { @@ -95,6 +97,8 @@ class BindingInfo { LLVM_ABI std::optional findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size); + LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space, BindingRange B); + friend class BindingInfoBuilder; }; diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 08cfd3e5fa134..e38017f0c6b4e 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -148,51 +148,6 @@ struct OverlappingRanges { /// B: Check for overlap with any overlapping Visibility ResourceRange LLVM_ABI llvm::SmallVector findOverlappingRanges(ArrayRef Infos); - -class RootSignatureBindingValidation { -private: - llvm::SmallVector Bindings; - struct TypeRange { - uint32_t Start; - uint32_t End; - }; - std::unordered_map Ranges; - -public: - void addBinding(dxil::ResourceClass Type, const RangeInfo &Binding) { - auto It = Ranges.find(Type); - - if (It == Ranges.end()) { - uint32_t InsertPos = Bindings.size(); - Bindings.push_back(Binding); - Ranges[Type] = {InsertPos, InsertPos + 1}; - return; - } - uint32_t InsertPos = It->second.End; - Bindings.insert(Bindings.begin() + InsertPos, Binding); - - It->second.End++; - - for (auto &[Type, Range] : Ranges) { - if (Range.Start > InsertPos) { - Range.Start++; - Range.End++; - } - } - } - - llvm::ArrayRef - getBindingsOfType(const dxil::ResourceClass &Type) const { - auto It = Ranges.find(Type); - if (It == Ranges.end()) - return {}; - return llvm::ArrayRef(Bindings.data() + It->second.Start, - It->second.End - It->second.Start); - } -}; -llvm::SmallVector -findUnboundRanges(const llvm::ArrayRef &Ranges, - const llvm::ArrayRef &Bindings); } // namespace rootsig } // namespace hlsl } // namespace llvm diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index d581311f22028..cf6d4b741ed14 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -8,6 +8,7 @@ #include "llvm/Frontend/HLSL/HLSLBinding.h" #include "llvm/ADT/STLExtras.h" +#include using namespace llvm; using namespace hlsl; @@ -66,6 +67,22 @@ BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) { return std::nullopt; } +bool BindingInfo::RegisterSpace::isBound(BindingRange B) { + for (BindingRange &R : FreeRanges) { + if (B.LowerBound >= R.LowerBound && B.LowerBound < R.UpperBound && + B.UpperBound > R.LowerBound && B.UpperBound <= R.UpperBound) + return false; + } + return true; +} + +bool BindingInfo::isBound(dxil::ResourceClass RC, uint32_t Space, + BindingRange B) { + BindingSpaces &BS = getBindingSpaces(RC); + RegisterSpace &RS = BS.getOrInsertSpace(Space); + return RS.isBound(B); +} + BindingInfo BindingInfoBuilder::calculateBindingInfo( llvm::function_ref diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index b5b2c20f2b9ce..b63404d7a760a 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -14,12 +14,16 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" +#include "llvm/BinaryFormat/DXContainer.h" +#include "llvm/Frontend/HLSL/HLSLBinding.h" #include "llvm/Frontend/HLSL/RootSignatureValidations.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/DXILABI.h" +#include #define DEBUG_TYPE "dxil-post-optimization-validation" @@ -116,11 +120,12 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } -static void reportRegNotBound(Module &M, - llvm::hlsl::rootsig::RangeInfo Unbound) { +static void +reportRegNotBound(Module &M, ResourceClass Class, + llvm::dxil::ResourceInfo::ResourceBinding Unbound) { SmallString<128> Message; raw_svector_ostream OS(Message); - OS << "register " << getResourceClassName(Unbound.Class) + OS << "register " << getResourceClassName(Class) << " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound << ")" << " does not have a binding in the Root Signature"; @@ -155,12 +160,9 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) { } } -static hlsl::rootsig::RootSignatureBindingValidation -initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, - dxbc::ShaderVisibility Visibility) { - - hlsl::rootsig::RootSignatureBindingValidation Validation; - +static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder, + const mcdxbc::RootSignatureDesc &RSD, + dxbc::ShaderVisibility Visibility) { for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) { const auto &[Type, Loc] = RSD.ParametersContainer.getTypeAndLocForParameter(I); @@ -175,15 +177,10 @@ initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): { dxbc::RTS0::v1::RootConstants Const = RSD.ParametersContainer.getConstant(Loc); - - hlsl::rootsig::RangeInfo Binding; - Binding.LowerBound = Const.ShaderRegister; - Binding.Space = Const.RegisterSpace; - Binding.UpperBound = Binding.LowerBound; - - // Root Constants Bind to CBuffers - Validation.addBinding(ResourceClass::CBuffer, Binding); - + Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace, + Const.ShaderRegister, + Const.ShaderRegister + Const.Num32BitValues, + nullptr); break; } @@ -192,13 +189,9 @@ initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, case llvm::to_underlying(dxbc::RootParameterType::CBV): { dxbc::RTS0::v2::RootDescriptor Desc = RSD.ParametersContainer.getRootDescriptor(Loc); + Builder.trackBinding(ParameterToResourceClass(Type), Desc.RegisterSpace, + Desc.ShaderRegister, Desc.ShaderRegister, nullptr); - hlsl::rootsig::RangeInfo Binding; - Binding.LowerBound = Desc.ShaderRegister; - Binding.Space = Desc.RegisterSpace; - Binding.UpperBound = Binding.LowerBound; - - Validation.addBinding(ParameterToResourceClass(Type), Binding); break; } case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): { @@ -206,18 +199,15 @@ initRSBindingValidation(const mcdxbc::RootSignatureDesc &RSD, RSD.ParametersContainer.getDescriptorTable(Loc); for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { - hlsl::rootsig::RangeInfo Binding; - Binding.LowerBound = Range.BaseShaderRegister; - Binding.Space = Range.RegisterSpace; - Binding.UpperBound = Binding.LowerBound + Range.NumDescriptors - 1; - Validation.addBinding(RangeToResourceClass(Range.RangeType), Binding); + Builder.trackBinding(RangeToResourceClass(Range.RangeType), + Range.RegisterSpace, Range.BaseShaderRegister, + Range.BaseShaderRegister + Range.NumDescriptors, + nullptr); } break; } } } - - return Validation; } std::optional @@ -232,30 +222,6 @@ getRootSignature(RootSignatureBindingInfo &RSBI, return RootSigDesc; } -static void reportUnboundRegisters( - Module &M, - const llvm::hlsl::rootsig::RootSignatureBindingValidation &Validation, - ResourceClass Class, - const iterator_range::iterator> - &Resources) { - SmallVector Ranges; - for (auto Res = Resources.begin(), End = Resources.end(); Res != End; Res++) { - ResourceInfo::ResourceBinding ResBinding = Res->getBinding(); - hlsl::rootsig::RangeInfo Range; - Range.Space = ResBinding.Space; - Range.LowerBound = ResBinding.LowerBound; - Range.UpperBound = Range.LowerBound + ResBinding.Size - 1; - Range.Class = Class; - Ranges.push_back(Range); - } - - SmallVector Unbounds = - hlsl::rootsig::findUnboundRanges(Ranges, - Validation.getBindingsOfType(Class)); - for (const auto &Unbound : Unbounds) - reportRegNotBound(M, Unbound); -} - static void reportErrors(Module &M, DXILResourceMap &DRM, DXILResourceBindingInfo &DRBI, RootSignatureBindingInfo &RSBI, @@ -271,15 +237,29 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, if (auto RSD = getRootSignature(RSBI, MMI)) { - 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()); + hlsl::BindingInfoBuilder Builder; + dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); + trackRootSigDescBinding(Builder, *RSD, Visibility); + + bool HasOverlap; + hlsl::BindingInfo Info = Builder.calculateBindingInfo(HasOverlap); + + for (const auto &ResList : + {std::make_pair(ResourceClass::SRV, DRM.srvs()), + std::make_pair(ResourceClass::UAV, DRM.uavs()), + std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), + std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { + for (auto Res : ResList.second) { + llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); + llvm::hlsl::BindingInfo::BindingRange ResRange( + ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); + + auto IsBound = Info.isBound(ResList.first, ResBinding.Space, ResRange); + if (!IsBound) { + reportRegNotBound(M, ResList.first, ResBinding); + } + } + } } } } // namespace diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll index 1bd0f6da62478..9cc5b6744a4a2 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll @@ -1,6 +1,6 @@ ; 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=4294967295) does not have a binding in the Root Signature +; CHECK: error: register UAV (space=0, register=4294967294) does not have a binding in the Root Signature ; Root Signature( ; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) @@ -12,8 +12,8 @@ define void @CSMain() "hlsl.shader"="compute" { entry: -; RWBuffer UAV : register(u4294967295); - %RWB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 -1, i32 1, i32 0, i1 false, ptr nonnull @RWB.str) +; RWBuffer UAV : register(4294967294); + %RWB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 4294967294, i32 1, i32 0, i1 false, ptr nonnull @RWB.str) ret void } @@ -27,4 +27,4 @@ entry: !5 = !{!"DescriptorTable", i32 0, !6} !6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} !7 = !{!"DescriptorTable", i32 0, !8} -!8 = !{!"UAV", i32 -1, i32 0, i32 0, i32 -1, i32 2} +!8 = !{!"UAV", i32 10, i32 0, i32 0, i32 -1, i32 2} From 04658b813a5b9b3863909fcdf522c662b1404409 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Fri, 1 Aug 2025 02:54:45 +0000 Subject: [PATCH 046/143] cleanup --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 1 - .../Frontend/HLSL/RootSignatureValidations.h | 1 + llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 1 - .../HLSL/RootSignatureValidations.cpp | 25 ------------------- .../DXILPostOptimizationValidation.cpp | 6 ----- 5 files changed, 1 insertion(+), 33 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index a97dc3bd13ce0..af7f2402c0fa0 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -17,7 +17,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DXILABI.h" #include "llvm/Support/ErrorHandling.h" -#include namespace llvm { namespace hlsl { diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index e38017f0c6b4e..f1e223da95241 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -148,6 +148,7 @@ struct OverlappingRanges { /// B: Check for overlap with any overlapping Visibility ResourceRange LLVM_ABI llvm::SmallVector findOverlappingRanges(ArrayRef Infos); + } // namespace rootsig } // namespace hlsl } // namespace llvm diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index cf6d4b741ed14..57075ca430d44 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -8,7 +8,6 @@ #include "llvm/Frontend/HLSL/HLSLBinding.h" #include "llvm/ADT/STLExtras.h" -#include using namespace llvm; using namespace hlsl; diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index bdf7f353432df..f11c7d2033bfb 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -314,31 +314,6 @@ findOverlappingRanges(ArrayRef Infos) { return Overlaps; } -llvm::SmallVector -findUnboundRanges(const llvm::ArrayRef &Ranges, - const llvm::ArrayRef &Bindings) { - llvm::SmallVector Unbounds; - for (const auto &Range : Ranges) { - bool Bound = false; - // hlsl::rootsig::RangeInfo Range; - // Range.Space = ResBinding.Space; - // Range.LowerBound = ResBinding.LowerBound; - // Range.UpperBound = Range.LowerBound + ResBinding.Size - 1; - - for (const auto &Binding : Bindings) { - if (Range.Space == Binding.Space && - Range.LowerBound >= Binding.LowerBound && - Range.UpperBound <= Binding.UpperBound) { - Bound = true; - break; - } - } - if (!Bound) - Unbounds.push_back(Range); - } - return Unbounds; -} - } // namespace rootsig } // namespace hlsl } // namespace llvm diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index b63404d7a760a..b661b71ffe3c2 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -11,19 +11,13 @@ #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" -#include "llvm/BinaryFormat/DXContainer.h" -#include "llvm/Frontend/HLSL/HLSLBinding.h" -#include "llvm/Frontend/HLSL/RootSignatureValidations.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/DXILABI.h" -#include #define DEBUG_TYPE "dxil-post-optimization-validation" From adf3feb83461a743b43039b9e903f75e19ca06cc Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 5 Aug 2025 10:45:23 -0700 Subject: [PATCH 047/143] address comments from inbelic --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index b661b71ffe3c2..0e25b8ff9897b 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -248,10 +248,8 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, llvm::hlsl::BindingInfo::BindingRange ResRange( ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); - auto IsBound = Info.isBound(ResList.first, ResBinding.Space, ResRange); - if (!IsBound) { + if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) reportRegNotBound(M, ResList.first, ResBinding); - } } } } From c95ce6866488ee12da119bc66a864fd0d6df367f Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Thu, 26 Jun 2025 19:28:01 +0000 Subject: [PATCH 048/143] refactoring refactoring clean up format formating fix import issues formating refactoring init refactoring adding validation clean implementing finish implementing && fix tests sync parent sync parent address comments fix test fix tests format address changes add preserved addressing comments updating format adding tests clean up address comments adding root constants clean moving code arround clean addressing comments address comments update code cleanup address comments from inbelic --- llvm/include/llvm/Analysis/DXILResource.h | 14 ++ llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 3 + .../Frontend/HLSL/RootSignatureValidations.h | 129 +++++++++++-- .../llvm/MC/DXContainerRootSignature.h | 2 - llvm/lib/Analysis/DXILResource.cpp | 14 -- llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 16 ++ llvm/lib/Target/DirectX/DXILOpLowering.cpp | 2 + .../DXILPostOptimizationValidation.cpp | 178 +++++++++++++++++- llvm/lib/Target/DirectX/DXILPrepare.cpp | 1 - llvm/lib/Target/DirectX/DXILRootSignature.cpp | 5 +- llvm/lib/Target/DirectX/DXILRootSignature.h | 12 +- llvm/test/CodeGen/DirectX/llc-pipeline.ll | 2 +- .../rootsignature-validation-constants.ll | 22 +++ .../rootsignature-validation-fail-cbuffer.ll | 34 ++++ ...rootsignature-validation-fail-constants.ll | 22 +++ .../rootsignature-validation-fail-sampler.ll | 31 +++ .../rootsignature-validation-fail-srv.ll | 30 +++ .../rootsignature-validation-fail-uav.ll | 30 +++ .../DirectX/rootsignature-validation.ll | 39 ++++ 19 files changed, 546 insertions(+), 40 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation.ll diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index 93c6bfb057ef5..96d631698af0a 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -33,6 +33,20 @@ class DXILResourceTypeMap; namespace dxil { +inline StringRef getResourceClassName(ResourceClass RC) { + switch (RC) { + case ResourceClass::SRV: + return "SRV"; + case ResourceClass::UAV: + return "UAV"; + case ResourceClass::CBuffer: + return "CBuffer"; + case ResourceClass::Sampler: + return "Sampler"; + } + llvm_unreachable("Unhandled ResourceClass"); +} + // Returns the resource name from dx_resource_handlefrombinding or // dx_resource_handlefromimplicitbinding call LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI); diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index 70a2eeb632f1b..af7f2402c0fa0 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -57,6 +57,7 @@ class BindingInfo { } // Size == -1 means unbounded array LLVM_ABI std::optional findAvailableBinding(int32_t Size); + LLVM_ABI bool isBound(BindingRange B); }; struct BindingSpaces { @@ -95,6 +96,8 @@ class BindingInfo { LLVM_ABI std::optional findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size); + LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space, BindingRange B); + friend class BindingInfoBuilder; }; diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index fde32a1fff591..bb6aeeb177412 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -16,7 +16,6 @@ #include "llvm/ADT/IntervalMap.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" -#include "llvm/Support/Compiler.h" namespace llvm { namespace hlsl { @@ -24,22 +23,118 @@ namespace rootsig { // Basic verification of RootElements -LLVM_ABI bool verifyRootFlag(uint32_t Flags); -LLVM_ABI bool verifyVersion(uint32_t Version); -LLVM_ABI bool verifyRegisterValue(uint32_t RegisterValue); -LLVM_ABI bool verifyRegisterSpace(uint32_t RegisterSpace); -LLVM_ABI bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal); -LLVM_ABI bool verifyRangeType(uint32_t Type); -LLVM_ABI bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, - uint32_t FlagsVal); -LLVM_ABI bool verifyNumDescriptors(uint32_t NumDescriptors); -LLVM_ABI bool verifySamplerFilter(uint32_t Value); -LLVM_ABI bool verifyAddress(uint32_t Address); -LLVM_ABI bool verifyMipLODBias(float MipLODBias); -LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); -LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc); -LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); -LLVM_ABI bool verifyLOD(float LOD); +bool verifyRootFlag(uint32_t Flags); +bool verifyVersion(uint32_t Version); +bool verifyRegisterValue(uint32_t RegisterValue); +bool verifyRegisterSpace(uint32_t RegisterSpace); +bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal); +bool verifyRangeType(uint32_t Type); +bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, + uint32_t FlagsVal); +bool verifyNumDescriptors(uint32_t NumDescriptors); +bool verifySamplerFilter(uint32_t Value); +bool verifyAddress(uint32_t Address); +bool verifyMipLODBias(float MipLODBias); +bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); +bool verifyComparisonFunc(uint32_t ComparisonFunc); +bool verifyBorderColor(uint32_t BorderColor); +bool verifyLOD(float LOD); + +struct RangeInfo { + const static uint32_t Unbounded = ~0u; + + // Interval information + uint32_t LowerBound; + uint32_t UpperBound; + + // Information retained for determining overlap + llvm::dxil::ResourceClass Class; + uint32_t Space; + llvm::dxbc::ShaderVisibility Visibility; +}; + +class ResourceRange { +public: + using MapT = llvm::IntervalMap>; + +private: + MapT Intervals; + +public: + ResourceRange(MapT::Allocator &Allocator) : Intervals(MapT(Allocator)) {} + + // Returns a reference to the first RangeInfo that overlaps with + // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap + LLVM_ABI std::optional + getOverlapping(const RangeInfo &Info) const; + + // Return the mapped RangeInfo at X or nullptr if no mapping exists + LLVM_ABI const RangeInfo *lookup(uint32_t X) const; + + // Removes all entries of the ResourceRange + LLVM_ABI void clear(); + + // Insert the required (sub-)intervals such that the interval of [a;b] = + // [Info.LowerBound, Info.UpperBound] is covered and points to a valid + // RangeInfo &. + // + // For instance consider the following chain of inserting RangeInfos with the + // intervals denoting the Lower/Upper-bounds: + // + // A = [0;2] + // insert(A) -> false + // intervals: [0;2] -> &A + // B = [5;7] + // insert(B) -> false + // intervals: [0;2] -> &A, [5;7] -> &B + // C = [4;7] + // insert(C) -> true + // intervals: [0;2] -> &A, [4;7] -> &C + // D = [1;5] + // insert(D) -> true + // intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C + // E = [0;unbounded] + // insert(E) -> true + // intervals: [0;unbounded] -> E + // + // Returns a reference to the first RangeInfo that overlaps with + // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap + // (equivalent to getOverlapping) + LLVM_ABI std::optional insert(const RangeInfo &Info); +}; + +struct OverlappingRanges { + const RangeInfo *A; + const RangeInfo *B; + + OverlappingRanges(const RangeInfo *A, const RangeInfo *B) : A(A), B(B) {} +}; + +/// The following conducts analysis on resource ranges to detect and report +/// any overlaps in resource ranges. +/// +/// A resource range overlaps with another resource range if they have: +/// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler) +/// - equivalent resource space +/// - overlapping visbility +/// +/// The algorithm is implemented in the following steps: +/// +/// 1. The user will collect RangeInfo from relevant RootElements: +/// - RangeInfo will retain the interval, ResourceClass, Space and Visibility +/// - It will also contain an index so that it can be associated to +/// additional diagnostic information +/// 2. Sort the RangeInfo's such that they are grouped together by +/// ResourceClass and Space +/// 3. Iterate through the collected RangeInfos by their groups +/// - For each group we will have a ResourceRange for each visibility +/// - As we iterate through we will: +/// A: Insert the current RangeInfo into the corresponding Visibility +/// ResourceRange +/// B: Check for overlap with any overlapping Visibility ResourceRange +LLVM_ABI llvm::SmallVector +findOverlappingRanges(ArrayRef Infos); } // namespace rootsig } // namespace hlsl diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h index 3c7c886e79fc3..a931b1d54b65c 100644 --- a/llvm/include/llvm/MC/DXContainerRootSignature.h +++ b/llvm/include/llvm/MC/DXContainerRootSignature.h @@ -5,7 +5,6 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// - #ifndef LLVM_MC_DXCONTAINERROOTSIGNATURE_H #define LLVM_MC_DXCONTAINERROOTSIGNATURE_H @@ -120,5 +119,4 @@ struct RootSignatureDesc { }; } // namespace mcdxbc } // namespace llvm - #endif // LLVM_MC_DXCONTAINERROOTSIGNATURE_H diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp index 629fa7cddb9d4..b476026fcc718 100644 --- a/llvm/lib/Analysis/DXILResource.cpp +++ b/llvm/lib/Analysis/DXILResource.cpp @@ -29,20 +29,6 @@ using namespace llvm; using namespace dxil; -static StringRef getResourceClassName(ResourceClass RC) { - switch (RC) { - case ResourceClass::SRV: - return "SRV"; - case ResourceClass::UAV: - return "UAV"; - case ResourceClass::CBuffer: - return "CBuffer"; - case ResourceClass::Sampler: - return "Sampler"; - } - llvm_unreachable("Unhandled ResourceClass"); -} - static StringRef getResourceKindName(ResourceKind RK) { switch (RK) { case ResourceKind::Texture1D: diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index d581311f22028..57075ca430d44 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -66,6 +66,22 @@ BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) { return std::nullopt; } +bool BindingInfo::RegisterSpace::isBound(BindingRange B) { + for (BindingRange &R : FreeRanges) { + if (B.LowerBound >= R.LowerBound && B.LowerBound < R.UpperBound && + B.UpperBound > R.LowerBound && B.UpperBound <= R.UpperBound) + return false; + } + return true; +} + +bool BindingInfo::isBound(dxil::ResourceClass RC, uint32_t Space, + BindingRange B) { + BindingSpaces &BS = getBindingSpaces(RC); + RegisterSpace &RS = BS.getOrInsertSpace(Space); + return RS.isBound(B); +} + BindingInfo BindingInfoBuilder::calculateBindingInfo( llvm::function_ref diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 0ec15a629d0a2..db7719e129ad0 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -9,6 +9,7 @@ #include "DXILOpLowering.h" #include "DXILConstants.h" #include "DXILOpBuilder.h" +#include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/SmallVector.h" @@ -945,6 +946,7 @@ class DXILOpLoweringLegacy : public ModulePass { AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); + AU.addPreserved(); } }; char DXILOpLoweringLegacy::ID = 0; diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 398dcbb8d1737..0e25b8ff9897b 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "DXILPostOptimizationValidation.h" +#include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" #include "llvm/ADT/SmallString.h" @@ -24,6 +25,35 @@ using namespace llvm; using namespace llvm::dxil; namespace { +static ResourceClass RangeToResourceClass(uint32_t RangeType) { + using namespace dxbc; + switch (static_cast(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; + } +} + +ResourceClass ParameterToResourceClass(uint32_t Type) { + using namespace dxbc; + switch (Type) { + case llvm::to_underlying(RootParameterType::Constants32Bit): + return ResourceClass::CBuffer; + case llvm::to_underlying(RootParameterType::SRV): + return ResourceClass::SRV; + case llvm::to_underlying(RootParameterType::UAV): + return ResourceClass::UAV; + case llvm::to_underlying(RootParameterType::CBV): + return ResourceClass::CBuffer; + default: + llvm_unreachable("Unknown RootParameterType"); + } +} static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) { for (const auto &UAV : DRM.uavs()) { @@ -84,8 +114,112 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } +static void +reportRegNotBound(Module &M, ResourceClass Class, + llvm::dxil::ResourceInfo::ResourceBinding Unbound) { + SmallString<128> Message; + raw_svector_ostream OS(Message); + OS << "register " << getResourceClassName(Class) + << " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound + << ")" + << " does not have a binding in the Root Signature"; + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); +} + +static dxbc::ShaderVisibility +tripleToVisibility(llvm::Triple::EnvironmentType ET) { + assert((ET == Triple::Pixel || ET == Triple::Vertex || + ET == Triple::Geometry || ET == Triple::Hull || + ET == Triple::Domain || ET == Triple::Mesh || + ET == Triple::Compute) && + "Invalid Triple to shader stage conversion"); + + switch (ET) { + case Triple::Pixel: + return dxbc::ShaderVisibility::Pixel; + case Triple::Vertex: + return dxbc::ShaderVisibility::Vertex; + case Triple::Geometry: + return dxbc::ShaderVisibility::Geometry; + case Triple::Hull: + return dxbc::ShaderVisibility::Hull; + case Triple::Domain: + return dxbc::ShaderVisibility::Domain; + case Triple::Mesh: + return dxbc::ShaderVisibility::Mesh; + case Triple::Compute: + return dxbc::ShaderVisibility::All; + default: + llvm_unreachable("Invalid triple to shader stage conversion"); + } +} + +static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder, + const mcdxbc::RootSignatureDesc &RSD, + dxbc::ShaderVisibility Visibility) { + 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); + if (Header.ShaderVisibility != + llvm::to_underlying(dxbc::ShaderVisibility::All) && + Header.ShaderVisibility != llvm::to_underlying(Visibility)) + continue; + + switch (Type) { + case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): { + dxbc::RTS0::v1::RootConstants Const = + RSD.ParametersContainer.getConstant(Loc); + Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace, + Const.ShaderRegister, + Const.ShaderRegister + Const.Num32BitValues, + nullptr); + break; + } + + 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); + Builder.trackBinding(ParameterToResourceClass(Type), Desc.RegisterSpace, + Desc.ShaderRegister, Desc.ShaderRegister, nullptr); + + 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) { + Builder.trackBinding(RangeToResourceClass(Range.RangeType), + Range.RegisterSpace, Range.BaseShaderRegister, + Range.BaseShaderRegister + Range.NumDescriptors, + nullptr); + } + break; + } + } + } +} + +std::optional +getRootSignature(RootSignatureBindingInfo &RSBI, + dxil::ModuleMetadataInfo &MMI) { + if (MMI.EntryPropertyVec.size() == 0) + return std::nullopt; + std::optional RootSigDesc = + RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); + if (!RootSigDesc) + return std::nullopt; + return RootSigDesc; +} + static void reportErrors(Module &M, DXILResourceMap &DRM, - DXILResourceBindingInfo &DRBI) { + DXILResourceBindingInfo &DRBI, + RootSignatureBindingInfo &RSBI, + dxil::ModuleMetadataInfo &MMI) { if (DRM.hasInvalidCounterDirection()) reportInvalidDirection(M, DRM); @@ -94,6 +228,31 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in " "DXILResourceImplicitBinding pass"); + + if (auto RSD = getRootSignature(RSBI, MMI)) { + + hlsl::BindingInfoBuilder Builder; + dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); + trackRootSigDescBinding(Builder, *RSD, Visibility); + + bool HasOverlap; + hlsl::BindingInfo Info = Builder.calculateBindingInfo(HasOverlap); + + for (const auto &ResList : + {std::make_pair(ResourceClass::SRV, DRM.srvs()), + std::make_pair(ResourceClass::UAV, DRM.uavs()), + std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), + std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { + for (auto Res : ResList.second) { + llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); + llvm::hlsl::BindingInfo::BindingRange ResRange( + ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); + + if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) + reportRegNotBound(M, ResList.first, ResBinding); + } + } + } } } // namespace @@ -101,7 +260,10 @@ PreservedAnalyses DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) { DXILResourceMap &DRM = MAM.getResult(M); DXILResourceBindingInfo &DRBI = MAM.getResult(M); - reportErrors(M, DRM, DRBI); + RootSignatureBindingInfo &RSBI = MAM.getResult(M); + ModuleMetadataInfo &MMI = MAM.getResult(M); + + reportErrors(M, DRM, DRBI, RSBI, MMI); return PreservedAnalyses::all(); } @@ -113,7 +275,12 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { getAnalysis().getResourceMap(); DXILResourceBindingInfo &DRBI = getAnalysis().getBindingInfo(); - reportErrors(M, DRM, DRBI); + RootSignatureBindingInfo &RSBI = + getAnalysis().getRSInfo(); + dxil::ModuleMetadataInfo &MMI = + getAnalysis().getModuleMetadata(); + + reportErrors(M, DRM, DRBI, RSBI, MMI); return false; } StringRef getPassName() const override { @@ -125,10 +292,13 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { AU.addRequired(); AU.addRequired(); + AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); + AU.addPreserved(); } }; char DXILPostOptimizationValidationLegacy::ID = 0; @@ -139,6 +309,8 @@ INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE, INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass) +INITIALIZE_PASS_DEPENDENCY(RootSignatureAnalysisWrapper) INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE, "DXIL Post Optimization Validation", false, false) diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp index c8866bfefdfc5..9c3eba83eba7c 100644 --- a/llvm/lib/Target/DirectX/DXILPrepare.cpp +++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp @@ -300,7 +300,6 @@ class DXILPrepareModule : public ModulePass { DXILPrepareModule() : ModulePass(ID) {} void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); - AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index a4f5086c2f428..eb9ff5ab405e4 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -29,6 +29,8 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include +#include +#include using namespace llvm; using namespace llvm::dxil; @@ -233,7 +235,7 @@ bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { void RootSignatureAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addPreserved(); + AU.addRequired(); } char RootSignatureAnalysisWrapper::ID = 0; @@ -241,6 +243,7 @@ char RootSignatureAnalysisWrapper::ID = 0; INITIALIZE_PASS_BEGIN(RootSignatureAnalysisWrapper, "dxil-root-signature-analysis", "DXIL Root Signature Analysis", true, true) +INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass) INITIALIZE_PASS_END(RootSignatureAnalysisWrapper, "dxil-root-signature-analysis", "DXIL Root Signature Analysis", true, true) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 254b7ff504633..ccffa3fd0a3e2 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -26,6 +26,16 @@ namespace llvm { namespace dxil { +enum class RootSignatureElementKind { + Error = 0, + RootFlags = 1, + RootConstants = 2, + SRV = 3, + UAV = 4, + CBV = 5, + DescriptorTable = 6, +}; + class RootSignatureBindingInfo { private: SmallDenseMap FuncToRsMap; @@ -96,4 +106,4 @@ class RootSignatureAnalysisPrinter } // namespace dxil } // namespace llvm -#endif +#endif // LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H diff --git a/llvm/test/CodeGen/DirectX/llc-pipeline.ll b/llvm/test/CodeGen/DirectX/llc-pipeline.ll index 151603a7161c5..c31d2194a8de5 100644 --- a/llvm/test/CodeGen/DirectX/llc-pipeline.ll +++ b/llvm/test/CodeGen/DirectX/llc-pipeline.ll @@ -33,9 +33,9 @@ ; CHECK-NEXT: DXIL Module Metadata analysis ; CHECK-NEXT: DXIL Shader Flag Analysis ; CHECK-NEXT: DXIL Translate Metadata +; CHECK-NEXT: DXIL Root Signature Analysis ; CHECK-NEXT: DXIL Post Optimization Validation ; CHECK-NEXT: DXIL Op Lowering -; CHECK-NEXT: DXIL Root Signature Analysis ; CHECK-NEXT: DXIL Prepare Module ; CHECK-ASM-NEXT: DXIL Metadata Pretty Printer 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-cbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll new file mode 100644 index 0000000000000..e5133810c0f32 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll @@ -0,0 +1,34 @@ +; 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=665, register=3) does not have a binding in the Root Signature + +; Root Signature( +; CBV(b3, space=666, 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) + +%__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(b3, space665) { +; float a; +; } + %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str) + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3, !5, !7} +!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} +!3 = !{!"DescriptorTable", i32 1, !4} +!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} +!5 = !{!"DescriptorTable", i32 0, !6} +!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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-fail-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll new file mode 100644 index 0000000000000..dc7657e79ec97 --- /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 CBuffer (space=666, register=2) does not have a binding in the 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} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll new file mode 100644 index 0000000000000..152c363fdf75b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.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: register Sampler (space=2, register=3) does not have a binding in the Root Signature + +; Root Signature( +; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) +; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) + +@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: +; SamplerState S1 : register(s3, space2); + %Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str) + + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3, !5, !7} +!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} +!3 = !{!"DescriptorTable", i32 1, !4} +!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} +!5 = !{!"DescriptorTable", i32 0, !6} +!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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-fail-srv.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll new file mode 100644 index 0000000000000..ebefa7b1a3d85 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll @@ -0,0 +1,30 @@ +; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s + +; CHECK: error: register SRV (space=0, register=0) does not have a binding in the Root Signature + +; Root Signature( +; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) +; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) + +@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: +; StructuredBuffer In : register(t0, space0); + %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) + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3, !5, !7} +!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} +!3 = !{!"DescriptorTable", i32 1, !4} +!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} +!5 = !{!"DescriptorTable", i32 0, !6} +!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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-fail-uav.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll new file mode 100644 index 0000000000000..9cc5b6744a4a2 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll @@ -0,0 +1,30 @@ +; 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=4294967294) does not have a binding in the Root Signature + +; Root Signature( +; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) +; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) +; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) + +@RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: +; RWBuffer UAV : register(4294967294); + %RWB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 4294967294, i32 1, i32 0, i1 false, ptr nonnull @RWB.str) + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3, !5, !7} +!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} +!3 = !{!"DescriptorTable", i32 1, !4} +!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} +!5 = !{!"DescriptorTable", i32 0, !6} +!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} +!7 = !{!"DescriptorTable", i32 0, !8} +!8 = !{!"UAV", i32 10, 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 new file mode 100644 index 0000000000000..750679bf743c5 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -0,0 +1,39 @@ +; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 +; expected-no-diagnostics + + +; 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) + +%__cblayout_CB = type <{ float }> + +@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 +@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 +@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1 +@RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1 + +define void @CSMain() "hlsl.shader"="compute" { +entry: + + %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 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.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 @RWB.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} From af6aa531329212cfe71baf720196b62d0baa67bc Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 5 Aug 2025 13:39:56 -0700 Subject: [PATCH 049/143] add tests --- .../DXILPostOptimizationValidation.cpp | 59 +++++++++---------- ...signature-validation-fail-cbuffer-range.ll | 15 +++++ .../rootsignature-validation-fail-cbuffer.ll | 34 ----------- ...rootsignature-validation-fail-constants.ll | 22 ------- ...-validation-fail-descriptor-table-range.ll | 15 +++++ ...e-validation-fail-root-descriptor-range.ll | 15 +++++ .../rootsignature-validation-fail-sampler.ll | 31 ---------- .../rootsignature-validation-fail-srv.ll | 30 ---------- ...re-validation-fail-static-sampler-range.ll | 13 ++++ .../rootsignature-validation-fail-uav.ll | 30 ---------- 10 files changed, 87 insertions(+), 177 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 0e25b8ff9897b..3da4cfbea23b8 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -114,15 +114,18 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } -static void -reportRegNotBound(Module &M, ResourceClass Class, - llvm::dxil::ResourceInfo::ResourceBinding Unbound) { +static void reportOverlappingRegisters( + Module &M, const llvm::hlsl::BindingInfoBuilder::Binding &Reported, + const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping) { SmallString<128> Message; raw_svector_ostream OS(Message); - OS << "register " << getResourceClassName(Class) - << " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound - << ")" - << " does not have a binding in the Root Signature"; + OS << "register " << getResourceClassName(Reported.RC) + << " (space=" << Reported.Space << ", register=" << Reported.LowerBound + << ")" << " is overlapping with" << " register " + << getResourceClassName(Overlaping.RC) << " (space=" << Overlaping.Space + << ", register=" << Overlaping.LowerBound << ")" + << ", verify your root signature definition."; + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } @@ -173,8 +176,7 @@ static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder, RSD.ParametersContainer.getConstant(Loc); Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace, Const.ShaderRegister, - Const.ShaderRegister + Const.Num32BitValues, - nullptr); + Const.ShaderRegister + Const.Num32BitValues, &Const); break; } @@ -184,7 +186,7 @@ static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder, dxbc::RTS0::v2::RootDescriptor Desc = RSD.ParametersContainer.getRootDescriptor(Loc); Builder.trackBinding(ParameterToResourceClass(Type), Desc.RegisterSpace, - Desc.ShaderRegister, Desc.ShaderRegister, nullptr); + Desc.ShaderRegister, Desc.ShaderRegister, &Desc); break; } @@ -195,13 +197,21 @@ static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder, for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { Builder.trackBinding(RangeToResourceClass(Range.RangeType), Range.RegisterSpace, Range.BaseShaderRegister, - Range.BaseShaderRegister + Range.NumDescriptors, - nullptr); + Range.NumDescriptors == ~0U + ? Range.NumDescriptors + : Range.BaseShaderRegister + + Range.NumDescriptors, + &Range); } break; } } } + + for (auto &S : RSD.StaticSamplers) { + Builder.trackBinding(dxil::ResourceClass::Sampler, S.RegisterSpace, + S.ShaderRegister, S.ShaderRegister, &S); + } } std::optional @@ -234,24 +244,13 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, hlsl::BindingInfoBuilder Builder; dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); trackRootSigDescBinding(Builder, *RSD, Visibility); - - bool HasOverlap; - hlsl::BindingInfo Info = Builder.calculateBindingInfo(HasOverlap); - - for (const auto &ResList : - {std::make_pair(ResourceClass::SRV, DRM.srvs()), - std::make_pair(ResourceClass::UAV, DRM.uavs()), - std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), - std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { - for (auto Res : ResList.second) { - llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); - llvm::hlsl::BindingInfo::BindingRange ResRange( - ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); - - if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) - reportRegNotBound(M, ResList.first, ResBinding); - } - } + hlsl::BindingInfo Info = Builder.calculateBindingInfo( + [&M](const llvm::hlsl::BindingInfoBuilder &Builder, + const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) { + const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping = + Builder.findOverlapping(ReportedBinding); + reportOverlappingRegisters(M, ReportedBinding, Overlaping); + }); } } } // 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 new file mode 100644 index 0000000000000..5def38af0fbeb --- /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=2) is overlapping with register CBuffer (space=0, register=0), 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 = !{!"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} \ No newline at end of file diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll deleted file mode 100644 index e5133810c0f32..0000000000000 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll +++ /dev/null @@ -1,34 +0,0 @@ -; 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=665, register=3) does not have a binding in the Root Signature - -; Root Signature( -; CBV(b3, space=666, 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) - -%__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(b3, space665) { -; float a; -; } - %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str) - ret void -} - -!dx.rootsignatures = !{!0} - -!0 = !{ptr @CSMain, !1, i32 2} -!1 = !{!2, !3, !5, !7} -!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} -!3 = !{!"DescriptorTable", i32 1, !4} -!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} -!5 = !{!"DescriptorTable", i32 0, !6} -!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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-fail-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll deleted file mode 100644 index dc7657e79ec97..0000000000000 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll +++ /dev/null @@ -1,22 +0,0 @@ -; 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=666, register=2) does not have a binding in the 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} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll new file mode 100644 index 0000000000000..7108d9834219e --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-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=10, register=4294967295) is overlapping with register UAV (space=10, register=4294967295), verify your root signature definition. +define void @CSMain() "hlsl.shader"="compute" { +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 0, !3} +!3 = !{!"UAV", i32 -1, i32 -1, i32 10, i32 -1, i32 2} +!4 = !{!"DescriptorTable", i32 0, !5} +!5 = !{ !"UAV", i32 -1, i32 -1, i32 10, i32 5, i32 2 } \ No newline at end of file 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..7790230eb07a0 --- /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=1, register=3) is overlapping with register UAV (space=1, register=0), verify your root signature definition. + +define void @CSMain() "hlsl.shader"="compute" { +entry: + ret void +} + +; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), UAV(u3, space=1) +!dx.rootsignatures = !{!0} +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !4} +!2 = !{!"RootUAV", i32 0, i32 3, i32 1, i32 4} +!4 = !{!"DescriptorTable", i32 0, !5} +!5 = !{!"UAV", i32 3, i32 0, i32 1, i32 -1, i32 2} \ No newline at end of file diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll deleted file mode 100644 index 152c363fdf75b..0000000000000 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll +++ /dev/null @@ -1,31 +0,0 @@ -; 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=2, register=3) does not have a binding in the Root Signature - -; Root Signature( -; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) -; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) - -@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 - -define void @CSMain() "hlsl.shader"="compute" { -entry: -; SamplerState S1 : register(s3, space2); - %Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str) - - ret void -} - -!dx.rootsignatures = !{!0} - -!0 = !{ptr @CSMain, !1, i32 2} -!1 = !{!2, !3, !5, !7} -!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} -!3 = !{!"DescriptorTable", i32 1, !4} -!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} -!5 = !{!"DescriptorTable", i32 0, !6} -!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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-fail-srv.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll deleted file mode 100644 index ebefa7b1a3d85..0000000000000 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll +++ /dev/null @@ -1,30 +0,0 @@ -; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s - -; CHECK: error: register SRV (space=0, register=0) does not have a binding in the Root Signature - -; Root Signature( -; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) -; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) - -@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1 - -define void @CSMain() "hlsl.shader"="compute" { -entry: -; StructuredBuffer In : register(t0, space0); - %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) - ret void -} - -!dx.rootsignatures = !{!0} - -!0 = !{ptr @CSMain, !1, i32 2} -!1 = !{!2, !3, !5, !7} -!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} -!3 = !{!"DescriptorTable", i32 1, !4} -!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} -!5 = !{!"DescriptorTable", i32 0, !6} -!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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-fail-static-sampler-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll new file mode 100644 index 0000000000000..bbcc42769d7be --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll @@ -0,0 +1,13 @@ +; 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 +} + +!dx.rootsignatures = !{!0} +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3} +!2 = !{ !"StaticSampler", i32 5, i32 4, i32 5, i32 3, float 0x3FF7CCCCC0000000, i32 10, i32 2, i32 1, float -1.270000e+02, float 1.220000e+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 } \ No newline at end of file diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll deleted file mode 100644 index 9cc5b6744a4a2..0000000000000 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll +++ /dev/null @@ -1,30 +0,0 @@ -; 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=4294967294) does not have a binding in the Root Signature - -; Root Signature( -; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) -; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) - -@RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1 - -define void @CSMain() "hlsl.shader"="compute" { -entry: -; RWBuffer UAV : register(4294967294); - %RWB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 4294967294, i32 1, i32 0, i1 false, ptr nonnull @RWB.str) - ret void -} - -!dx.rootsignatures = !{!0} - -!0 = !{ptr @CSMain, !1, i32 2} -!1 = !{!2, !3, !5, !7} -!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} -!3 = !{!"DescriptorTable", i32 1, !4} -!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} -!5 = !{!"DescriptorTable", i32 0, !6} -!6 = !{!"Sampler", i32 2, i32 0, i32 0, i32 -1, i32 0} -!7 = !{!"DescriptorTable", i32 0, !8} -!8 = !{!"UAV", i32 10, i32 0, i32 0, i32 -1, i32 2} From 29eb893bcb28676157c6c2314f55ff6d7e33043f Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 5 Aug 2025 14:43:51 -0700 Subject: [PATCH 050/143] cleanup --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 3 --- llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 16 ---------------- ...ature-validation-fail-static-sampler-range.ll | 2 +- 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index af7f2402c0fa0..70a2eeb632f1b 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -57,7 +57,6 @@ class BindingInfo { } // Size == -1 means unbounded array LLVM_ABI std::optional findAvailableBinding(int32_t Size); - LLVM_ABI bool isBound(BindingRange B); }; struct BindingSpaces { @@ -96,8 +95,6 @@ class BindingInfo { LLVM_ABI std::optional findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size); - LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space, BindingRange B); - friend class BindingInfoBuilder; }; diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index 57075ca430d44..d581311f22028 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -66,22 +66,6 @@ BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) { return std::nullopt; } -bool BindingInfo::RegisterSpace::isBound(BindingRange B) { - for (BindingRange &R : FreeRanges) { - if (B.LowerBound >= R.LowerBound && B.LowerBound < R.UpperBound && - B.UpperBound > R.LowerBound && B.UpperBound <= R.UpperBound) - return false; - } - return true; -} - -bool BindingInfo::isBound(dxil::ResourceClass RC, uint32_t Space, - BindingRange B) { - BindingSpaces &BS = getBindingSpaces(RC); - RegisterSpace &RS = BS.getOrInsertSpace(Space); - return RS.isBound(B); -} - BindingInfo BindingInfoBuilder::calculateBindingInfo( llvm::function_ref diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll index bbcc42769d7be..340b0aed6d16b 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll @@ -10,4 +10,4 @@ entry: !0 = !{ptr @CSMain, !1, i32 2} !1 = !{!2, !3} !2 = !{ !"StaticSampler", i32 5, i32 4, i32 5, i32 3, float 0x3FF7CCCCC0000000, i32 10, i32 2, i32 1, float -1.270000e+02, float 1.220000e+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 } \ No newline at end of file +!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 ed4c5539bf15b241a3d2ec243068d714fbe37acb Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 5 Aug 2025 14:46:26 -0700 Subject: [PATCH 051/143] clean --- .../rootsignature-validation-fail-descriptor-table-range.ll | 2 +- .../rootsignature-validation-fail-root-descriptor-range.ll | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll index 7108d9834219e..dbc75ac86db5f 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll @@ -12,4 +12,4 @@ entry: !2 = !{!"DescriptorTable", i32 0, !3} !3 = !{!"UAV", i32 -1, i32 -1, i32 10, i32 -1, i32 2} !4 = !{!"DescriptorTable", i32 0, !5} -!5 = !{ !"UAV", i32 -1, i32 -1, i32 10, i32 5, i32 2 } \ No newline at end of file +!5 = !{ !"UAV", i32 -1, i32 -1, i32 10, i32 5, i32 2 } 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 index 7790230eb07a0..9f70cc3f062a9 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll @@ -12,4 +12,4 @@ entry: !1 = !{!2, !4} !2 = !{!"RootUAV", i32 0, i32 3, i32 1, i32 4} !4 = !{!"DescriptorTable", i32 0, !5} -!5 = !{!"UAV", i32 3, i32 0, i32 1, i32 -1, i32 2} \ No newline at end of file +!5 = !{!"UAV", i32 3, i32 0, i32 1, i32 -1, i32 2} From 28fb609226910ef2ae4ef6caa8b5116df846d114 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 5 Aug 2025 17:21:18 -0700 Subject: [PATCH 052/143] clean up --- .../Frontend/HLSL/RootSignatureValidations.h | 129 +++--------------- .../llvm/MC/DXContainerRootSignature.h | 2 + llvm/lib/Target/DirectX/DXILPrepare.cpp | 1 + llvm/lib/Target/DirectX/DXILRootSignature.cpp | 5 +- llvm/lib/Target/DirectX/DXILRootSignature.h | 12 +- ...signature-validation-fail-cbuffer-range.ll | 2 +- 6 files changed, 23 insertions(+), 128 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index bb6aeeb177412..fde32a1fff591 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -16,6 +16,7 @@ #include "llvm/ADT/IntervalMap.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" +#include "llvm/Support/Compiler.h" namespace llvm { namespace hlsl { @@ -23,118 +24,22 @@ namespace rootsig { // Basic verification of RootElements -bool verifyRootFlag(uint32_t Flags); -bool verifyVersion(uint32_t Version); -bool verifyRegisterValue(uint32_t RegisterValue); -bool verifyRegisterSpace(uint32_t RegisterSpace); -bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal); -bool verifyRangeType(uint32_t Type); -bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, - uint32_t FlagsVal); -bool verifyNumDescriptors(uint32_t NumDescriptors); -bool verifySamplerFilter(uint32_t Value); -bool verifyAddress(uint32_t Address); -bool verifyMipLODBias(float MipLODBias); -bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); -bool verifyComparisonFunc(uint32_t ComparisonFunc); -bool verifyBorderColor(uint32_t BorderColor); -bool verifyLOD(float LOD); - -struct RangeInfo { - const static uint32_t Unbounded = ~0u; - - // Interval information - uint32_t LowerBound; - uint32_t UpperBound; - - // Information retained for determining overlap - llvm::dxil::ResourceClass Class; - uint32_t Space; - llvm::dxbc::ShaderVisibility Visibility; -}; - -class ResourceRange { -public: - using MapT = llvm::IntervalMap>; - -private: - MapT Intervals; - -public: - ResourceRange(MapT::Allocator &Allocator) : Intervals(MapT(Allocator)) {} - - // Returns a reference to the first RangeInfo that overlaps with - // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap - LLVM_ABI std::optional - getOverlapping(const RangeInfo &Info) const; - - // Return the mapped RangeInfo at X or nullptr if no mapping exists - LLVM_ABI const RangeInfo *lookup(uint32_t X) const; - - // Removes all entries of the ResourceRange - LLVM_ABI void clear(); - - // Insert the required (sub-)intervals such that the interval of [a;b] = - // [Info.LowerBound, Info.UpperBound] is covered and points to a valid - // RangeInfo &. - // - // For instance consider the following chain of inserting RangeInfos with the - // intervals denoting the Lower/Upper-bounds: - // - // A = [0;2] - // insert(A) -> false - // intervals: [0;2] -> &A - // B = [5;7] - // insert(B) -> false - // intervals: [0;2] -> &A, [5;7] -> &B - // C = [4;7] - // insert(C) -> true - // intervals: [0;2] -> &A, [4;7] -> &C - // D = [1;5] - // insert(D) -> true - // intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C - // E = [0;unbounded] - // insert(E) -> true - // intervals: [0;unbounded] -> E - // - // Returns a reference to the first RangeInfo that overlaps with - // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap - // (equivalent to getOverlapping) - LLVM_ABI std::optional insert(const RangeInfo &Info); -}; - -struct OverlappingRanges { - const RangeInfo *A; - const RangeInfo *B; - - OverlappingRanges(const RangeInfo *A, const RangeInfo *B) : A(A), B(B) {} -}; - -/// The following conducts analysis on resource ranges to detect and report -/// any overlaps in resource ranges. -/// -/// A resource range overlaps with another resource range if they have: -/// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler) -/// - equivalent resource space -/// - overlapping visbility -/// -/// The algorithm is implemented in the following steps: -/// -/// 1. The user will collect RangeInfo from relevant RootElements: -/// - RangeInfo will retain the interval, ResourceClass, Space and Visibility -/// - It will also contain an index so that it can be associated to -/// additional diagnostic information -/// 2. Sort the RangeInfo's such that they are grouped together by -/// ResourceClass and Space -/// 3. Iterate through the collected RangeInfos by their groups -/// - For each group we will have a ResourceRange for each visibility -/// - As we iterate through we will: -/// A: Insert the current RangeInfo into the corresponding Visibility -/// ResourceRange -/// B: Check for overlap with any overlapping Visibility ResourceRange -LLVM_ABI llvm::SmallVector -findOverlappingRanges(ArrayRef Infos); +LLVM_ABI bool verifyRootFlag(uint32_t Flags); +LLVM_ABI bool verifyVersion(uint32_t Version); +LLVM_ABI bool verifyRegisterValue(uint32_t RegisterValue); +LLVM_ABI bool verifyRegisterSpace(uint32_t RegisterSpace); +LLVM_ABI bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal); +LLVM_ABI bool verifyRangeType(uint32_t Type); +LLVM_ABI bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, + uint32_t FlagsVal); +LLVM_ABI bool verifyNumDescriptors(uint32_t NumDescriptors); +LLVM_ABI bool verifySamplerFilter(uint32_t Value); +LLVM_ABI bool verifyAddress(uint32_t Address); +LLVM_ABI bool verifyMipLODBias(float MipLODBias); +LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); +LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc); +LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); +LLVM_ABI bool verifyLOD(float LOD); } // namespace rootsig } // namespace hlsl diff --git a/llvm/include/llvm/MC/DXContainerRootSignature.h b/llvm/include/llvm/MC/DXContainerRootSignature.h index a931b1d54b65c..3c7c886e79fc3 100644 --- a/llvm/include/llvm/MC/DXContainerRootSignature.h +++ b/llvm/include/llvm/MC/DXContainerRootSignature.h @@ -5,6 +5,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #ifndef LLVM_MC_DXCONTAINERROOTSIGNATURE_H #define LLVM_MC_DXCONTAINERROOTSIGNATURE_H @@ -119,4 +120,5 @@ struct RootSignatureDesc { }; } // namespace mcdxbc } // namespace llvm + #endif // LLVM_MC_DXCONTAINERROOTSIGNATURE_H diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp index 9c3eba83eba7c..c8866bfefdfc5 100644 --- a/llvm/lib/Target/DirectX/DXILPrepare.cpp +++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp @@ -300,6 +300,7 @@ class DXILPrepareModule : public ModulePass { DXILPrepareModule() : ModulePass(ID) {} void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index eb9ff5ab405e4..a4f5086c2f428 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -29,8 +29,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include -#include -#include using namespace llvm; using namespace llvm::dxil; @@ -235,7 +233,7 @@ bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { void RootSignatureAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addRequired(); + AU.addPreserved(); } char RootSignatureAnalysisWrapper::ID = 0; @@ -243,7 +241,6 @@ char RootSignatureAnalysisWrapper::ID = 0; INITIALIZE_PASS_BEGIN(RootSignatureAnalysisWrapper, "dxil-root-signature-analysis", "DXIL Root Signature Analysis", true, true) -INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass) INITIALIZE_PASS_END(RootSignatureAnalysisWrapper, "dxil-root-signature-analysis", "DXIL Root Signature Analysis", true, true) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index ccffa3fd0a3e2..254b7ff504633 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -26,16 +26,6 @@ namespace llvm { namespace dxil { -enum class RootSignatureElementKind { - Error = 0, - RootFlags = 1, - RootConstants = 2, - SRV = 3, - UAV = 4, - CBV = 5, - DescriptorTable = 6, -}; - class RootSignatureBindingInfo { private: SmallDenseMap FuncToRsMap; @@ -106,4 +96,4 @@ class RootSignatureAnalysisPrinter } // namespace dxil } // namespace llvm -#endif // LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H +#endif 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 5def38af0fbeb..47d2a5b8d5aab 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll @@ -12,4 +12,4 @@ entry: !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} \ No newline at end of file +!4 = !{!"CBV", i32 3, i32 0, i32 0, i32 -1, i32 4} From f5b5b3e86938b441218fa75a560eb030b04118d3 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 5 Aug 2025 18:17:55 -0700 Subject: [PATCH 053/143] clean --- .../DXILPostOptimizationValidation.cpp | 24 +++++++++---------- llvm/lib/Target/DirectX/DXILPrepare.cpp | 1 + llvm/lib/Target/DirectX/DXILRootSignature.cpp | 3 +-- llvm/lib/Target/DirectX/DXILRootSignature.h | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 6e0913a838912..cef6c8381a88b 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -154,18 +154,6 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) { } } -std::optional -getRootSignature(RootSignatureBindingInfo &RSBI, - dxil::ModuleMetadataInfo &MMI) { - if (MMI.EntryPropertyVec.size() == 0) - return std::nullopt; - std::optional RootSigDesc = - RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); - if (!RootSigDesc) - return std::nullopt; - return RootSigDesc; -} - static void reportOverlappingRegisters( Module &M, const llvm::hlsl::BindingInfoBuilder::Binding &Reported, const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping) { @@ -238,6 +226,18 @@ static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder, } } +std::optional +getRootSignature(RootSignatureBindingInfo &RSBI, + dxil::ModuleMetadataInfo &MMI) { + if (MMI.EntryPropertyVec.size() == 0) + return std::nullopt; + std::optional RootSigDesc = + RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); + if (!RootSigDesc) + return std::nullopt; + return RootSigDesc; +} + static void reportErrors(Module &M, DXILResourceMap &DRM, DXILResourceBindingInfo &DRBI, RootSignatureBindingInfo &RSBI, diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp index 9c3eba83eba7c..c8866bfefdfc5 100644 --- a/llvm/lib/Target/DirectX/DXILPrepare.cpp +++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp @@ -300,6 +300,7 @@ class DXILPrepareModule : public ModulePass { DXILPrepareModule() : ModulePass(ID) {} void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.cpp b/llvm/lib/Target/DirectX/DXILRootSignature.cpp index a0c64fbb752c7..a4f5086c2f428 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.cpp +++ b/llvm/lib/Target/DirectX/DXILRootSignature.cpp @@ -233,7 +233,7 @@ bool RootSignatureAnalysisWrapper::runOnModule(Module &M) { void RootSignatureAnalysisWrapper::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addRequired(); + AU.addPreserved(); } char RootSignatureAnalysisWrapper::ID = 0; @@ -241,7 +241,6 @@ char RootSignatureAnalysisWrapper::ID = 0; INITIALIZE_PASS_BEGIN(RootSignatureAnalysisWrapper, "dxil-root-signature-analysis", "DXIL Root Signature Analysis", true, true) -INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass) INITIALIZE_PASS_END(RootSignatureAnalysisWrapper, "dxil-root-signature-analysis", "DXIL Root Signature Analysis", true, true) diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 4b6c6eb3726e5..254b7ff504633 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -96,4 +96,4 @@ class RootSignatureAnalysisPrinter } // namespace dxil } // namespace llvm -#endif // LLVM_LIB_TARGET_DIRECTX_DXILROOTSIGNATURE_H +#endif From 03d571a01c27f6dedb689544d379b2a6cf05c6c3 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 5 Aug 2025 18:26:53 -0700 Subject: [PATCH 054/143] clean? --- .../DXILPostOptimizationValidation.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index cef6c8381a88b..3ed9ef8979a2f 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -114,6 +114,21 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } +static void reportOverlappingRegisters( + Module &M, const llvm::hlsl::BindingInfoBuilder::Binding &Reported, + const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping) { + SmallString<128> Message; + raw_svector_ostream OS(Message); + OS << "register " << getResourceClassName(Reported.RC) + << " (space=" << Reported.Space << ", register=" << Reported.LowerBound + << ")" << " is overlapping with" << " register " + << getResourceClassName(Overlaping.RC) << " (space=" << Overlaping.Space + << ", register=" << Overlaping.LowerBound << ")" + << ", verify your root signature definition."; + + M.getContext().diagnose(DiagnosticInfoGeneric(Message)); +} + static void reportRegNotBound(Module &M, ResourceClass Class, llvm::dxil::ResourceInfo::ResourceBinding Unbound) { @@ -154,21 +169,6 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) { } } -static void reportOverlappingRegisters( - Module &M, const llvm::hlsl::BindingInfoBuilder::Binding &Reported, - const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping) { - SmallString<128> Message; - raw_svector_ostream OS(Message); - OS << "register " << getResourceClassName(Reported.RC) - << " (space=" << Reported.Space << ", register=" << Reported.LowerBound - << ")" << " is overlapping with" << " register " - << getResourceClassName(Overlaping.RC) << " (space=" << Overlaping.Space - << ", register=" << Overlaping.LowerBound << ")" - << ", verify your root signature definition."; - - M.getContext().diagnose(DiagnosticInfoGeneric(Message)); -} - static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder, const mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) { From 7c9bd624028e5464631c05d200784b7639a6bdc2 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 5 Aug 2025 19:49:19 -0700 Subject: [PATCH 055/143] clean? --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 129a6dd28cbc1..d12ad64721568 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -10,8 +10,6 @@ #include "DXILRootSignature.h" #include "DXILShaderFlags.h" #include "DirectX.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" From ef51048d94229dbec1764a4defd513ee9928375d Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 5 Aug 2025 19:54:27 -0700 Subject: [PATCH 056/143] format --- .../DirectX/DXILPostOptimizationValidation.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 3ed9ef8979a2f..69916dfd9f509 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -258,9 +258,10 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, trackRootSigDescBinding(Builder, *RSD, Visibility); bool HasOverlap = false; hlsl::BindingInfo Info = Builder.calculateBindingInfo( - [&M, &HasOverlap](const llvm::hlsl::BindingInfoBuilder &Builder, - const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) { - HasOverlap = true; + [&M, &HasOverlap]( + const llvm::hlsl::BindingInfoBuilder &Builder, + const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) { + HasOverlap = true; const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping = Builder.findOverlapping(ReportedBinding); reportOverlappingRegisters(M, ReportedBinding, Overlaping); @@ -268,12 +269,13 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, // Next checks require that the root signature definition is valid. if (!HasOverlap){ for (const auto &ResList : - {std::make_pair(ResourceClass::SRV, DRM.srvs()), + {std::make_pair(ResourceClass::SRV, DRM.srvs()), std::make_pair(ResourceClass::UAV, DRM.uavs()), std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { for (auto Res : ResList.second) { - llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); + llvm::dxil::ResourceInfo::ResourceBinding ResBinding = + Res.getBinding(); llvm::hlsl::BindingInfo::BindingRange ResRange( ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); From 21675e61731acf7b204a117b89fb7e3a973f5277 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:06:55 -0700 Subject: [PATCH 057/143] formating --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 69916dfd9f509..09e7d9a90de00 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -267,7 +267,7 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, reportOverlappingRegisters(M, ReportedBinding, Overlaping); }); // Next checks require that the root signature definition is valid. - if (!HasOverlap){ + if (!HasOverlap) { for (const auto &ResList : {std::make_pair(ResourceClass::SRV, DRM.srvs()), std::make_pair(ResourceClass::UAV, DRM.uavs()), From 849ff8617832cf5d8148543c7107e2e98471e344 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:10:51 -0700 Subject: [PATCH 058/143] format --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index d12ad64721568..dc08a7d0244f2 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -295,7 +295,7 @@ static void reportInvalidHandleTy( llvm::dxil::ResourceInfo::ResourceBinding Binding = Res->getBinding(); for (const auto &RD : RDs) { if (Binding.overlapsWith(RD)) { - TargetExtType *Handle = Res->getHandleTy(); + TargetExtType *Handle = Res->getHandleTy(); auto *TypedBuffer = dyn_cast_or_null(Handle); auto *Texture = dyn_cast_or_null(Handle); @@ -336,7 +336,7 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, // Next checks require that the root signature definition is valid. if (!HasOverlap){ SmallVector RDs = - getRootDescriptorsBindingInfo(*RSD, Visibility); + getRootDescriptorsBindingInfo(*RSD, Visibility); for (const auto &ResList : {std::make_pair(ResourceClass::SRV, DRM.srvs()), std::make_pair(ResourceClass::UAV, DRM.uavs()), From 7a1bc21bb289613778353375477ac62980904581 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:11:09 -0700 Subject: [PATCH 059/143] format --- 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 dc08a7d0244f2..33fc9f218bd5b 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -351,7 +351,6 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, reportRegNotBound(M, ResList.first, ResBinding); } reportInvalidHandleTy(M, RDs, ResList.second); - } } } From 403972dbde579a83de8c6a2b7ec2468be2c2b202 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 7 Aug 2025 15:07:56 -0700 Subject: [PATCH 060/143] addressing comments from bogner and inbelic --- llvm/include/llvm/Analysis/DXILResource.h | 15 -- llvm/include/llvm/Support/DXILABI.h | 3 + llvm/lib/Support/DXILABI.cpp | 19 +++ llvm/lib/Target/DirectX/DXILOpLowering.cpp | 1 + .../DXILPostOptimizationValidation.cpp | 135 ++++++++---------- llvm/lib/Target/DirectX/DXILRootSignature.h | 8 +- ...e-validation-fail-root-descriptor-range.ll | 3 +- 7 files changed, 90 insertions(+), 94 deletions(-) create mode 100644 llvm/lib/Support/DXILABI.cpp diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index 96d631698af0a..557fc513c2a57 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -32,21 +32,6 @@ class Value; class DXILResourceTypeMap; namespace dxil { - -inline StringRef getResourceClassName(ResourceClass RC) { - switch (RC) { - case ResourceClass::SRV: - return "SRV"; - case ResourceClass::UAV: - return "UAV"; - case ResourceClass::CBuffer: - return "CBuffer"; - case ResourceClass::Sampler: - return "Sampler"; - } - llvm_unreachable("Unhandled ResourceClass"); -} - // Returns the resource name from dx_resource_handlefrombinding or // dx_resource_handlefromimplicitbinding call LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI); diff --git a/llvm/include/llvm/Support/DXILABI.h b/llvm/include/llvm/Support/DXILABI.h index b479f7c73eba3..397906a3466c5 100644 --- a/llvm/include/llvm/Support/DXILABI.h +++ b/llvm/include/llvm/Support/DXILABI.h @@ -17,6 +17,7 @@ #ifndef LLVM_SUPPORT_DXILABI_H #define LLVM_SUPPORT_DXILABI_H +#include "llvm/ADT/StringRef.h" #include namespace llvm { @@ -99,6 +100,8 @@ enum class SamplerFeedbackType : uint32_t { const unsigned MinWaveSize = 4; const unsigned MaxWaveSize = 128; +StringRef getResourceClassName(ResourceClass RC); + } // namespace dxil } // namespace llvm diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp new file mode 100644 index 0000000000000..510e15b403ab1 --- /dev/null +++ b/llvm/lib/Support/DXILABI.cpp @@ -0,0 +1,19 @@ + +#include "llvm/Support/DXILABI.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +StringRef getResourceClassName(dxil::ResourceClass RC) { + switch (RC) { + case dxil::ResourceClass::SRV: + return "SRV"; + case dxil::ResourceClass::UAV: + return "UAV"; + case dxil::ResourceClass::CBuffer: + return "CBuffer"; + case dxil::ResourceClass::Sampler: + return "Sampler"; + } + llvm_unreachable("Unhandled ResourceClass"); +} \ No newline at end of file diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index db7719e129ad0..1cfba523183c8 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -919,6 +919,7 @@ PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) { PA.preserve(); PA.preserve(); PA.preserve(); + PA.preserve(); return PA; } diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 3da4cfbea23b8..368c8c6b5dbba 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -13,21 +13,22 @@ #include "llvm/ADT/SmallString.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" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" +#include #define DEBUG_TYPE "dxil-post-optimization-validation" using namespace llvm; using namespace llvm::dxil; -namespace { -static ResourceClass RangeToResourceClass(uint32_t RangeType) { +static ResourceClass toResourceClass(dxbc::DescriptorRangeType RangeType) { using namespace dxbc; - switch (static_cast(RangeType)) { + switch (RangeType) { case DescriptorRangeType::SRV: return ResourceClass::SRV; case DescriptorRangeType::UAV: @@ -39,20 +40,21 @@ static ResourceClass RangeToResourceClass(uint32_t RangeType) { } } -ResourceClass ParameterToResourceClass(uint32_t Type) { +static ResourceClass toResourceClass(dxbc::RootParameterType Type) { using namespace dxbc; switch (Type) { - case llvm::to_underlying(RootParameterType::Constants32Bit): + case RootParameterType::Constants32Bit: return ResourceClass::CBuffer; - case llvm::to_underlying(RootParameterType::SRV): + case RootParameterType::SRV: return ResourceClass::SRV; - case llvm::to_underlying(RootParameterType::UAV): + case RootParameterType::UAV: return ResourceClass::UAV; - case llvm::to_underlying(RootParameterType::CBV): + case RootParameterType::CBV: return ResourceClass::CBuffer; - default: - llvm_unreachable("Unknown RootParameterType"); + case dxbc::RootParameterType::DescriptorTable: + break; } + llvm_unreachable("Unconvertible RootParameterType"); } static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) { @@ -131,12 +133,6 @@ static void reportOverlappingRegisters( static dxbc::ShaderVisibility tripleToVisibility(llvm::Triple::EnvironmentType ET) { - assert((ET == Triple::Pixel || ET == Triple::Vertex || - ET == Triple::Geometry || ET == Triple::Hull || - ET == Triple::Domain || ET == Triple::Mesh || - ET == Triple::Compute) && - "Invalid Triple to shader stage conversion"); - switch (ET) { case Triple::Pixel: return dxbc::ShaderVisibility::Pixel; @@ -157,73 +153,80 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) { } } -static void trackRootSigDescBinding(hlsl::BindingInfoBuilder &Builder, - const mcdxbc::RootSignatureDesc &RSD, - dxbc::ShaderVisibility Visibility) { - 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); - if (Header.ShaderVisibility != - llvm::to_underlying(dxbc::ShaderVisibility::All) && - Header.ShaderVisibility != llvm::to_underlying(Visibility)) - continue; +static void validateRootSignature(Module &M, + const mcdxbc::RootSignatureDesc &RSD, + dxil::ModuleMetadataInfo &MMI) { - switch (Type) { - case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): { + hlsl::BindingInfoBuilder Builder; + dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); + + for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) { + dxbc::ShaderVisibility ParamVisibility = + static_cast(ParamInfo.Header.ShaderVisibility); + if (ParamVisibility != dxbc::ShaderVisibility::All && + ParamVisibility != Visibility) + continue; + dxbc::RootParameterType ParamType = + static_cast(ParamInfo.Header.ParameterType); + switch (ParamType) { + case dxbc::RootParameterType::Constants32Bit: { dxbc::RTS0::v1::RootConstants Const = - RSD.ParametersContainer.getConstant(Loc); + RSD.ParametersContainer.getConstant(ParamInfo.Location); Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace, - Const.ShaderRegister, - Const.ShaderRegister + Const.Num32BitValues, &Const); + Const.ShaderRegister, Const.ShaderRegister, nullptr); break; } - case llvm::to_underlying(dxbc::RootParameterType::SRV): - case llvm::to_underlying(dxbc::RootParameterType::UAV): - case llvm::to_underlying(dxbc::RootParameterType::CBV): { + case dxbc::RootParameterType::SRV: + case dxbc::RootParameterType::UAV: + case dxbc::RootParameterType::CBV: { dxbc::RTS0::v2::RootDescriptor Desc = - RSD.ParametersContainer.getRootDescriptor(Loc); - Builder.trackBinding(ParameterToResourceClass(Type), Desc.RegisterSpace, - Desc.ShaderRegister, Desc.ShaderRegister, &Desc); + RSD.ParametersContainer.getRootDescriptor(ParamInfo.Location); + Builder.trackBinding(toResourceClass(static_cast( + ParamInfo.Header.ParameterType)), + Desc.RegisterSpace, Desc.ShaderRegister, + Desc.ShaderRegister, nullptr); break; } - case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): { + case dxbc::RootParameterType::DescriptorTable: { const mcdxbc::DescriptorTable &Table = - RSD.ParametersContainer.getDescriptorTable(Loc); + RSD.ParametersContainer.getDescriptorTable(ParamInfo.Location); for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { - Builder.trackBinding(RangeToResourceClass(Range.RangeType), - Range.RegisterSpace, Range.BaseShaderRegister, - Range.NumDescriptors == ~0U - ? Range.NumDescriptors - : Range.BaseShaderRegister + - Range.NumDescriptors, - &Range); + uint32_t UpperBound = + Range.NumDescriptors == ~0U + ? Range.BaseShaderRegister + : Range.BaseShaderRegister + Range.NumDescriptors - 1; + Builder.trackBinding( + toResourceClass( + static_cast(Range.RangeType)), + Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, nullptr); } break; } } } - for (auto &S : RSD.StaticSamplers) { + for (const dxbc::RTS0::v1::StaticSampler &S : RSD.StaticSamplers) Builder.trackBinding(dxil::ResourceClass::Sampler, S.RegisterSpace, - S.ShaderRegister, S.ShaderRegister, &S); - } + S.ShaderRegister, S.ShaderRegister, nullptr); + + hlsl::BindingInfo Info = Builder.calculateBindingInfo( + [&M](const llvm::hlsl::BindingInfoBuilder &Builder, + const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) { + const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping = + Builder.findOverlapping(ReportedBinding); + reportOverlappingRegisters(M, ReportedBinding, Overlaping); + }); } -std::optional +static mcdxbc::RootSignatureDesc * getRootSignature(RootSignatureBindingInfo &RSBI, dxil::ModuleMetadataInfo &MMI) { if (MMI.EntryPropertyVec.size() == 0) - return std::nullopt; - std::optional RootSigDesc = - RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); - if (!RootSigDesc) - return std::nullopt; - return RootSigDesc; + return nullptr; + return RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); } static void reportErrors(Module &M, DXILResourceMap &DRM, @@ -239,21 +242,9 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in " "DXILResourceImplicitBinding pass"); - if (auto RSD = getRootSignature(RSBI, MMI)) { - - hlsl::BindingInfoBuilder Builder; - dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); - trackRootSigDescBinding(Builder, *RSD, Visibility); - hlsl::BindingInfo Info = Builder.calculateBindingInfo( - [&M](const llvm::hlsl::BindingInfoBuilder &Builder, - const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) { - const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping = - Builder.findOverlapping(ReportedBinding); - reportOverlappingRegisters(M, ReportedBinding, Overlaping); - }); - } + if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI)) + validateRootSignature(M, *RSD, MMI); } -} // namespace PreservedAnalyses DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) { diff --git a/llvm/lib/Target/DirectX/DXILRootSignature.h b/llvm/lib/Target/DirectX/DXILRootSignature.h index 254b7ff504633..b990b6c7410ac 100644 --- a/llvm/lib/Target/DirectX/DXILRootSignature.h +++ b/llvm/lib/Target/DirectX/DXILRootSignature.h @@ -43,13 +43,11 @@ class RootSignatureBindingInfo { iterator end() { return FuncToRsMap.end(); } - std::optional - getDescForFunction(const Function *F) { + mcdxbc::RootSignatureDesc *getDescForFunction(const Function *F) { const auto FuncRs = find(F); if (FuncRs == end()) - return std::nullopt; - - return FuncRs->second; + return nullptr; + return &FuncRs->second; } }; 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 index 9f70cc3f062a9..38674d9ba0c6d 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll @@ -6,10 +6,9 @@ entry: ret void } -; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), UAV(u3, space=1) !dx.rootsignatures = !{!0} !0 = !{ptr @CSMain, !1, i32 2} !1 = !{!2, !4} !2 = !{!"RootUAV", i32 0, i32 3, i32 1, i32 4} !4 = !{!"DescriptorTable", i32 0, !5} -!5 = !{!"UAV", i32 3, i32 0, i32 1, i32 -1, i32 2} +!5 = !{!"UAV", i32 4, i32 0, i32 1, i32 -1, i32 2} From 0f0435d6b43a0364c2a0dfc89bd94df57b6a6c99 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 7 Aug 2025 15:16:14 -0700 Subject: [PATCH 061/143] clean up --- llvm/include/llvm/Analysis/DXILResource.h | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h index 557fc513c2a57..93c6bfb057ef5 100644 --- a/llvm/include/llvm/Analysis/DXILResource.h +++ b/llvm/include/llvm/Analysis/DXILResource.h @@ -32,6 +32,7 @@ class Value; class DXILResourceTypeMap; namespace dxil { + // Returns the resource name from dx_resource_handlefrombinding or // dx_resource_handlefromimplicitbinding call LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI); From e841a98b1cefbcd92c4f3f9ed050dc33f07b0299 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 7 Aug 2025 15:18:21 -0700 Subject: [PATCH 062/143] clean up --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 368c8c6b5dbba..80cbc9b6bee57 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -13,13 +13,11 @@ #include "llvm/ADT/SmallString.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" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" -#include #define DEBUG_TYPE "dxil-post-optimization-validation" From ae6d67a18553ab4d2608e46ccc0ca7c9edfba591 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 7 Aug 2025 16:34:12 -0700 Subject: [PATCH 063/143] fix build --- llvm/lib/Analysis/DXILResource.cpp | 1 + llvm/lib/Support/CMakeLists.txt | 1 + llvm/lib/Support/DXILABI.cpp | 7 +++++-- llvm/lib/Target/DirectX/DXContainerGlobals.cpp | 3 +-- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 2 +- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 1 + 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp index b476026fcc718..5aeee6f681114 100644 --- a/llvm/lib/Analysis/DXILResource.cpp +++ b/llvm/lib/Analysis/DXILResource.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" +#include "llvm/Support/DXILABI.h" #include "llvm/Support/FormatVariadic.h" #include #include diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt index 10b6101d73277..b7578dd580072 100644 --- a/llvm/lib/Support/CMakeLists.txt +++ b/llvm/lib/Support/CMakeLists.txt @@ -182,6 +182,7 @@ add_llvm_component_library(LLVMSupport DivisionByConstantInfo.cpp DAGDeltaAlgorithm.cpp DJB.cpp + DXILABI.cpp DynamicAPInt.cpp ELFAttributes.cpp ELFAttrParserCompact.cpp diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp index 510e15b403ab1..e45e86922cb39 100644 --- a/llvm/lib/Support/DXILABI.cpp +++ b/llvm/lib/Support/DXILABI.cpp @@ -3,7 +3,8 @@ #include "llvm/Support/ErrorHandling.h" using namespace llvm; - +namespace llvm { +namespace dxil { StringRef getResourceClassName(dxil::ResourceClass RC) { switch (RC) { case dxil::ResourceClass::SRV: @@ -16,4 +17,6 @@ StringRef getResourceClassName(dxil::ResourceClass RC) { return "Sampler"; } llvm_unreachable("Unhandled ResourceClass"); -} \ No newline at end of file +} +} // namespace dxil +} // namespace llvm \ No newline at end of file diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 26a113d2d5260..a1ef2578f00aa 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -162,8 +162,7 @@ void DXContainerGlobals::addRootSignature(Module &M, auto &RSA = getAnalysis().getRSInfo(); const Function *EntryFunction = MMI.EntryPropertyVec[0].Entry; - const std::optional &RS = - RSA.getDescForFunction(EntryFunction); + const mcdxbc::RootSignatureDesc *RS = RSA.getDescForFunction(EntryFunction); if (!RS) return; diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 1cfba523183c8..247ba7d93b3c2 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -919,7 +919,7 @@ PreservedAnalyses DXILOpLowering::run(Module &M, ModuleAnalysisManager &MAM) { PA.preserve(); PA.preserve(); PA.preserve(); - PA.preserve(); + PA.preserve(); return PA; } diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 80cbc9b6bee57..cbb4307949f86 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/DXILABI.h" #define DEBUG_TYPE "dxil-post-optimization-validation" From 41f32bd5ded0e14cfef0f2dd3ec8f5b9594d0f72 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 8 Aug 2025 10:44:24 -0700 Subject: [PATCH 064/143] fix tests --- .../DirectX/DXILPostOptimizationValidation.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index cbb4307949f86..7dc1ac0a5c0f2 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -158,7 +158,7 @@ static void validateRootSignature(Module &M, hlsl::BindingInfoBuilder Builder; dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); - + SmallVector IDs; for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) { dxbc::ShaderVisibility ParamVisibility = static_cast(ParamInfo.Header.ShaderVisibility); @@ -172,7 +172,8 @@ static void validateRootSignature(Module &M, dxbc::RTS0::v1::RootConstants Const = RSD.ParametersContainer.getConstant(ParamInfo.Location); Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace, - Const.ShaderRegister, Const.ShaderRegister, nullptr); + Const.ShaderRegister, Const.ShaderRegister, + &IDs.emplace_back()); break; } @@ -184,7 +185,7 @@ static void validateRootSignature(Module &M, Builder.trackBinding(toResourceClass(static_cast( ParamInfo.Header.ParameterType)), Desc.RegisterSpace, Desc.ShaderRegister, - Desc.ShaderRegister, nullptr); + Desc.ShaderRegister, &IDs.emplace_back()); break; } @@ -200,7 +201,8 @@ static void validateRootSignature(Module &M, Builder.trackBinding( toResourceClass( static_cast(Range.RangeType)), - Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, nullptr); + Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, + &IDs.emplace_back()); } break; } @@ -209,7 +211,8 @@ static void validateRootSignature(Module &M, for (const dxbc::RTS0::v1::StaticSampler &S : RSD.StaticSamplers) Builder.trackBinding(dxil::ResourceClass::Sampler, S.RegisterSpace, - S.ShaderRegister, S.ShaderRegister, nullptr); + S.ShaderRegister, S.ShaderRegister, + &IDs.emplace_back()); hlsl::BindingInfo Info = Builder.calculateBindingInfo( [&M](const llvm::hlsl::BindingInfoBuilder &Builder, From 6da5fb01cf4b92c0a94b0629bdc65cd94c23827e Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:46:50 -0700 Subject: [PATCH 065/143] format --- .../DXILPostOptimizationValidation.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 44eec17e87fb8..80054f3a516b7 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -228,31 +228,31 @@ static void validateRootSignature(Module &M, &IDs.emplace_back()); bool HasOverlap = false; hlsl::BindingInfo Info = Builder.calculateBindingInfo( - [&M, &HasOverlap](const llvm::hlsl::BindingInfoBuilder &Builder, + [&M, &HasOverlap]( + const llvm::hlsl::BindingInfoBuilder &Builder, const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) { - HasOverlap = true; - const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping = + HasOverlap = true; + const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping = Builder.findOverlapping(ReportedBinding); - reportOverlappingRegisters(M, ReportedBinding, Overlaping); + reportOverlappingRegisters(M, ReportedBinding, Overlaping); }); - // Next checks require that the root signature definition is valid. - if (!HasOverlap) { - for (const auto &ResList : - {std::make_pair(ResourceClass::SRV, DRM.srvs()), - std::make_pair(ResourceClass::UAV, DRM.uavs()), - std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), - std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { - for (auto Res : ResList.second) { - llvm::dxil::ResourceInfo::ResourceBinding ResBinding = - Res.getBinding(); - llvm::hlsl::BindingInfo::BindingRange ResRange( - ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); - - if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) - reportRegNotBound(M, ResList.first, ResBinding); - } + // Next checks require that the root signature definition is valid. + if (!HasOverlap) { + for (const auto &ResList : + {std::make_pair(ResourceClass::SRV, DRM.srvs()), + std::make_pair(ResourceClass::UAV, DRM.uavs()), + std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), + std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { + for (auto Res : ResList.second) { + llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); + llvm::hlsl::BindingInfo::BindingRange ResRange( + ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); + + if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) + reportRegNotBound(M, ResList.first, ResBinding); } } + } } static mcdxbc::RootSignatureDesc * From db73d716287c775686245455884327d734749ec2 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Fri, 8 Aug 2025 13:04:21 -0700 Subject: [PATCH 066/143] update --- llvm/lib/Support/DXILABI.cpp | 14 +++----------- .../rootsignature-validation-fail-cbuffer-range.ll | 2 +- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp index e45e86922cb39..3596a766b4388 100644 --- a/llvm/lib/Support/DXILABI.cpp +++ b/llvm/lib/Support/DXILABI.cpp @@ -1,22 +1,14 @@ #include "llvm/Support/DXILABI.h" +#include "llvm/BinaryFormat/DXContainer.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ScopedPrinter.h" using namespace llvm; namespace llvm { namespace dxil { StringRef getResourceClassName(dxil::ResourceClass RC) { - switch (RC) { - case dxil::ResourceClass::SRV: - return "SRV"; - case dxil::ResourceClass::UAV: - return "UAV"; - case dxil::ResourceClass::CBuffer: - return "CBuffer"; - case dxil::ResourceClass::Sampler: - return "Sampler"; - } - llvm_unreachable("Unhandled ResourceClass"); + return enumToStringRef(RC, dxbc::getResourceClasses()); } } // namespace dxil } // namespace llvm \ No newline at end of file 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 47d2a5b8d5aab..2f206702394a1 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.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: register CBuffer (space=0, register=2) is overlapping with register CBuffer (space=0, register=0), verify your root signature definition. +; CHECK: error: register CBV (space=0, register=2) is overlapping with register CBV (space=0, register=0), verify your root signature definition. define void @CSMain() "hlsl.shader"="compute" { entry: From 3b04c2d0b534502ab876803f3a52fce9e8078497 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:34:47 -0700 Subject: [PATCH 067/143] address comment from inbelic --- .../DirectX/DXILPostOptimizationValidation.cpp | 17 ++++++++--------- ...otsignature-validation-fail-cbuffer-range.ll | 2 +- ...re-validation-fail-descriptor-table-range.ll | 2 +- ...ure-validation-fail-root-descriptor-range.ll | 2 +- ...ture-validation-fail-static-sampler-range.ll | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 7dc1ac0a5c0f2..c3e7c9930ee3a 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -116,17 +116,16 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } static void reportOverlappingRegisters( - Module &M, const llvm::hlsl::BindingInfoBuilder::Binding &Reported, - const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping) { + Module &M, const llvm::hlsl::BindingInfoBuilder::Binding &R1, + const llvm::hlsl::BindingInfoBuilder::Binding &R2) { SmallString<128> Message; - raw_svector_ostream OS(Message); - OS << "register " << getResourceClassName(Reported.RC) - << " (space=" << Reported.Space << ", register=" << Reported.LowerBound - << ")" << " is overlapping with" << " register " - << getResourceClassName(Overlaping.RC) << " (space=" << Overlaping.Space - << ", register=" << Overlaping.LowerBound << ")" - << ", verify your root signature definition."; + raw_svector_ostream OS(Message); + OS << "resource " << getResourceClassName(R1.RC) << " (space="<< R1.Space + << ", registers=[" << R1.LowerBound << ", " + << R1.UpperBound << "]) overlaps with resource " << getResourceClassName(R2.RC) + << " (space="<< R2.Space << ", registers=[" + << R2.LowerBound << ", " << R2.UpperBound << "])"; M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } 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 2f206702394a1..3d3f57d136845 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.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: register CBV (space=0, register=2) is overlapping with register CBV (space=0, register=0), verify your root signature definition. +; CHECK: error: resource CBV (space=0, registers=[2, 2]) overlaps with resource CBV (space=0, registers=[0, 2]) define void @CSMain() "hlsl.shader"="compute" { entry: diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll index dbc75ac86db5f..1093aa3e38611 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.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: register UAV (space=10, register=4294967295) is overlapping with register UAV (space=10, register=4294967295), verify your root signature definition. +; CHECK: error: resource UAV (space=10, registers=[4294967295, 4294967295]) overlaps with resource UAV (space=10, registers=[4294967295, 4294967295]) define void @CSMain() "hlsl.shader"="compute" { entry: ret void 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 index 38674d9ba0c6d..4e6a3e7e49608 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.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: register UAV (space=1, register=3) is overlapping with register UAV (space=1, register=0), verify your root signature definition. +; CHECK: error: resource UAV (space=1, registers=[3, 3]) overlaps with resource UAV (space=1, registers=[0, 3]) define void @CSMain() "hlsl.shader"="compute" { entry: diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll index 340b0aed6d16b..66649f7ffc653 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.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: register Sampler (space=0, register=42) is overlapping with register Sampler (space=0, register=42), verify your root signature definition. +; CHECK: error: resource Sampler (space=0, registers=[42, 42]) overlaps with resource Sampler (space=0, registers=[42, 42]) define void @CSMain() "hlsl.shader"="compute" { entry: From 1ddffc3c079ed5226ea5b1c3ea56887f108d3cd0 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:44:09 -0700 Subject: [PATCH 068/143] address comments 2 --- .../DirectX/DXILPostOptimizationValidation.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index c3e7c9930ee3a..a4ecafd3b7041 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -115,17 +115,18 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { } } -static void reportOverlappingRegisters( - Module &M, const llvm::hlsl::BindingInfoBuilder::Binding &R1, - const llvm::hlsl::BindingInfoBuilder::Binding &R2) { +static void +reportOverlappingRegisters(Module &M, + const llvm::hlsl::BindingInfoBuilder::Binding &R1, + const llvm::hlsl::BindingInfoBuilder::Binding &R2) { SmallString<128> Message; raw_svector_ostream OS(Message); - OS << "resource " << getResourceClassName(R1.RC) << " (space="<< R1.Space - << ", registers=[" << R1.LowerBound << ", " - << R1.UpperBound << "]) overlaps with resource " << getResourceClassName(R2.RC) - << " (space="<< R2.Space << ", registers=[" - << R2.LowerBound << ", " << R2.UpperBound << "])"; + OS << "resource " << getResourceClassName(R1.RC) << " (space=" << R1.Space + << ", registers=[" << R1.LowerBound << ", " << R1.UpperBound + << "]) overlaps with resource " << getResourceClassName(R2.RC) + << " (space=" << R2.Space << ", registers=[" << R2.LowerBound << ", " + << R2.UpperBound << "])"; M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } From 1c10acf8f68273fc9e729d0dc15bb677390b9bfa Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:45:53 -0700 Subject: [PATCH 069/143] fix merge mess --- 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 abcefe287d9bc..c444d8d0e481d 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -309,7 +309,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 RDs = getRootDescriptorsBindingInfo(RSD, Visibility); 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 070/143] 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 #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 &RDs, const iterator_range::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(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(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 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 071/143] 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(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 &RDs, const iterator_range::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(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 072/143] 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 #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 073/143] 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(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(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(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 074/143] 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(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 075/143] 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 076/143] 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 db0008ec5a49f315bb85f411f189f117abf10eab Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 14:39:47 -0700 Subject: [PATCH 077/143] addressing comments from inbelic --- .../DirectX/DXILPostOptimizationValidation.cpp | 2 +- .../DirectX/rootsignature-validation-constants.ll | 8 -------- .../test/CodeGen/DirectX/rootsignature-validation.ll | 12 ------------ 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index a4ecafd3b7041..1bd7a438a4575 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -214,7 +214,7 @@ static void validateRootSignature(Module &M, S.ShaderRegister, S.ShaderRegister, &IDs.emplace_back()); - hlsl::BindingInfo Info = Builder.calculateBindingInfo( + Builder.calculateBindingInfo( [&M](const llvm::hlsl::BindingInfoBuilder &Builder, const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) { const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping = diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll index 3c33f1dc6bdf0..ab8c51629fa53 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll @@ -2,16 +2,8 @@ ; 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 } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll index 750679bf743c5..67a57d05e65ee 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -8,21 +8,9 @@ ; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_VERTEX) ; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) -%__cblayout_CB = type <{ float }> - -@CB.str = private unnamed_addr constant [3 x i8] c"CB\00", align 1 -@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 -@SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1 -@RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1 define void @CSMain() "hlsl.shader"="compute" { entry: - - %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 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.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 @RWB.str) - ret void } From 0c72dcfcfea6b2bf3562fc94108b226ef52437e9 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 15:25:57 -0700 Subject: [PATCH 078/143] addressing inbelic comments --- llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 10 ++++--- .../DXILPostOptimizationValidation.cpp | 26 +++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index 57075ca430d44..f69a7ce37b403 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -67,9 +67,13 @@ BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) { } bool BindingInfo::RegisterSpace::isBound(BindingRange B) { - for (BindingRange &R : FreeRanges) { - if (B.LowerBound >= R.LowerBound && B.LowerBound < R.UpperBound && - B.UpperBound > R.LowerBound && B.UpperBound <= R.UpperBound) + BindingRange *It = llvm::lower_bound( + FreeRanges, B.LowerBound, + [](const BindingRange &R, uint32_t Val) { return R.UpperBound <= Val; }); + + if (It != FreeRanges.end()) { + // Check if B is fully contained in the found range + if (B.LowerBound >= It->LowerBound && B.UpperBound <= It->UpperBound) return false; } return true; diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 80054f3a516b7..2ad8628251ee6 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -237,20 +237,18 @@ static void validateRootSignature(Module &M, reportOverlappingRegisters(M, ReportedBinding, Overlaping); }); // Next checks require that the root signature definition is valid. - if (!HasOverlap) { - for (const auto &ResList : - {std::make_pair(ResourceClass::SRV, DRM.srvs()), - std::make_pair(ResourceClass::UAV, DRM.uavs()), - std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), - std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { - for (auto Res : ResList.second) { - llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); - llvm::hlsl::BindingInfo::BindingRange ResRange( - ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); - - if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) - reportRegNotBound(M, ResList.first, ResBinding); - } + for (const auto &ResList : + {std::make_pair(ResourceClass::SRV, DRM.srvs()), + std::make_pair(ResourceClass::UAV, DRM.uavs()), + std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), + std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { + for (auto Res : ResList.second) { + llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); + llvm::hlsl::BindingInfo::BindingRange ResRange( + ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); + + if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) + reportRegNotBound(M, ResList.first, ResBinding); } } } From b4e5fb4e393cb3f4918821596e5186725e5c7205 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Tue, 12 Aug 2025 15:42:18 -0700 Subject: [PATCH 079/143] adding test --- .../rootsignature-validation-fail-sampler.ll | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll new file mode 100644 index 0000000000000..a29c00fe0f2f4 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.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: resource Sampler (space=0, registers=[42, 42]) overlaps with resource Sampler (space=0, registers=[42, 42]) + +define void @CSMain() "hlsl.shader"="compute" { +entry: + ret void +} + +!dx.rootsignatures = !{!0} +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2, !3} +!2 = !{ !"StaticSampler", i32 5, i32 4, i32 5, i32 3, float 0x3FF7CCCCC0000000, i32 10, i32 2, i32 1, float -1.270000e+02, float 1.220000e+02, i32 42, i32 0, i32 0 } +!3 = !{!"DescriptorTable", i32 0, !4} +!4 = !{!"Sampler", i32 1, i32 42, i32 0, i32 -1, i32 0} \ No newline at end of file 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 080/143] 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 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 class RootSignatureValidationError : public ErrorInfo> { @@ -47,6 +81,52 @@ class RootSignatureValidationError } }; +class TableRegisterOverflowError + : public ErrorInfo { +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 { +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 { 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 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 char RootSignatureValidationError::ID; static std::optional 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(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(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(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( + 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( + 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( + 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>( "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(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 &RDs, const iterator_range::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(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(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( - ParamInfo.Header.ParameterType)), - Desc.RegisterSpace, Desc.ShaderRegister, - Desc.ShaderRegister, &IDs.emplace_back()); + Builder.trackBinding( + hlsl::rootsig::toResourceClass(static_cast( + 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(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 081/143] 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 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 class RootSignatureValidationError : public ErrorInfo> { @@ -47,6 +81,51 @@ class RootSignatureValidationError } }; +class TableRegisterOverflowError + : public ErrorInfo { +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 { +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 { 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 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 char RootSignatureValidationError::ID; static std::optional 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(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(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(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( + 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( + 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( + 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>( "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(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 &RDs, const iterator_range::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(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(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( - ParamInfo.Header.ParameterType)), - Desc.RegisterSpace, Desc.ShaderRegister, - Desc.ShaderRegister, &IDs.emplace_back()); + Builder.trackBinding( + hlsl::rootsig::toResourceClass(static_cast( + 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(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 082/143] 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 4a655a54ed2d6a9503f78e6ca11cd9bbf8e2ccb8 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Wed, 13 Aug 2025 10:50:52 -0700 Subject: [PATCH 083/143] addressing comments from bogner --- llvm/lib/Support/DXILABI.cpp | 23 ++++++++++++------- .../DXILPostOptimizationValidation.cpp | 3 ++- ...-validation-fail-descriptor-table-range.ll | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp index 3596a766b4388..8d60e1a1b3ba8 100644 --- a/llvm/lib/Support/DXILABI.cpp +++ b/llvm/lib/Support/DXILABI.cpp @@ -1,14 +1,21 @@ +//===-- DXILABI.cpp - ABI Sensitive Values for DXIL ---------------*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements functions that can be reused accross different stages +// dxil generation. +// +//===----------------------------------------------------------------------===// -#include "llvm/Support/DXILABI.h" #include "llvm/BinaryFormat/DXContainer.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ScopedPrinter.h" - using namespace llvm; -namespace llvm { -namespace dxil { -StringRef getResourceClassName(dxil::ResourceClass RC) { + +StringRef dxil::getResourceClassName(dxil::ResourceClass RC) { return enumToStringRef(RC, dxbc::getResourceClasses()); } -} // namespace dxil -} // namespace llvm \ No newline at end of file diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 1bd7a438a4575..3918dfd13e5e3 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -51,9 +51,10 @@ static ResourceClass toResourceClass(dxbc::RootParameterType Type) { case RootParameterType::CBV: return ResourceClass::CBuffer; case dxbc::RootParameterType::DescriptorTable: + llvm_unreachable("DescriptorTable is not convertible to ResourceClass"); break; } - llvm_unreachable("Unconvertible RootParameterType"); + llvm_unreachable("Unknown RootParameterType"); } static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) { diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll index 1093aa3e38611..6ca53f8897225 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll @@ -5,7 +5,7 @@ entry: ret void } -; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility = SHADER_VISIBILITY_HULL), DescriptorTable(UAV(u2, numDescriptors=4)) +; DescriptorTable(UAV(u0, numDescriptors=unbounded)), DescriptorTable(UAV(u2, numDescriptors=4)) !dx.rootsignatures = !{!0} !0 = !{ptr @CSMain, !1, i32 2} !1 = !{!2, !4} From cc94561c9a98e64fe37c916073037546f718add2 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Wed, 13 Aug 2025 11:36:46 -0700 Subject: [PATCH 084/143] addressing comments --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 3918dfd13e5e3..095665683ed58 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -37,6 +37,7 @@ static ResourceClass toResourceClass(dxbc::DescriptorRangeType RangeType) { case DescriptorRangeType::Sampler: return ResourceClass::Sampler; } + llvm_unreachable("Unknown DescriptorRangeType"); } static ResourceClass toResourceClass(dxbc::RootParameterType Type) { From 98f48d252fe210bdf1cdc52538ea4511b510d7e2 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:24:35 -0700 Subject: [PATCH 085/143] address comments --- llvm/lib/Support/DXILABI.cpp | 3 +-- .../DirectX/rootsignature-validation-constants.ll | 14 -------------- .../rootsignature-validation-fail-sampler.ll | 2 +- .../CodeGen/DirectX/rootsignature-validation.ll | 3 ++- 4 files changed, 4 insertions(+), 18 deletions(-) delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp index 8d60e1a1b3ba8..c6499b21613fb 100644 --- a/llvm/lib/Support/DXILABI.cpp +++ b/llvm/lib/Support/DXILABI.cpp @@ -1,5 +1,4 @@ -//===-- DXILABI.cpp - ABI Sensitive Values for DXIL ---------------*- C++ -//-*-===// +//===-- DXILABI.cpp - ABI Sensitive Values for DXIL --------------*- C++-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll deleted file mode 100644 index ab8c51629fa53..0000000000000 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-constants.ll +++ /dev/null @@ -1,14 +0,0 @@ -; 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)) - -define void @CSMain() "hlsl.shader"="compute" { -entry: - 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-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll index a29c00fe0f2f4..90f4c6f683e8b 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll @@ -11,4 +11,4 @@ entry: !1 = !{!2, !3} !2 = !{ !"StaticSampler", i32 5, i32 4, i32 5, i32 3, float 0x3FF7CCCCC0000000, i32 10, i32 2, i32 1, float -1.270000e+02, float 1.220000e+02, i32 42, i32 0, i32 0 } !3 = !{!"DescriptorTable", i32 0, !4} -!4 = !{!"Sampler", i32 1, i32 42, i32 0, i32 -1, i32 0} \ No newline at end of file +!4 = !{!"Sampler", i32 1, i32 42, i32 0, i32 -1, i32 0} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll index 67a57d05e65ee..42545886b6312 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -17,8 +17,9 @@ entry: !dx.rootsignatures = !{!0} !0 = !{ptr @CSMain, !1, i32 2} -!1 = !{!2, !3, !5, !7} +!1 = !{!2, !3, !5, !7, !9} !2 = !{!"RootCBV", i32 0, i32 3, i32 1, i32 4} +!9 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4} !3 = !{!"DescriptorTable", i32 0, !4} !4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 0} !5 = !{!"DescriptorTable", i32 0, !6} From eb334b89ccc63e74244df707c9381924df79e914 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Wed, 13 Aug 2025 13:25:53 -0700 Subject: [PATCH 086/143] refactoring --- llvm/include/llvm/BinaryFormat/DXContainer.h | 2 -- llvm/include/llvm/Support/DXILABI.h | 5 ++++- llvm/lib/BinaryFormat/DXContainer.cpp | 11 ----------- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 2 +- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 4 ++-- llvm/lib/Support/DXILABI.cpp | 13 ++++++++++++- 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index cc4af3d9be8d7..f74c9775cb3f3 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -158,8 +158,6 @@ enum class FeatureFlags : uint64_t { static_assert((uint64_t)FeatureFlags::NextUnusedBit <= 1ull << 63, "Shader flag bits exceed enum size."); -LLVM_ABI ArrayRef> getResourceClasses(); - #define ROOT_SIGNATURE_FLAG(Num, Val) Val = Num, enum class RootFlags : uint32_t { #include "DXContainerConstants.def" diff --git a/llvm/include/llvm/Support/DXILABI.h b/llvm/include/llvm/Support/DXILABI.h index 397906a3466c5..dcd611eb3b7db 100644 --- a/llvm/include/llvm/Support/DXILABI.h +++ b/llvm/include/llvm/Support/DXILABI.h @@ -18,6 +18,7 @@ #define LLVM_SUPPORT_DXILABI_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ScopedPrinter.h" #include namespace llvm { @@ -100,7 +101,9 @@ enum class SamplerFeedbackType : uint32_t { const unsigned MinWaveSize = 4; const unsigned MaxWaveSize = 128; -StringRef getResourceClassName(ResourceClass RC); +LLVM_ABI ArrayRef> getResourceClasses(); + +LLVM_ABI StringRef getResourceClassName(ResourceClass RC); } // namespace dxil } // namespace llvm diff --git a/llvm/lib/BinaryFormat/DXContainer.cpp b/llvm/lib/BinaryFormat/DXContainer.cpp index eb83945c9c42f..36d10d0b63078 100644 --- a/llvm/lib/BinaryFormat/DXContainer.cpp +++ b/llvm/lib/BinaryFormat/DXContainer.cpp @@ -60,17 +60,6 @@ ArrayRef> dxbc::getSigComponentTypes() { return ArrayRef(SigComponentTypes); } -static const EnumEntry ResourceClassNames[] = { - {"SRV", llvm::dxil::ResourceClass::SRV}, - {"UAV", llvm::dxil::ResourceClass::UAV}, - {"CBV", llvm::dxil::ResourceClass::CBuffer}, - {"Sampler", llvm::dxil::ResourceClass::Sampler}, -}; - -ArrayRef> dxbc::getResourceClasses() { - return ArrayRef(ResourceClassNames); -} - static const EnumEntry RootFlagNames[] = { #define ROOT_SIGNATURE_FLAG(Val, Enum) {#Enum, RootFlags::Enum}, #include "llvm/BinaryFormat/DXContainerConstants.def" diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index 574883e0d7fd7..050cc46e8c9b0 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -94,7 +94,7 @@ static raw_ostream &operator<<(raw_ostream &OS, static raw_ostream &operator<<(raw_ostream &OS, const ClauseType &Type) { OS << enumToStringRef(dxil::ResourceClass(llvm::to_underlying(Type)), - dxbc::getResourceClasses()); + dxil::getResourceClasses()); return OS; } diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 1cda3080442b2..157bfc665b207 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -121,7 +121,7 @@ MDNode *MetadataBuilder::BuildRootDescriptor(const RootDescriptor &Descriptor) { IRBuilder<> Builder(Ctx); StringRef ResName = enumToStringRef(dxil::ResourceClass(to_underlying(Descriptor.Type)), - dxbc::getResourceClasses()); + dxil::getResourceClasses()); assert(!ResName.empty() && "Provided an invalid Resource Class"); SmallString<7> Name({"Root", ResName}); Metadata *Operands[] = { @@ -163,7 +163,7 @@ MDNode *MetadataBuilder::BuildDescriptorTableClause( IRBuilder<> Builder(Ctx); StringRef ResName = enumToStringRef(dxil::ResourceClass(to_underlying(Clause.Type)), - dxbc::getResourceClasses()); + dxil::getResourceClasses()); assert(!ResName.empty() && "Provided an invalid Resource Class"); Metadata *Operands[] = { MDString::get(Ctx, ResName), diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp index c6499b21613fb..892c910dbe97b 100644 --- a/llvm/lib/Support/DXILABI.cpp +++ b/llvm/lib/Support/DXILABI.cpp @@ -15,6 +15,17 @@ #include "llvm/Support/ScopedPrinter.h" using namespace llvm; +static const EnumEntry ResourceClassNames[] = { + {"SRV", llvm::dxil::ResourceClass::SRV}, + {"UAV", llvm::dxil::ResourceClass::UAV}, + {"CBV", llvm::dxil::ResourceClass::CBuffer}, + {"Sampler", llvm::dxil::ResourceClass::Sampler}, +}; + +ArrayRef> dxil::getResourceClasses() { + return ArrayRef(ResourceClassNames); +} + StringRef dxil::getResourceClassName(dxil::ResourceClass RC) { - return enumToStringRef(RC, dxbc::getResourceClasses()); + return enumToStringRef(RC, getResourceClasses()); } From 06c0da45f95ae06499f2f1a5347737ba0dc9e14e Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 11:00:53 -0700 Subject: [PATCH 087/143] addressing comments --- llvm/lib/Support/DXILABI.cpp | 9 ++++++--- .../DirectX/DXILPostOptimizationValidation.cpp | 12 +++++------- .../test/CodeGen/DirectX/rootsignature-validation.ll | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp index 892c910dbe97b..ae2f41b3944ce 100644 --- a/llvm/lib/Support/DXILABI.cpp +++ b/llvm/lib/Support/DXILABI.cpp @@ -1,4 +1,4 @@ -//===-- DXILABI.cpp - ABI Sensitive Values for DXIL --------------*- C++-*-===// +//===-- DXILABI.cpp - ABI Sensitive Values for DXIL -----------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,8 +6,11 @@ // //===----------------------------------------------------------------------===// // -// This file implements functions that can be reused accross different stages -// dxil generation. +// This file contains definitions of various constants and enums that are +// required to remain stable as per the DXIL format's requirements. +// +// Documentation for DXIL can be found in +// https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst. // //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 095665683ed58..0e9e2253e2ec9 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -53,7 +53,6 @@ static ResourceClass toResourceClass(dxbc::RootParameterType Type) { return ResourceClass::CBuffer; case dxbc::RootParameterType::DescriptorTable: llvm_unreachable("DescriptorTable is not convertible to ResourceClass"); - break; } llvm_unreachable("Unknown RootParameterType"); } @@ -160,7 +159,7 @@ static void validateRootSignature(Module &M, hlsl::BindingInfoBuilder Builder; dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); - SmallVector IDs; + for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) { dxbc::ShaderVisibility ParamVisibility = static_cast(ParamInfo.Header.ShaderVisibility); @@ -175,7 +174,7 @@ static void validateRootSignature(Module &M, RSD.ParametersContainer.getConstant(ParamInfo.Location); Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace, Const.ShaderRegister, Const.ShaderRegister, - &IDs.emplace_back()); + &ParamInfo); break; } @@ -187,7 +186,7 @@ static void validateRootSignature(Module &M, Builder.trackBinding(toResourceClass(static_cast( ParamInfo.Header.ParameterType)), Desc.RegisterSpace, Desc.ShaderRegister, - Desc.ShaderRegister, &IDs.emplace_back()); + Desc.ShaderRegister, &ParamInfo); break; } @@ -204,7 +203,7 @@ static void validateRootSignature(Module &M, toResourceClass( static_cast(Range.RangeType)), Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, - &IDs.emplace_back()); + &ParamInfo); } break; } @@ -213,8 +212,7 @@ static void validateRootSignature(Module &M, for (const dxbc::RTS0::v1::StaticSampler &S : RSD.StaticSamplers) Builder.trackBinding(dxil::ResourceClass::Sampler, S.RegisterSpace, - S.ShaderRegister, S.ShaderRegister, - &IDs.emplace_back()); + S.ShaderRegister, S.ShaderRegister, &S); Builder.calculateBindingInfo( [&M](const llvm::hlsl::BindingInfoBuilder &Builder, diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll index 42545886b6312..1b88a56e8aa35 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 +; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s ; expected-no-diagnostics From 74980c89759ebf9076ee3baec1d3e2530b9e5843 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 11:30:27 -0700 Subject: [PATCH 088/143] fix test --- llvm/test/Analysis/DXILResource/buffer-frombinding.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll index 2623e6f4d44f1..d08b68d3768af 100644 --- a/llvm/test/Analysis/DXILResource/buffer-frombinding.ll +++ b/llvm/test/Analysis/DXILResource/buffer-frombinding.ll @@ -146,7 +146,7 @@ define void @test_typedbuffer() { ; CHECK: Space: 1 ; CHECK: Lower Bound: 0 ; CHECK: Size: 1 - ; CHECK: Class: CBuffer + ; CHECK: Class: CBV ; CHECK: Kind: CBuffer ; CHECK: CBuffer size: 4 @@ -159,7 +159,7 @@ define void @test_typedbuffer() { ; CHECK: Space: 1 ; CHECK: Lower Bound: 8 ; CHECK: Size: 1 - ; CHECK: Class: CBuffer + ; CHECK: Class: CBV ; CHECK: Kind: CBuffer ; CHECK: CBuffer size: 4 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 089/143] 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} - From d376abf1843d07fdd4c7f91c8b5462ad55ca34aa Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 14:38:50 -0700 Subject: [PATCH 090/143] address comments --- llvm/include/llvm/Support/DXILABI.h | 2 +- llvm/lib/Support/DXILABI.cpp | 2 +- .../rootsignature-validation-fail-cbuffer-range.ll | 2 +- ...signature-validation-fail-descriptor-table-range.ll | 3 ++- ...tsignature-validation-fail-root-descriptor-range.ll | 1 + .../DirectX/rootsignature-validation-fail-sampler.ll | 1 + ...otsignature-validation-fail-static-sampler-range.ll | 1 + llvm/test/CodeGen/DirectX/rootsignature-validation.ll | 10 +--------- 8 files changed, 9 insertions(+), 13 deletions(-) diff --git a/llvm/include/llvm/Support/DXILABI.h b/llvm/include/llvm/Support/DXILABI.h index dcd611eb3b7db..2dcdd73415be2 100644 --- a/llvm/include/llvm/Support/DXILABI.h +++ b/llvm/include/llvm/Support/DXILABI.h @@ -101,7 +101,7 @@ enum class SamplerFeedbackType : uint32_t { const unsigned MinWaveSize = 4; const unsigned MaxWaveSize = 128; -LLVM_ABI ArrayRef> getResourceClasses(); +LLVM_ABI ArrayRef> getResourceClasses(); LLVM_ABI StringRef getResourceClassName(ResourceClass RC); diff --git a/llvm/lib/Support/DXILABI.cpp b/llvm/lib/Support/DXILABI.cpp index ae2f41b3944ce..261fe1ef98278 100644 --- a/llvm/lib/Support/DXILABI.cpp +++ b/llvm/lib/Support/DXILABI.cpp @@ -14,7 +14,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/BinaryFormat/DXContainer.h" +#include "llvm/Support/DXILABI.h" #include "llvm/Support/ScopedPrinter.h" using namespace llvm; 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 3d3f57d136845..e420225229919 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer-range.ll @@ -6,8 +6,8 @@ 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 = !{!"RootConstants", i32 0, i32 2, i32 0, i32 4} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll index 6ca53f8897225..037f8c71f8ef0 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-descriptor-table-range.ll @@ -1,12 +1,13 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s ; CHECK: error: resource UAV (space=10, registers=[4294967295, 4294967295]) overlaps with resource UAV (space=10, registers=[4294967295, 4294967295]) + define void @CSMain() "hlsl.shader"="compute" { entry: ret void } -; DescriptorTable(UAV(u0, numDescriptors=unbounded)), DescriptorTable(UAV(u2, numDescriptors=4)) !dx.rootsignatures = !{!0} + !0 = !{ptr @CSMain, !1, i32 2} !1 = !{!2, !4} !2 = !{!"DescriptorTable", i32 0, !3} 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 index 4e6a3e7e49608..7098efbb43f6a 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-root-descriptor-range.ll @@ -7,6 +7,7 @@ entry: } !dx.rootsignatures = !{!0} + !0 = !{ptr @CSMain, !1, i32 2} !1 = !{!2, !4} !2 = !{!"RootUAV", i32 0, i32 3, i32 1, i32 4} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll index 90f4c6f683e8b..c244095520468 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll @@ -7,6 +7,7 @@ entry: } !dx.rootsignatures = !{!0} + !0 = !{ptr @CSMain, !1, i32 2} !1 = !{!2, !3} !2 = !{ !"StaticSampler", i32 5, i32 4, i32 5, i32 3, float 0x3FF7CCCCC0000000, i32 10, i32 2, i32 1, float -1.270000e+02, float 1.220000e+02, i32 42, i32 0, i32 0 } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll index 66649f7ffc653..9ac02ebbc0965 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-static-sampler-range.ll @@ -7,6 +7,7 @@ entry: } !dx.rootsignatures = !{!0} + !0 = !{ptr @CSMain, !1, i32 2} !1 = !{!2, !3} !2 = !{ !"StaticSampler", i32 5, i32 4, i32 5, i32 3, float 0x3FF7CCCCC0000000, i32 10, i32 2, i32 1, float -1.270000e+02, float 1.220000e+02, i32 42, i32 0, i32 0 } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll index 1b88a56e8aa35..0fdba27018cd4 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -1,13 +1,5 @@ ; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s -; expected-no-diagnostics - - -; 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) - +; We have a valid root signature, this should compile successfully define void @CSMain() "hlsl.shader"="compute" { entry: From bb44eef7ebf6908997bf507e0a84666bea6af234 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 16:09:55 -0700 Subject: [PATCH 091/143] fix test --- .../rootsignature-validation-fail-cbuffer.ll | 34 ------------------- ...rootsignature-validation-fail-constants.ll | 6 +--- 2 files changed, 1 insertion(+), 39 deletions(-) delete mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll deleted file mode 100644 index e5133810c0f32..0000000000000 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbuffer.ll +++ /dev/null @@ -1,34 +0,0 @@ -; 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=665, register=3) does not have a binding in the Root Signature - -; Root Signature( -; CBV(b3, space=666, 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) - -%__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(b3, space665) { -; float a; -; } - %CB = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_CB, 4, 0)) @llvm.dx.resource.handlefrombinding(i32 665, i32 3, i32 1, i32 0, i1 false, ptr nonnull @CB.str) - ret void -} - -!dx.rootsignatures = !{!0} - -!0 = !{ptr @CSMain, !1, i32 2} -!1 = !{!2, !3, !5, !7} -!2 = !{!"RootCBV", i32 0, i32 3, i32 666, i32 4} -!3 = !{!"DescriptorTable", i32 1, !4} -!4 = !{!"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4} -!5 = !{!"DescriptorTable", i32 0, !6} -!6 = !{!"Sampler", i32 2, i32 0, i32 0, 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-fail-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll index dc7657e79ec97..07dbeb9be81d0 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll @@ -1,6 +1,5 @@ ; 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=666, register=2) does not have a binding in the Root Signature -; Root Signature(RootConstants(num32BitConstants=4, b2)) +; CHECK: error: register CBV (space=666, register=2) does not have a binding in the Root Signature %__cblayout_CB = type <{ float }> @@ -8,9 +7,6 @@ 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 } From 373d871f6a2faab8b724e816b899ece63845464f Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 16:48:57 -0700 Subject: [PATCH 092/143] clean up --- .../DirectX/DXILPostOptimizationValidation.cpp | 1 - ...otsignature-validation-fail-cbv-binding.ll} | 0 ...ignature-validation-fail-sampler-binding.ll | 18 ++++++++++++++++++ .../rootsignature-validation-fail-sampler.ll | 3 --- ...otsignature-validation-fail-srv-binding.ll} | 7 ------- ...otsignature-validation-fail-uav-binding.ll} | 7 ------- 6 files changed, 18 insertions(+), 18 deletions(-) rename llvm/test/CodeGen/DirectX/{rootsignature-validation-fail-constants.ll => rootsignature-validation-fail-cbv-binding.ll} (100%) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-binding.ll rename llvm/test/CodeGen/DirectX/{rootsignature-validation-fail-srv.ll => rootsignature-validation-fail-srv-binding.ll} (74%) rename llvm/test/CodeGen/DirectX/{rootsignature-validation-fail-uav.ll => rootsignature-validation-fail-uav-binding.ll} (74%) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 95918cb035304..bbdf7098222b2 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -13,7 +13,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" -#include "llvm/Frontend/HLSL/HLSLBinding.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicsDirectX.h" diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbv-binding.ll similarity index 100% rename from llvm/test/CodeGen/DirectX/rootsignature-validation-fail-constants.ll rename to llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbv-binding.ll diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-binding.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-binding.ll new file mode 100644 index 0000000000000..4dc21448e2796 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-binding.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: register Sampler (space=2, register=3) does not have a binding in the Root Signature + +@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 + + +define void @CSMain() "hlsl.shader"="compute" { +entry: + %Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str) + ret void +} + +!dx.rootsignatures = !{!0} + +!0 = !{ptr @CSMain, !1, i32 2} +!1 = !{!2} +!2 = !{!"DescriptorTable", i32 0, !3} +!3 = !{!"Sampler", i32 1, i32 42, i32 0, i32 -1, i32 0} diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll index a218c55fb5745..968ab1d699574 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll @@ -1,12 +1,9 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s ; CHECK: error: resource Sampler (space=0, registers=[42, 42]) overlaps with resource Sampler (space=0, registers=[42, 42]) -@Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 - define void @CSMain() "hlsl.shader"="compute" { entry: - %Sampler = call target("dx.Sampler", 0) @llvm.dx.resource.handlefrombinding(i32 2, i32 3, i32 1, i32 0, i1 false, ptr nonnull @Smp.str) ret void } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv-binding.ll similarity index 74% rename from llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll rename to llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv-binding.ll index ebefa7b1a3d85..c851550556024 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv-binding.ll @@ -1,13 +1,6 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s - ; CHECK: error: register SRV (space=0, register=0) does not have a binding in the Root Signature -; Root Signature( -; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) -; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) - @SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1 define void @CSMain() "hlsl.shader"="compute" { diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav-binding.ll similarity index 74% rename from llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll rename to llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav-binding.ll index 9cc5b6744a4a2..523999348ae10 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav-binding.ll @@ -1,13 +1,6 @@ ; 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=4294967294) does not have a binding in the Root Signature -; Root Signature( -; CBV(b3, space=666, visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(SRV(t0, space=0, numDescriptors=1), visibility=SHADER_VISIBILITY_VERTEX) -; DescriptorTable(Sampler(s0, numDescriptors=2), visibility=SHADER_VISIBILITY_ALL) -; DescriptorTable(UAV(u0, numDescriptors=unbounded), visibility=SHADER_VISIBILITY_ALL) - @RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1 define void @CSMain() "hlsl.shader"="compute" { From d2750d7b2771ec100893dd27df46d636c503fe98 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 16:50:16 -0700 Subject: [PATCH 093/143] format --- .../CodeGen/DirectX/rootsignature-validation-fail-sampler.ll | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll index 968ab1d699574..c244095520468 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll @@ -1,7 +1,6 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s ; CHECK: error: resource Sampler (space=0, registers=[42, 42]) overlaps with resource Sampler (space=0, registers=[42, 42]) - define void @CSMain() "hlsl.shader"="compute" { entry: ret void From 19e9baace0662dfa9fbbecda47391217cde5e572 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 16:58:03 -0700 Subject: [PATCH 094/143] fix merge oopsi --- llvm/test/CodeGen/DirectX/rootsignature-validation.ll | 9 --------- 1 file changed, 9 deletions(-) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll index 79d7ddd46088e..0fdba27018cd4 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation.ll @@ -3,15 +3,6 @@ define void @CSMain() "hlsl.shader"="compute" { entry: -<<<<<<< HEAD - - %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.TypedBuffer", 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) - -======= ->>>>>>> validation/check-descriptors-are-bound ret void } From 708c4dc8a2941fd2dfa693f59b6833da8e50683d Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 16:58:50 -0700 Subject: [PATCH 095/143] format --- .../CodeGen/DirectX/rootsignature-validation-fail-sampler.ll | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll index c244095520468..968ab1d699574 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll @@ -1,6 +1,7 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s ; CHECK: error: resource Sampler (space=0, registers=[42, 42]) overlaps with resource Sampler (space=0, registers=[42, 42]) + define void @CSMain() "hlsl.shader"="compute" { entry: ret void From a163d1b5ad7e4a4c892e6fb1794ecb5b587a7008 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 17:01:46 -0700 Subject: [PATCH 096/143] clean up --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 4aa5245c9622f..2f2db23cb2be5 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -13,13 +13,11 @@ #include "llvm/ADT/SmallString.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" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" -#include "llvm/MC/DXContainerRootSignature.h" #include "llvm/Support/DXILABI.h" #define DEBUG_TYPE "dxil-post-optimization-validation" @@ -327,8 +325,9 @@ static void validateRootSignature(Module &M, } } -mcdxbc::RootSignatureDesc *getRootSignature(RootSignatureBindingInfo &RSBI, - dxil::ModuleMetadataInfo &MMI) { +static mcdxbc::RootSignatureDesc * +getRootSignature(RootSignatureBindingInfo &RSBI, + dxil::ModuleMetadataInfo &MMI) { if (MMI.EntryPropertyVec.size() == 0) return nullptr; return RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry); From 4f120ccf16a7f18d40988b175e28b8bc4924b34f Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 17:05:07 -0700 Subject: [PATCH 097/143] clean up tests --- .../DirectX/rootsignature-validation-textures-fail.ll | 6 ------ .../CodeGen/DirectX/rootsignature-validation-textures.ll | 8 ++------ .../DirectX/rootsignature-validation-typedbuffer-fail.ll | 9 --------- .../DirectX/rootsignature-validation-typedbuffer.ll | 6 +----- 4 files changed, 3 insertions(+), 26 deletions(-) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll index a534b6c956e84..d7b0a656e4d83 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll @@ -1,17 +1,11 @@ ; 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( -; UAV(b0, space=0, 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.Texture", 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 } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll index f20ccd04c49c6..70abfb3a7120a 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll @@ -1,15 +1,11 @@ -; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 -; expected-no-diagnostics -; Root Signature( -; DescriptorTable(UAV(b0, space=0, visibility=SHADER_VISIBILITY_ALL)) +; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s +; "This is a valid root signature with a texture/typed buffer resource" @TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 define void @CSMain() "hlsl.shader"="compute" { entry: - %TB = tail call target("dx.Texture", float, 1, 0, 0) @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 } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll index 46ee29258dbdc..ee0a49b566618 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll @@ -1,20 +1,11 @@ ; 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 } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll index a880cbdc8f442..a4cbc94df169c 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll @@ -1,15 +1,11 @@ ; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 -; expected-no-diagnostics -; Root Signature( -; DescriptorTable(UAV(b0, space=0, visibility=SHADER_VISIBILITY_ALL)) +; This is a valid root signature with a texture/typed buffer resource @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 } From d3349cec0490c0b8d26d5ff21f32b2b292bf2f28 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 17:46:40 -0700 Subject: [PATCH 098/143] clean up --- llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h | 6 +++--- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index c817782f21e58..a112fe6ade7c6 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -15,7 +15,6 @@ #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" @@ -42,6 +41,7 @@ toResourceClass(dxbc::DescriptorRangeType RangeType) { case DescriptorRangeType::Sampler: return dxil::ResourceClass::Sampler; } + llvm_unreachable("Unknown DescriptorRangeType"); } inline dxil::ResourceClass toResourceClass(dxbc::RootParameterType Type) { @@ -56,9 +56,9 @@ inline dxil::ResourceClass toResourceClass(dxbc::RootParameterType Type) { case RootParameterType::CBV: return dxil::ResourceClass::CBuffer; case dxbc::RootParameterType::DescriptorTable: - break; + llvm_unreachable("DescriptorTable is not convertible to ResourceClass"); } - llvm_unreachable("Unconvertible RootParameterType"); + llvm_unreachable("Unknown RootParameterType"); } template diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 47957f08fc008..c2d32ad25fca0 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -15,9 +15,7 @@ #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 using namespace llvm; From bf5714d7abf8d3dfe4d1e8d108b95ac113dcf092 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 17:49:37 -0700 Subject: [PATCH 099/143] moving code to where I think make sense --- llvm/include/llvm/BinaryFormat/DXContainer.h | 33 +++++++++++++++++++ .../Frontend/HLSL/RootSignatureMetadata.h | 33 ------------------- .../DXILPostOptimizationValidation.cpp | 12 +++---- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index f74c9775cb3f3..355a86420d29d 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -214,6 +214,39 @@ enum class ShaderVisibility : uint32_t { #include "DXContainerConstants.def" }; +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; + } + llvm_unreachable("Unknown DescriptorRangeType"); +} + +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: + llvm_unreachable("DescriptorTable is not convertible to ResourceClass"); + } + llvm_unreachable("Unknown RootParameterType"); +} + LLVM_ABI ArrayRef> getShaderVisibility(); #define SHADER_VISIBILITY(Val, Enum) \ diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index a112fe6ade7c6..096cd9dded9eb 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -28,39 +28,6 @@ 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; - } - llvm_unreachable("Unknown DescriptorRangeType"); -} - -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: - llvm_unreachable("DescriptorTable is not convertible to ResourceClass"); - } - llvm_unreachable("Unknown RootParameterType"); -} - template class RootSignatureValidationError : public ErrorInfo> { diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index b78cc63388179..1d2c9a35c1184 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -13,7 +13,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/DXILMetadataAnalysis.h" #include "llvm/Analysis/DXILResource.h" -#include "llvm/Frontend/HLSL/RootSignatureMetadata.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicsDirectX.h" @@ -237,10 +236,11 @@ static void validateRootSignatureBindings(Module &M, case dxbc::RootParameterType::CBV: { dxbc::RTS0::v2::RootDescriptor Desc = RSD.ParametersContainer.getRootDescriptor(ParamInfo.Location); - Builder.trackBinding(hlsl::rootsig::toResourceClass(static_cast( - ParamInfo.Header.ParameterType)), - Desc.RegisterSpace, Desc.ShaderRegister, - Desc.ShaderRegister, &ParamInfo); + Builder.trackBinding( + dxbc::toResourceClass(static_cast( + ParamInfo.Header.ParameterType)), + Desc.RegisterSpace, Desc.ShaderRegister, Desc.ShaderRegister, + &ParamInfo); break; } @@ -254,7 +254,7 @@ static void validateRootSignatureBindings(Module &M, ? Range.BaseShaderRegister : Range.BaseShaderRegister + Range.NumDescriptors - 1; Builder.trackBinding( - hlsl::rootsig::toResourceClass( + dxbc::toResourceClass( static_cast(Range.RangeType)), Range.RegisterSpace, Range.BaseShaderRegister, UpperBound, &ParamInfo); From 7cf513f02a86b6b8e6f5728b0bb6aee9b057d914 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 17:59:28 -0700 Subject: [PATCH 100/143] format --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 2f2db23cb2be5..ceed846b73114 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -118,9 +118,8 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { "true, yet no overlapping binding was found"); } -static void -reportInvalidHandleTyError(Module &M, Twine Type, - ResourceInfo::ResourceBinding Binding) { +static void reportInvalidHandleTyError(Module &M, Twine Type, + ResourceInfo::ResourceBinding Binding) { SmallString<128> Message; raw_svector_ostream OS(Message); OS << "resource " << Type << " at register (space=" << Binding.Space @@ -129,7 +128,7 @@ reportInvalidHandleTyError(Module &M, Twine Type, M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } -static void +static void reportOverlappingRegisters(Module &M, const llvm::hlsl::BindingInfoBuilder::Binding &R1, const llvm::hlsl::BindingInfoBuilder::Binding &R2) { From fe246374aa916a33b1b5d6f60099c0c0f99453e8 Mon Sep 17 00:00:00 2001 From: Joao Saffran <{ID}+{username}@users.noreply.github.com> Date: Thu, 14 Aug 2025 18:21:13 -0700 Subject: [PATCH 101/143] format --- .../DXILPostOptimizationValidation.cpp | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index ceed846b73114..4b865246a357a 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -305,22 +305,22 @@ static void validateRootSignature(Module &M, Builder.findOverlapping(ReportedBinding); reportOverlappingRegisters(M, ReportedBinding, Overlaping); }); - SmallVector RDs = - getRootDescriptorsBindingInfo(RSD, Visibility); - for (const auto &ResList : - {std::make_pair(ResourceClass::SRV, DRM.srvs()), - std::make_pair(ResourceClass::UAV, DRM.uavs()), - std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), - std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { - for (auto Res : ResList.second) { - llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); - llvm::hlsl::BindingInfo::BindingRange ResRange( - ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); - - if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) - reportRegNotBound(M, ResList.first, ResBinding); - } - checkInvalidHandleTy(M, RDs, ResList.second); + SmallVector RDs = + getRootDescriptorsBindingInfo(RSD, Visibility); + for (const auto &ResList : + {std::make_pair(ResourceClass::SRV, DRM.srvs()), + std::make_pair(ResourceClass::UAV, DRM.uavs()), + std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), + std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { + for (auto Res : ResList.second) { + llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); + llvm::hlsl::BindingInfo::BindingRange ResRange( + ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); + + if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) + reportRegNotBound(M, ResList.first, ResBinding); + } + checkInvalidHandleTy(M, RDs, ResList.second); } } From 6db8d93a9ee9460fc094eb4476c67a67b7b94a8b Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 21 Aug 2025 12:49:33 -0700 Subject: [PATCH 102/143] refactoring to not create extra space --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 2 ++ llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index eb94fb989e4f0..276507f3a45bf 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -66,6 +66,8 @@ class BindingInfo { llvm::SmallVector Spaces; BindingSpaces(dxil::ResourceClass RC) : RC(RC) {} LLVM_ABI RegisterSpace &getOrInsertSpace(uint32_t Space); + LLVM_ABI std::optional + contains(uint32_t Space); }; private: diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index 483c3eb56f6be..62a6146c34795 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -8,6 +8,8 @@ #include "llvm/Frontend/HLSL/HLSLBinding.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Error.h" +#include using namespace llvm; using namespace hlsl; @@ -32,6 +34,15 @@ BindingInfo::BindingSpaces::getOrInsertSpace(uint32_t Space) { return Spaces.emplace_back(Space); } +std::optional +BindingInfo::BindingSpaces::contains(uint32_t Space) { + BindingInfo::RegisterSpace *It = + std::find(Spaces.begin(), Spaces.end(), Space); + if (It == Spaces.end()) + return std::nullopt; + return It; +} + std::optional BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) { assert((Size == -1 || Size > 0) && "invalid size"); @@ -82,8 +93,10 @@ bool BindingInfo::RegisterSpace::isBound(BindingRange B) { bool BindingInfo::isBound(dxil::ResourceClass RC, uint32_t Space, BindingRange B) { BindingSpaces &BS = getBindingSpaces(RC); - RegisterSpace &RS = BS.getOrInsertSpace(Space); - return RS.isBound(B); + std::optional RS = BS.contains(Space); + if (!RS) + return false; + return RS.value()->isBound(B); } BindingInfo BindingInfoBuilder::calculateBindingInfo( From e3a65b6621caa4dabcce080070bd6ec6dc244a28 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 21 Aug 2025 12:50:30 -0700 Subject: [PATCH 103/143] remove copy of binding --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index bbdf7098222b2..b15f1bedafbe5 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -135,7 +135,7 @@ reportOverlappingRegisters(Module &M, static void reportRegNotBound(Module &M, ResourceClass Class, - llvm::dxil::ResourceInfo::ResourceBinding Unbound) { + const llvm::dxil::ResourceInfo::ResourceBinding &Unbound) { SmallString<128> Message; raw_svector_ostream OS(Message); OS << "register " << getResourceClassName(Class) From e902add6461c1f0f51534e329f99332d264c4a88 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 21 Aug 2025 12:52:30 -0700 Subject: [PATCH 104/143] making BindingRange const --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 2 +- llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index 276507f3a45bf..1971b9ff72294 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -58,7 +58,7 @@ class BindingInfo { } // Size == -1 means unbounded array LLVM_ABI std::optional findAvailableBinding(int32_t Size); - LLVM_ABI bool isBound(BindingRange B); + LLVM_ABI bool isBound(const BindingRange &Range) const; }; struct BindingSpaces { diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index 62a6146c34795..2a6ddbc31063a 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -77,14 +77,15 @@ BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) { return std::nullopt; } -bool BindingInfo::RegisterSpace::isBound(BindingRange B) { - BindingRange *It = llvm::lower_bound( - FreeRanges, B.LowerBound, +bool BindingInfo::RegisterSpace::isBound(const BindingRange &Range) const { + const BindingRange *It = llvm::lower_bound( + FreeRanges, Range.LowerBound, [](const BindingRange &R, uint32_t Val) { return R.UpperBound <= Val; }); if (It != FreeRanges.end()) { // Check if B is fully contained in the found range - if (B.LowerBound >= It->LowerBound && B.UpperBound <= It->UpperBound) + if (Range.LowerBound >= It->LowerBound && + Range.UpperBound <= It->UpperBound) return false; } return true; From 9a6d64c55bc7d8a781fcc181967f6907212a8726 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 21 Aug 2025 12:54:51 -0700 Subject: [PATCH 105/143] doing it again for other isBound --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 7 ++++--- llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 14 +++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index 1971b9ff72294..959e40ea50da8 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -66,8 +66,8 @@ class BindingInfo { llvm::SmallVector Spaces; BindingSpaces(dxil::ResourceClass RC) : RC(RC) {} LLVM_ABI RegisterSpace &getOrInsertSpace(uint32_t Space); - LLVM_ABI std::optional - contains(uint32_t Space); + LLVM_ABI std::optional + contains(uint32_t Space) const; }; private: @@ -99,7 +99,8 @@ class BindingInfo { LLVM_ABI std::optional findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size); - LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space, BindingRange B); + LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space, + const BindingRange &Range) const; friend class BindingInfoBuilder; }; diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index 2a6ddbc31063a..9cb1ccea84ec3 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -34,9 +34,9 @@ BindingInfo::BindingSpaces::getOrInsertSpace(uint32_t Space) { return Spaces.emplace_back(Space); } -std::optional -BindingInfo::BindingSpaces::contains(uint32_t Space) { - BindingInfo::RegisterSpace *It = +std::optional +BindingInfo::BindingSpaces::contains(uint32_t Space) const { + const BindingInfo::RegisterSpace *It = std::find(Spaces.begin(), Spaces.end(), Space); if (It == Spaces.end()) return std::nullopt; @@ -92,12 +92,12 @@ bool BindingInfo::RegisterSpace::isBound(const BindingRange &Range) const { } bool BindingInfo::isBound(dxil::ResourceClass RC, uint32_t Space, - BindingRange B) { - BindingSpaces &BS = getBindingSpaces(RC); - std::optional RS = BS.contains(Space); + const BindingRange &Range) const { + const BindingSpaces &BS = getBindingSpaces(RC); + std::optional RS = BS.contains(Space); if (!RS) return false; - return RS.value()->isBound(B); + return RS.value()->isBound(Range); } BindingInfo BindingInfoBuilder::calculateBindingInfo( From 15b75920623dd7f3031654dbbd367e23dcd8168f Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 21 Aug 2025 13:06:22 -0700 Subject: [PATCH 106/143] adding DXILResourceTypeMap --- .../DXILPostOptimizationValidation.cpp | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index b15f1bedafbe5..e3ece353f1c38 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -170,7 +170,8 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) { static void validateRootSignature(Module &M, const mcdxbc::RootSignatureDesc &RSD, dxil::ModuleMetadataInfo &MMI, - DXILResourceMap &DRM) { + DXILResourceMap &DRM, + DXILResourceTypeMap &DRTM) { hlsl::BindingInfoBuilder Builder; dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile); @@ -236,19 +237,12 @@ static void validateRootSignature(Module &M, Builder.findOverlapping(ReportedBinding); reportOverlappingRegisters(M, ReportedBinding, Overlaping); }); - for (const auto &ResList : - {std::make_pair(ResourceClass::SRV, DRM.srvs()), - std::make_pair(ResourceClass::UAV, DRM.uavs()), - std::make_pair(ResourceClass::CBuffer, DRM.cbuffers()), - std::make_pair(ResourceClass::Sampler, DRM.samplers())}) { - for (auto Res : ResList.second) { - llvm::dxil::ResourceInfo::ResourceBinding ResBinding = Res.getBinding(); - llvm::hlsl::BindingInfo::BindingRange ResRange( - ResBinding.LowerBound, ResBinding.LowerBound + ResBinding.Size); - - if (!Info.isBound(ResList.first, ResBinding.Space, ResRange)) - reportRegNotBound(M, ResList.first, ResBinding); - } + for (const ResourceInfo &RI : DRM) { + const ResourceInfo::ResourceBinding &Binding = RI.getBinding(); + ResourceClass RC = DRTM[RI.getHandleTy()].getResourceClass(); + if (!Info.isBound(RC, Binding.Space, + {Binding.LowerBound, Binding.LowerBound + Binding.Size})) + reportRegNotBound(M, RC, Binding); } } @@ -263,7 +257,8 @@ getRootSignature(RootSignatureBindingInfo &RSBI, static void reportErrors(Module &M, DXILResourceMap &DRM, DXILResourceBindingInfo &DRBI, RootSignatureBindingInfo &RSBI, - dxil::ModuleMetadataInfo &MMI) { + dxil::ModuleMetadataInfo &MMI, + DXILResourceTypeMap &DRTM) { if (DRM.hasInvalidCounterDirection()) reportInvalidDirection(M, DRM); @@ -274,7 +269,7 @@ static void reportErrors(Module &M, DXILResourceMap &DRM, "DXILResourceImplicitBinding pass"); if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI)) - validateRootSignature(M, *RSD, MMI, DRM); + validateRootSignature(M, *RSD, MMI, DRM, DRTM); } PreservedAnalyses @@ -283,8 +278,9 @@ DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) { DXILResourceBindingInfo &DRBI = MAM.getResult(M); RootSignatureBindingInfo &RSBI = MAM.getResult(M); ModuleMetadataInfo &MMI = MAM.getResult(M); + DXILResourceTypeMap &DRTM = MAM.getResult(M); - reportErrors(M, DRM, DRBI, RSBI, MMI); + reportErrors(M, DRM, DRBI, RSBI, MMI, DRTM); return PreservedAnalyses::all(); } @@ -300,8 +296,10 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { getAnalysis().getRSInfo(); dxil::ModuleMetadataInfo &MMI = getAnalysis().getModuleMetadata(); + DXILResourceTypeMap &DRTM = + getAnalysis().getResourceTypeMap(); - reportErrors(M, DRM, DRBI, RSBI, MMI); + reportErrors(M, DRM, DRBI, RSBI, MMI, DRTM); return false; } StringRef getPassName() const override { @@ -311,15 +309,18 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { static char ID; // Pass identification. void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { + AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); + AU.addPreserved(); } }; char DXILPostOptimizationValidationLegacy::ID = 0; @@ -332,6 +333,7 @@ INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass) INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass) INITIALIZE_PASS_DEPENDENCY(RootSignatureAnalysisWrapper) +INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass) INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE, "DXIL Post Optimization Validation", false, false) From 11b9fb21bfaeb0342f30e0129e875678176ddb88 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 21 Aug 2025 13:37:13 -0700 Subject: [PATCH 107/143] updating error messages and tests --- llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 7 +++++-- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 5 ++--- .../DirectX/rootsignature-validation-fail-cbv-binding.ll | 2 +- .../rootsignature-validation-fail-sampler-binding.ll | 2 +- .../DirectX/rootsignature-validation-fail-srv-binding.ll | 2 +- .../DirectX/rootsignature-validation-fail-uav-binding.ll | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index 9cb1ccea84ec3..bb62ad8cffe89 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -36,8 +36,11 @@ BindingInfo::BindingSpaces::getOrInsertSpace(uint32_t Space) { std::optional BindingInfo::BindingSpaces::contains(uint32_t Space) const { - const BindingInfo::RegisterSpace *It = - std::find(Spaces.begin(), Spaces.end(), Space); + const BindingInfo::RegisterSpace *It = Spaces.begin(); + for (auto *End = Spaces.end(); It != End; ++It) { + if (It->Space == Space) + break; + } if (It == Spaces.end()) return std::nullopt; return It; diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index e3ece353f1c38..b001c716b717e 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -138,9 +138,8 @@ reportRegNotBound(Module &M, ResourceClass Class, const llvm::dxil::ResourceInfo::ResourceBinding &Unbound) { SmallString<128> Message; raw_svector_ostream OS(Message); - OS << "register " << getResourceClassName(Class) - << " (space=" << Unbound.Space << ", register=" << Unbound.LowerBound - << ")" + OS << getResourceClassName(Class) << " register " << Unbound.LowerBound + << " in space " << Unbound.Space << " does not have a binding in the Root Signature"; M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbv-binding.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbv-binding.ll index 07dbeb9be81d0..a469c16991dc3 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbv-binding.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-cbv-binding.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: register CBV (space=666, register=2) does not have a binding in the Root Signature +; CHECK: error: CBV register 2 in space 666 does not have a binding in the Root Signature %__cblayout_CB = type <{ float }> diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-binding.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-binding.ll index 4dc21448e2796..3e1d7f4497d39 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-binding.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-binding.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: register Sampler (space=2, register=3) does not have a binding in the Root Signature +; CHECK: error: Sampler register 3 in space 2 does not have a binding in the Root Signature @Smp.str = private unnamed_addr constant [4 x i8] c"Smp\00", align 1 diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv-binding.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv-binding.ll index c851550556024..e027d3c10c900 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv-binding.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-srv-binding.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: register SRV (space=0, register=0) does not have a binding in the Root Signature +; CHECK: error: SRV register 0 in space 0 does not have a binding in the Root Signature @SB.str = private unnamed_addr constant [3 x i8] c"SB\00", align 1 diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav-binding.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav-binding.ll index 523999348ae10..5e30b1f45c34d 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav-binding.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-uav-binding.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: register UAV (space=0, register=4294967294) does not have a binding in the Root Signature +; CHECK: error: UAV register 4294967294 in space 0 does not have a binding in the Root Signature @RWB.str = private unnamed_addr constant [4 x i8] c"RWB\00", align 1 From 34619da2ba69efa09d1a5d0efa7fb98ab6505953 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 22 Aug 2025 15:20:46 -0700 Subject: [PATCH 108/143] moving offset logic into shared validations --- .../Frontend/HLSL/RootSignatureValidations.h | 3 ++ .../Frontend/HLSL/RootSignatureMetadata.cpp | 42 ++----------------- .../HLSL/RootSignatureValidations.cpp | 42 +++++++++++++++++++ 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index fde32a1fff591..c6a2886e89118 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -40,6 +40,9 @@ LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc); LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); LLVM_ABI bool verifyLOD(float LOD); +LLVM_ABI bool verifyOffsetOverflowing( + uint64_t &AppendingRegister, uint32_t OffsetInDescriptorsFromTableStart, + uint32_t BaseRegister, uint32_t Space, uint32_t NumDescriptors); } // namespace rootsig } // namespace hlsl diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index c2d32ad25fca0..40b1f10e09ae9 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -539,53 +539,19 @@ Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, 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 appends a resource - * after an unbounded range. - **/ 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(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) + if (verifyOffsetOverflowing(AppendingRegister, + Range.OffsetInDescriptorsFromTableStart, + Range.BaseShaderRegister, Range.RegisterSpace, + Range.NumDescriptors)) return make_error( 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( - 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( - RangeType, Range.BaseShaderRegister, Range.RegisterSpace); - AppendingRegister = Register + Range.NumDescriptors; - } } return Error::success(); diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 72308a3de5fd4..52cada81a7c44 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -180,6 +180,48 @@ bool verifyBorderColor(uint32_t BorderColor) { bool verifyLOD(float LOD) { return !std::isnan(LOD); } +/** 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 appends a resource + * after an unbounded range. + **/ +bool verifyOffsetOverflowing(uint64_t &AppendingRegister, + uint32_t OffsetInDescriptorsFromTableStart, + uint32_t BaseRegister, uint32_t Space, + uint32_t NumDescriptors) { + uint64_t Register = AppendingRegister; + + // Checks if the current register should be appended to the previous range. + if (OffsetInDescriptorsFromTableStart != ~0U) + Register = OffsetInDescriptorsFromTableStart; + + // Check for overflow in the register value. + if (Register > ~0U) + return true; + // Is the current range unbounded? + if (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)BaseRegister + (uint64_t)NumDescriptors - (uint64_t)1U; + if (UpperBound > ~0U) + return true; + + // If we append this range, will it overflow? + uint64_t AppendingUpperBound = + (uint64_t)Register + (uint64_t)NumDescriptors - (uint64_t)1U; + if (AppendingUpperBound > ~0U) + return true; + AppendingRegister = Register + NumDescriptors; + } + return false; +} + } // namespace rootsig } // namespace hlsl } // namespace llvm From 84d457985374fa8f24bdeac2da5c8d65cb5e502e Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Mon, 25 Aug 2025 13:08:50 -0700 Subject: [PATCH 109/143] refactoring suggested by inbelic --- .../Frontend/HLSL/RootSignatureValidations.h | 9 ++- .../Frontend/HLSL/RootSignatureMetadata.cpp | 18 ++++-- .../HLSL/RootSignatureValidations.cpp | 59 +++++++------------ 3 files changed, 42 insertions(+), 44 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index c6a2886e89118..15769b910a55d 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -17,6 +17,7 @@ #include "llvm/ADT/IntervalMap.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" #include "llvm/Support/Compiler.h" +#include namespace llvm { namespace hlsl { @@ -40,9 +41,11 @@ LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc); LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); LLVM_ABI bool verifyLOD(float LOD); -LLVM_ABI bool verifyOffsetOverflowing( - uint64_t &AppendingRegister, uint32_t OffsetInDescriptorsFromTableStart, - uint32_t BaseRegister, uint32_t Space, uint32_t NumDescriptors); +LLVM_ABI bool verifyRegisterOverflow(uint64_t Register, + uint32_t NumDescriptors); +LLVM_ABI uint64_t updateAppendingRegister(uint64_t Register, + uint32_t NumDescriptors); +LLVM_ABI bool verifyOffsetOverflow(uint32_t Offset, uint64_t Register); } // namespace rootsig } // namespace hlsl diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 40b1f10e09ae9..7a94ad42d6fbf 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -546,12 +546,22 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges) { dxbc::DescriptorRangeType RangeType = static_cast(Range.RangeType); - if (verifyOffsetOverflowing(AppendingRegister, - Range.OffsetInDescriptorsFromTableStart, - Range.BaseShaderRegister, Range.RegisterSpace, - Range.NumDescriptors)) + + if (verifyOffsetOverflow(Range.OffsetInDescriptorsFromTableStart, + AppendingRegister)) + return make_error( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + + if (verifyRegisterOverflow(Range.BaseShaderRegister, Range.NumDescriptors)) return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + + if (verifyRegisterOverflow(AppendingRegister, Range.NumDescriptors)) + return make_error( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + + AppendingRegister = + updateAppendingRegister(AppendingRegister, Range.NumDescriptors); } return Error::success(); diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 52cada81a7c44..ff420de392b94 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -180,48 +180,33 @@ bool verifyBorderColor(uint32_t BorderColor) { bool verifyLOD(float LOD) { return !std::isnan(LOD); } -/** 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 appends a resource - * after an unbounded range. - **/ -bool verifyOffsetOverflowing(uint64_t &AppendingRegister, - uint32_t OffsetInDescriptorsFromTableStart, - uint32_t BaseRegister, uint32_t Space, - uint32_t NumDescriptors) { - uint64_t Register = AppendingRegister; - - // Checks if the current register should be appended to the previous range. - if (OffsetInDescriptorsFromTableStart != ~0U) - Register = OffsetInDescriptorsFromTableStart; - - // Check for overflow in the register value. +bool verifyOffsetOverflow(uint32_t Offset, uint64_t Register) { + if (Offset != ~0U) + Register = Offset; + if (Register > ~0U) return true; - // Is the current range unbounded? - if (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)BaseRegister + (uint64_t)NumDescriptors - (uint64_t)1U; - if (UpperBound > ~0U) - return true; - - // If we append this range, will it overflow? - uint64_t AppendingUpperBound = - (uint64_t)Register + (uint64_t)NumDescriptors - (uint64_t)1U; - if (AppendingUpperBound > ~0U) - return true; - AppendingRegister = Register + NumDescriptors; - } return false; } +bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors) { + if (NumDescriptors == ~0U) + return false; + + uint64_t UpperBound = + (uint64_t)Register + (uint64_t)NumDescriptors - (uint64_t)1U; + if (UpperBound > ~0U) + return true; + + return false; +} + +uint64_t updateAppendingRegister(uint64_t AppendingRegisterRegister, + uint32_t NumDescriptors) { + if (NumDescriptors == ~0U) + return (uint64_t)~0U + (uint64_t)1ULL; + return AppendingRegisterRegister + NumDescriptors; +} } // namespace rootsig } // namespace hlsl } // namespace llvm From d2b4aea9307e2124ca84ef72e9ebbafaf3cd7e7a Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Mon, 25 Aug 2025 19:41:57 -0700 Subject: [PATCH 110/143] adding multiple error messages --- .../Frontend/HLSL/RootSignatureMetadata.h | 53 +++++++++++++++++-- .../Frontend/HLSL/RootSignatureValidations.h | 7 +-- .../Frontend/HLSL/RootSignatureMetadata.cpp | 23 +++++--- .../HLSL/RootSignatureValidations.cpp | 12 ++--- ...gnature-validation-fail-offset-overflow.ll | 16 ++++++ ...ature-validation-fail-register-overflow.ll | 2 +- 6 files changed, 90 insertions(+), 23 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index 096cd9dded9eb..6788b0f9773bc 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -48,16 +48,15 @@ class RootSignatureValidationError } }; -class TableRegisterOverflowError - : public ErrorInfo { +class OffsetOverflowError : public ErrorInfo { public: static char ID; dxbc::DescriptorRangeType Type; uint32_t Register; uint32_t Space; - TableRegisterOverflowError(dxbc::DescriptorRangeType Type, uint32_t Register, - uint32_t Space) + OffsetOverflowError(dxbc::DescriptorRangeType Type, uint32_t Register, + uint32_t Space) : Type(Type), Register(Register), Space(Space) {} void log(raw_ostream &OS) const override { @@ -72,6 +71,52 @@ class TableRegisterOverflowError } }; +class ShaderRegisterOverflowError + : public ErrorInfo { +public: + static char ID; + dxbc::DescriptorRangeType Type; + uint32_t Register; + uint32_t Space; + + ShaderRegisterOverflowError(dxbc::DescriptorRangeType Type, uint32_t Register, + uint32_t Space) + : Type(Type), Register(Register), Space(Space) {} + + void log(raw_ostream &OS) const override { + OS << "Overflow for shader register range: " + << getResourceClassName(toResourceClass(Type)) + << "(register=" << Register << ", space=" << Space << ")."; + } + + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; + +class DescriptorRangeOverflowError + : public ErrorInfo { +public: + static char ID; + dxbc::DescriptorRangeType Type; + uint32_t Register; + uint32_t Space; + + DescriptorRangeOverflowError(dxbc::DescriptorRangeType Type, + uint32_t Register, uint32_t Space) + : Type(Type), Register(Register), Space(Space) {} + + void log(raw_ostream &OS) const override { + OS << "Overflow for descriptor range: " + << getResourceClassName(toResourceClass(Type)) + << "(register=" << Register << ", space=" << Space << ")."; + } + + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; + class TableSamplerMixinError : public ErrorInfo { public: static char ID; diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 15769b910a55d..1ec3c01dfdd2e 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -43,9 +43,10 @@ LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); LLVM_ABI bool verifyLOD(float LOD); LLVM_ABI bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors); -LLVM_ABI uint64_t updateAppendingRegister(uint64_t Register, - uint32_t NumDescriptors); -LLVM_ABI bool verifyOffsetOverflow(uint32_t Offset, uint64_t Register); +LLVM_ABI uint64_t updateAppendingRegister(uint64_t AppendingRegisterRegister, + uint64_t NumDescriptors, + uint64_t Offset); +LLVM_ABI bool verifyOffsetOverflow(uint64_t Register); } // namespace rootsig } // namespace hlsl diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 7a94ad42d6fbf..aa7a4d0e1e579 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -27,7 +27,10 @@ char GenericRSMetadataError::ID; char InvalidRSMetadataFormat::ID; char InvalidRSMetadataValue::ID; char TableSamplerMixinError::ID; -char TableRegisterOverflowError::ID; +char ShaderRegisterOverflowError::ID; +char OffsetOverflowError::ID; +char DescriptorRangeOverflowError::ID; + template char RootSignatureValidationError::ID; static std::optional extractMdIntValue(MDNode *Node, @@ -547,21 +550,25 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, dxbc::DescriptorRangeType RangeType = static_cast(Range.RangeType); - if (verifyOffsetOverflow(Range.OffsetInDescriptorsFromTableStart, - AppendingRegister)) - return make_error( + uint64_t StartSlot = AppendingRegister; + if (Range.OffsetInDescriptorsFromTableStart != ~0U) + StartSlot = Range.OffsetInDescriptorsFromTableStart; + + if (verifyOffsetOverflow(StartSlot)) + return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); if (verifyRegisterOverflow(Range.BaseShaderRegister, Range.NumDescriptors)) - return make_error( + return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); - if (verifyRegisterOverflow(AppendingRegister, Range.NumDescriptors)) - return make_error( + if (verifyRegisterOverflow(StartSlot, Range.NumDescriptors)) + return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); AppendingRegister = - updateAppendingRegister(AppendingRegister, Range.NumDescriptors); + updateAppendingRegister(StartSlot, Range.NumDescriptors, + Range.OffsetInDescriptorsFromTableStart); } return Error::success(); diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index ff420de392b94..36d6bd9d8b0a2 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -180,10 +180,7 @@ bool verifyBorderColor(uint32_t BorderColor) { bool verifyLOD(float LOD) { return !std::isnan(LOD); } -bool verifyOffsetOverflow(uint32_t Offset, uint64_t Register) { - if (Offset != ~0U) - Register = Offset; - +bool verifyOffsetOverflow(uint64_t Register) { if (Register > ~0U) return true; return false; @@ -201,11 +198,12 @@ bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors) { return false; } -uint64_t updateAppendingRegister(uint64_t AppendingRegisterRegister, - uint32_t NumDescriptors) { +uint64_t updateAppendingRegister(uint64_t AppendingRegister, + uint64_t NumDescriptors, uint64_t Offset) { if (NumDescriptors == ~0U) return (uint64_t)~0U + (uint64_t)1ULL; - return AppendingRegisterRegister + NumDescriptors; + return Offset == ~0U ? AppendingRegister + NumDescriptors + : Offset + NumDescriptors; } } // namespace rootsig } // namespace hlsl diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll new file mode 100644 index 0000000000000..7517bc7c65121 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.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: Overflow for descriptor range: UAV(register=0, space=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 100, i32 0, i32 0, i32 4294967294, i32 0} +!5 = !{!"UAV", i32 1, i32 101, i32 0, i32 10, 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 65542a6ca98f2..935e0e146cecd 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 append range with implicit lower bound after an unbounded range UAV(register=4294967295, space=0). +; CHECK: error: Overflow for shader register 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" { From e2ba167e14d1973ff81cbf454a042f13941b5ec0 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Tue, 26 Aug 2025 11:10:38 -0700 Subject: [PATCH 111/143] removing StartSlot --- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index aa7a4d0e1e579..be79572ffed5d 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -550,11 +550,10 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, dxbc::DescriptorRangeType RangeType = static_cast(Range.RangeType); - uint64_t StartSlot = AppendingRegister; if (Range.OffsetInDescriptorsFromTableStart != ~0U) - StartSlot = Range.OffsetInDescriptorsFromTableStart; + AppendingRegister = Range.OffsetInDescriptorsFromTableStart; - if (verifyOffsetOverflow(StartSlot)) + if (verifyOffsetOverflow(AppendingRegister)) return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); @@ -562,12 +561,12 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); - if (verifyRegisterOverflow(StartSlot, Range.NumDescriptors)) + if (verifyRegisterOverflow(AppendingRegister, Range.NumDescriptors)) return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); AppendingRegister = - updateAppendingRegister(StartSlot, Range.NumDescriptors, + updateAppendingRegister(AppendingRegister, Range.NumDescriptors, Range.OffsetInDescriptorsFromTableStart); } From b395a47ae90bdf300c15452293e5a1d3c059e9e1 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Tue, 26 Aug 2025 11:29:16 -0700 Subject: [PATCH 112/143] removing unecessary code --- llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 36d6bd9d8b0a2..8d38166c8f021 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -200,8 +200,7 @@ bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors) { uint64_t updateAppendingRegister(uint64_t AppendingRegister, uint64_t NumDescriptors, uint64_t Offset) { - if (NumDescriptors == ~0U) - return (uint64_t)~0U + (uint64_t)1ULL; + return Offset == ~0U ? AppendingRegister + NumDescriptors : Offset + NumDescriptors; } From f9c4b9c20287e3cd45635c97f1b6ea5fe8df6439 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 28 Aug 2025 23:23:26 -0700 Subject: [PATCH 113/143] refactoring --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 10 +---- llvm/lib/Frontend/HLSL/HLSLBinding.cpp | 37 ------------------- .../DXILPostOptimizationValidation.cpp | 20 ++++------ .../rootsignature-validation-fail-sampler.ll | 1 - 4 files changed, 9 insertions(+), 59 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index 45d691b890b33..4c068a1c346fb 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -59,7 +59,6 @@ class BindingInfo { } // Size == -1 means unbounded array LLVM_ABI std::optional findAvailableBinding(int32_t Size); - LLVM_ABI bool isBound(const BindingRange &Range) const; }; struct BindingSpaces { @@ -67,8 +66,6 @@ class BindingInfo { llvm::SmallVector Spaces; BindingSpaces(dxil::ResourceClass RC) : RC(RC) {} LLVM_ABI RegisterSpace &getOrInsertSpace(uint32_t Space); - LLVM_ABI std::optional - contains(uint32_t Space) const; }; private: @@ -100,9 +97,6 @@ class BindingInfo { LLVM_ABI std::optional findAvailableBinding(dxil::ResourceClass RC, uint32_t Space, int32_t Size); - LLVM_ABI bool isBound(dxil::ResourceClass RC, uint32_t Space, - const BindingRange &Range) const; - friend class BindingInfoBuilder; }; @@ -152,8 +146,8 @@ class BoundRegs { It->UpperBound >= UpperBound; } - const Binding* getReg(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound, - uint32_t UpperBound) const { + const Binding *getReg(dxil::ResourceClass RC, uint32_t Space, + uint32_t LowerBound) const { const Binding *It = llvm::upper_bound(Bindings, Binding{RC, Space, LowerBound, 0, nullptr}); if (It == Bindings.begin()) diff --git a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp index e39449865fe6f..401402fb5a7ba 100644 --- a/llvm/lib/Frontend/HLSL/HLSLBinding.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLBinding.cpp @@ -8,8 +8,6 @@ #include "llvm/Frontend/HLSL/HLSLBinding.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Error.h" -#include using namespace llvm; using namespace hlsl; @@ -34,18 +32,6 @@ BindingInfo::BindingSpaces::getOrInsertSpace(uint32_t Space) { return Spaces.emplace_back(Space); } -std::optional -BindingInfo::BindingSpaces::contains(uint32_t Space) const { - const BindingInfo::RegisterSpace *It = Spaces.begin(); - for (auto *End = Spaces.end(); It != End; ++It) { - if (It->Space == Space) - break; - } - if (It == Spaces.end()) - return std::nullopt; - return It; -} - std::optional BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) { assert((Size == -1 || Size > 0) && "invalid size"); @@ -80,29 +66,6 @@ BindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) { return std::nullopt; } -bool BindingInfo::RegisterSpace::isBound(const BindingRange &Range) const { - const BindingRange *It = llvm::lower_bound( - FreeRanges, Range.LowerBound, - [](const BindingRange &R, uint32_t Val) { return R.UpperBound <= Val; }); - - if (It != FreeRanges.end()) { - // Check if B is fully contained in the found range - if (Range.LowerBound >= It->LowerBound && - Range.UpperBound <= It->UpperBound) - return false; - } - return true; -} - -bool BindingInfo::isBound(dxil::ResourceClass RC, uint32_t Space, - const BindingRange &Range) const { - const BindingSpaces &BS = getBindingSpaces(RC); - std::optional RS = BS.contains(Space); - if (!RS) - return false; - return RS.value()->isBound(Range); -} - BindingInfo BindingInfoBuilder::calculateBindingInfo( llvm::function_ref diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 90f372b1cc26a..7335b4e10f4bd 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -122,9 +122,10 @@ static void reportInvalidHandleTyError(Module &M, ResourceClass RC, ResourceInfo::ResourceBinding Binding) { SmallString<128> Message; raw_svector_ostream OS(Message); - OS << getResourceClassName(RC) << " at register " << Binding.LowerBound << " and space " - << Binding.Space << " is bound to a texture or typed buffer. " << - "SRV or UAV root descriptors can only be Raw or Structured buffers."; + StringRef RCName = getResourceClassName(RC); + OS << RCName << " at register " << Binding.LowerBound << " and space " + << Binding.Space << " is bound to a texture or typed buffer. " << RCName + << " root descriptors can only be Raw or Structured buffers."; M.getContext().diagnose(DiagnosticInfoGeneric(Message)); } @@ -242,22 +243,18 @@ static void validateRootSignature(Module &M, Builder.findOverlapping(ReportedBinding); reportOverlappingRegisters(M, ReportedBinding, Overlaping); }); - const hlsl::BoundRegs &BoundRegs = Builder.takeBoundRegs(); - for (const ResourceInfo &RI : DRM) { const ResourceInfo::ResourceBinding &Binding = RI.getBinding(); const dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()]; dxil::ResourceClass RC = RTI.getResourceClass(); dxil::ResourceKind RK = RTI.getResourceKind(); if (!BoundRegs.isBound(RC, Binding.Space, Binding.LowerBound, - Binding.LowerBound + Binding.Size - 1)) + Binding.LowerBound + Binding.Size - 1)) { reportRegNotBound(M, RC, Binding); - else { - + } else { const llvm::hlsl::Binding *Reg = - BoundRegs.getReg(RC, Binding.Space, Binding.LowerBound, - Binding.LowerBound + Binding.Size - 1); + BoundRegs.getReg(RC, Binding.Space, Binding.LowerBound); const mcdxbc::RootParameterInfo *ParamInfo = static_cast(Reg->Cookie); if((RC == ResourceClass::SRV || RC == ResourceClass::UAV) && @@ -265,7 +262,6 @@ static void validateRootSignature(Module &M, !(RK == ResourceKind::RawBuffer || RK == ResourceKind::StructuredBuffer)) reportInvalidHandleTyError(M, RC, Binding); } - } } @@ -332,7 +328,6 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { static char ID; // Pass identification. void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { - AU.addRequired(); AU.addRequired(); AU.addRequired(); @@ -343,7 +338,6 @@ class DXILPostOptimizationValidationLegacy : public ModulePass { AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); - AU.addPreserved(); } }; char DXILPostOptimizationValidationLegacy::ID = 0; diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll index 968ab1d699574..c244095520468 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler.ll @@ -1,7 +1,6 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s ; CHECK: error: resource Sampler (space=0, registers=[42, 42]) overlaps with resource Sampler (space=0, registers=[42, 42]) - define void @CSMain() "hlsl.shader"="compute" { entry: ret void From c7cedb4213a03b5111cd67cf3550bf3abb1e275a Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 28 Aug 2025 23:26:18 -0700 Subject: [PATCH 114/143] adding comment --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index 4c068a1c346fb..b73066a101560 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -148,6 +148,7 @@ class BoundRegs { const Binding *getReg(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound) const { + // UpperBound and Cookie are not used in operator< const Binding *It = llvm::upper_bound(Bindings, Binding{RC, Space, LowerBound, 0, nullptr}); if (It == Bindings.begin()) From bf9b30c1eb6ca185df516e3f8f1b8d7e2f609370 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 29 Aug 2025 11:54:04 -0700 Subject: [PATCH 115/143] refactoring isBound to return the bound reg --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 24 ++++++--------- .../DXILPostOptimizationValidation.cpp | 29 ++++++++++++------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index b73066a101560..9cfe208855f57 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -133,27 +133,21 @@ class BoundRegs { public: BoundRegs(SmallVector &&Bindings) : Bindings(std::move(Bindings)) {} - bool isBound(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound, - uint32_t UpperBound) const { + std::optional getBoundRegister(dxil::ResourceClass RC, + uint32_t Space, + uint32_t LowerBound, + uint32_t UpperBound) const { // UpperBound and Cookie are given dummy values, since they aren't // interesting for operator< const Binding *It = llvm::upper_bound(Bindings, Binding{RC, Space, LowerBound, 0, nullptr}); if (It == Bindings.begin()) - return false; + return std::nullopt; --It; - return It->RC == RC && It->Space == Space && It->LowerBound <= LowerBound && - It->UpperBound >= UpperBound; - } - - const Binding *getReg(dxil::ResourceClass RC, uint32_t Space, - uint32_t LowerBound) const { - // UpperBound and Cookie are not used in operator< - const Binding *It = - llvm::upper_bound(Bindings, Binding{RC, Space, LowerBound, 0, nullptr}); - if (It == Bindings.begin()) - llvm_unreachable("getReg expectes to be called only when isBound is true"); - return --It; + if (It->RC == RC && It->Space == Space && It->LowerBound <= LowerBound && + It->UpperBound >= UpperBound) + return It; + return std::nullopt; } }; diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 7335b4e10f4bd..8f2f88f1f5c52 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -249,18 +249,25 @@ static void validateRootSignature(Module &M, const dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()]; dxil::ResourceClass RC = RTI.getResourceClass(); dxil::ResourceKind RK = RTI.getResourceKind(); - if (!BoundRegs.isBound(RC, Binding.Space, Binding.LowerBound, - Binding.LowerBound + Binding.Size - 1)) { - reportRegNotBound(M, RC, Binding); + + std::optional Reg = + BoundRegs.getBoundRegister(RC, Binding.Space, Binding.LowerBound, + Binding.LowerBound + Binding.Size - 1); + + if (Reg.has_value()) { + const auto *ParamInfo = + static_cast((*Reg)->Cookie); + + if (RC != ResourceClass::SRV && RC != ResourceClass::UAV) + continue; + + if (ParamInfo->Type == dxbc::RootParameterType::DescriptorTable) + continue; + + if (RK != ResourceKind::RawBuffer && RK != ResourceKind::StructuredBuffer) + reportInvalidHandleTyError(M, RC, Binding); } else { - const llvm::hlsl::Binding *Reg = - BoundRegs.getReg(RC, Binding.Space, Binding.LowerBound); - const mcdxbc::RootParameterInfo *ParamInfo = static_cast(Reg->Cookie); - - if((RC == ResourceClass::SRV || RC == ResourceClass::UAV) && - ParamInfo->Type != dxbc::RootParameterType::DescriptorTable && - !(RK == ResourceKind::RawBuffer || RK == ResourceKind::StructuredBuffer)) - reportInvalidHandleTyError(M, RC, Binding); + reportRegNotBound(M, RC, Binding); } } } From 18e4c3d1e29cdc796cd02b410d7b4afdde0c4fed Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 29 Aug 2025 11:55:17 -0700 Subject: [PATCH 116/143] formating --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 8 ++++---- .../lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index 9cfe208855f57..3940cc0253eee 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -133,10 +133,10 @@ class BoundRegs { public: BoundRegs(SmallVector &&Bindings) : Bindings(std::move(Bindings)) {} - std::optional getBoundRegister(dxil::ResourceClass RC, - uint32_t Space, - uint32_t LowerBound, - uint32_t UpperBound) const { + std::optional findBoundReg(dxil::ResourceClass RC, + uint32_t Space, + uint32_t LowerBound, + uint32_t UpperBound) const { // UpperBound and Cookie are given dummy values, since they aren't // interesting for operator< const Binding *It = diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 8f2f88f1f5c52..9bb6ed0a1a821 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -251,8 +251,8 @@ static void validateRootSignature(Module &M, dxil::ResourceKind RK = RTI.getResourceKind(); std::optional Reg = - BoundRegs.getBoundRegister(RC, Binding.Space, Binding.LowerBound, - Binding.LowerBound + Binding.Size - 1); + BoundRegs.findBoundReg(RC, Binding.Space, Binding.LowerBound, + Binding.LowerBound + Binding.Size - 1); if (Reg.has_value()) { const auto *ParamInfo = From 42518b247667c14e845cd4de750c94301774145a Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 29 Aug 2025 19:53:17 -0700 Subject: [PATCH 117/143] clean up --- llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 1ec3c01dfdd2e..aa957e3feb819 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -17,7 +17,6 @@ #include "llvm/ADT/IntervalMap.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" #include "llvm/Support/Compiler.h" -#include namespace llvm { namespace hlsl { @@ -43,10 +42,10 @@ LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); LLVM_ABI bool verifyLOD(float LOD); LLVM_ABI bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors); +LLVM_ABI bool verifyOffsetOverflow(uint64_t Register); LLVM_ABI uint64_t updateAppendingRegister(uint64_t AppendingRegisterRegister, uint64_t NumDescriptors, uint64_t Offset); -LLVM_ABI bool verifyOffsetOverflow(uint64_t Register); } // namespace rootsig } // namespace hlsl From f6abbf71135c4f8fe1489dcf1ec702d4fa5e8d6d Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 29 Aug 2025 20:26:43 -0700 Subject: [PATCH 118/143] clean up --- .../Frontend/HLSL/RootSignatureMetadata.h | 31 +++++++++---------- .../Frontend/HLSL/RootSignatureMetadata.cpp | 14 ++++++--- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index 6788b0f9773bc..4e2a074e37421 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -51,19 +51,19 @@ class RootSignatureValidationError class OffsetOverflowError : public ErrorInfo { public: static char ID; - dxbc::DescriptorRangeType Type; + dxil::ResourceClass Type; uint32_t Register; uint32_t Space; - OffsetOverflowError(dxbc::DescriptorRangeType Type, uint32_t Register, + OffsetOverflowError(dxil::ResourceClass 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 << ")."; + << getResourceClassName(Type) << "(register=" << Register + << ", space=" << Space << ")."; } std::error_code convertToErrorCode() const override { @@ -75,17 +75,16 @@ class ShaderRegisterOverflowError : public ErrorInfo { public: static char ID; - dxbc::DescriptorRangeType Type; + dxil::ResourceClass Type; uint32_t Register; uint32_t Space; - ShaderRegisterOverflowError(dxbc::DescriptorRangeType Type, uint32_t Register, + ShaderRegisterOverflowError(dxil::ResourceClass Type, uint32_t Register, uint32_t Space) : Type(Type), Register(Register), Space(Space) {} void log(raw_ostream &OS) const override { - OS << "Overflow for shader register range: " - << getResourceClassName(toResourceClass(Type)) + OS << "Overflow for shader register range: " << getResourceClassName(Type) << "(register=" << Register << ", space=" << Space << ")."; } @@ -98,17 +97,16 @@ class DescriptorRangeOverflowError : public ErrorInfo { public: static char ID; - dxbc::DescriptorRangeType Type; + dxil::ResourceClass Type; uint32_t Register; uint32_t Space; - DescriptorRangeOverflowError(dxbc::DescriptorRangeType Type, - uint32_t Register, uint32_t Space) + DescriptorRangeOverflowError(dxil::ResourceClass Type, uint32_t Register, + uint32_t Space) : Type(Type), Register(Register), Space(Space) {} void log(raw_ostream &OS) const override { - OS << "Overflow for descriptor range: " - << getResourceClassName(toResourceClass(Type)) + OS << "Overflow for descriptor range: " << getResourceClassName(Type) << "(register=" << Register << ", space=" << Space << ")."; } @@ -120,16 +118,15 @@ class DescriptorRangeOverflowError class TableSamplerMixinError : public ErrorInfo { public: static char ID; - dxbc::DescriptorRangeType Type; + dxil::ResourceClass Type; uint32_t Location; - TableSamplerMixinError(dxbc::DescriptorRangeType Type, uint32_t Location) + TableSamplerMixinError(dxil::ResourceClass 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)) + << "resource types in a descriptor table, " << getResourceClassName(Type) << "(location=" << Location << ")"; } diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index bab5d913a35f0..6324f36852afc 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -540,7 +540,8 @@ Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, // Samplers cannot be mixed with other resources in a descriptor table. if (HasSampler && HasOtherRangeType) - return make_error(OtherRangeType, Location); + return make_error(toResourceClass(OtherRangeType), + Location); return Error::success(); } @@ -556,16 +557,19 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, AppendingRegister = Range.OffsetInDescriptorsFromTableStart; if (verifyOffsetOverflow(AppendingRegister)) - return make_error( - RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + return make_error(dxbc::toResourceClass(RangeType), + Range.BaseShaderRegister, + Range.RegisterSpace); if (verifyRegisterOverflow(Range.BaseShaderRegister, Range.NumDescriptors)) return make_error( - RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + dxbc::toResourceClass(RangeType), Range.BaseShaderRegister, + Range.RegisterSpace); if (verifyRegisterOverflow(AppendingRegister, Range.NumDescriptors)) return make_error( - RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + dxbc::toResourceClass(RangeType), Range.BaseShaderRegister, + Range.RegisterSpace); AppendingRegister = updateAppendingRegister(AppendingRegister, Range.NumDescriptors, From 2971f5fc6f17e697ba3c41efbcb82dd1383269aa Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 29 Aug 2025 20:40:07 -0700 Subject: [PATCH 119/143] clean up --- llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 8d38166c8f021..83c971de1960c 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -181,9 +181,7 @@ bool verifyBorderColor(uint32_t BorderColor) { bool verifyLOD(float LOD) { return !std::isnan(LOD); } bool verifyOffsetOverflow(uint64_t Register) { - if (Register > ~0U) - return true; - return false; + return Register > ~0U; } bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors) { From f0ed242c159fc0360287a4c47fc49c885e33dbe0 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 29 Aug 2025 20:41:04 -0700 Subject: [PATCH 120/143] clean up: self review --- llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 83c971de1960c..ba365837389a5 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -180,9 +180,7 @@ bool verifyBorderColor(uint32_t BorderColor) { bool verifyLOD(float LOD) { return !std::isnan(LOD); } -bool verifyOffsetOverflow(uint64_t Register) { - return Register > ~0U; -} +bool verifyOffsetOverflow(uint64_t Register) { return Register > ~0U; } bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors) { if (NumDescriptors == ~0U) @@ -190,10 +188,7 @@ bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors) { uint64_t UpperBound = (uint64_t)Register + (uint64_t)NumDescriptors - (uint64_t)1U; - if (UpperBound > ~0U) - return true; - - return false; + return UpperBound > ~0U; } uint64_t updateAppendingRegister(uint64_t AppendingRegister, From a6a9fe9acc17da1073f92bbf6cf0ca3acd84ac3d Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 29 Aug 2025 20:46:15 -0700 Subject: [PATCH 121/143] clean up self review --- .../HLSL/RootSignatureValidations.cpp | 1 - ...escriptorTable-AllValidFlagCombinations.ll | 216 +++++++++--------- ...criptorTable-AllValidFlagCombinationsV1.ll | 60 ++--- 3 files changed, 138 insertions(+), 139 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index ba365837389a5..58b82a6d3a49a 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -193,7 +193,6 @@ bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors) { uint64_t updateAppendingRegister(uint64_t AppendingRegister, uint64_t NumDescriptors, uint64_t Offset) { - return Offset == ~0U ? AppendingRegister + NumDescriptors : Offset + NumDescriptors; } diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll index f605bcfe62c40..481f519e9dfde 100644 --- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll @@ -54,111 +54,111 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } !20 = !{ !"UAV", i32 5, i32 1, i32 15, i32 5, i32 65540 } ;DXC:- Name: RTS0 -;DXC-NEXT: Size: 400 -;DXC-NEXT: RootSignature: -;DXC-NEXT: Version: 2 -;DXC-NEXT: NumRootParameters: 2 -;DXC-NEXT: RootParametersOffset: 24 -;DXC-NEXT: NumStaticSamplers: 0 -;DXC-NEXT: StaticSamplersOffset: 400 -;DXC-NEXT: Parameters: -;DXC-NEXT: - ParameterType: 0 -;DXC-NEXT: ShaderVisibility: 0 -;DXC-NEXT: Table: -;DXC-NEXT: NumRanges: 11 -;DXC-NEXT: RangesOffset: 56 -;DXC-NEXT: Ranges: -;DXC-NEXT: - RangeType: 0 -;DXC-NEXT: NumDescriptors: 1 -;DXC-NEXT: BaseShaderRegister: 0 -;DXC-NEXT: RegisterSpace: 5 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: - RangeType: 1 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 6 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: - RangeType: 2 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 7 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_VOLATILE: true -;DXC-NEXT: - RangeType: 0 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 8 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_STATIC: true -;DXC-NEXT: - RangeType: 1 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 9 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true -;DXC-NEXT: - RangeType: 2 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 10 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: DATA_VOLATILE: true -;DXC-NEXT: - RangeType: 0 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 11 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true -;DXC-NEXT: - RangeType: 1 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 12 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true -;DXC-NEXT: - RangeType: 2 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 13 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_VOLATILE: true -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true -;DXC-NEXT: - RangeType: 0 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 14 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_STATIC: true -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true -;DXC-NEXT: - RangeType: 1 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 15 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 -;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true -;DXC-NEXT: - ParameterType: 0 -;DXC-NEXT: ShaderVisibility: 0 -;DXC-NEXT: Table: -;DXC-NEXT: NumRanges: 3 -;DXC-NEXT: RangesOffset: 328 -;DXC-NEXT: Ranges: -;DXC-NEXT: - RangeType: 3 -;DXC-NEXT: NumDescriptors: 1 -;DXC-NEXT: BaseShaderRegister: 0 -;DXC-NEXT: RegisterSpace: 1 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -;DXC-NEXT: - RangeType: 3 -;DXC-NEXT: NumDescriptors: 1 -;DXC-NEXT: BaseShaderRegister: 0 -;DXC-NEXT: RegisterSpace: 3 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -;DXC-NEXT: DESCRIPTORS_VOLATILE: true -;DXC-NEXT: - RangeType: 3 -;DXC-NEXT: NumDescriptors: 1 -;DXC-NEXT: BaseShaderRegister: 0 -;DXC-NEXT: RegisterSpace: 4 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: Size: 400 +;DXC-NEXT: RootSignature: +;DXC-NEXT: Version: 2 +;DXC-NEXT: NumRootParameters: 2 +;DXC-NEXT: RootParametersOffset: 24 +;DXC-NEXT: NumStaticSamplers: 0 +;DXC-NEXT: StaticSamplersOffset: 400 +;DXC-NEXT: Parameters: +;DXC-NEXT: - ParameterType: 0 +;DXC-NEXT: ShaderVisibility: 0 +;DXC-NEXT: Table: +;DXC-NEXT: NumRanges: 11 +;DXC-NEXT: RangesOffset: 56 +;DXC-NEXT: Ranges: +;DXC-NEXT: - RangeType: 0 +;DXC-NEXT: NumDescriptors: 1 +;DXC-NEXT: BaseShaderRegister: 0 +;DXC-NEXT: RegisterSpace: 5 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: - RangeType: 1 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 6 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: - RangeType: 2 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 7 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_VOLATILE: true +;DXC-NEXT: - RangeType: 0 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 8 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_STATIC: true +;DXC-NEXT: - RangeType: 1 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 9 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true +;DXC-NEXT: - RangeType: 2 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 10 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: DATA_VOLATILE: true +;DXC-NEXT: - RangeType: 0 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 11 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true +;DXC-NEXT: - RangeType: 1 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 12 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: - RangeType: 2 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 13 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_VOLATILE: true +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: - RangeType: 0 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 14 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_STATIC: true +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: - RangeType: 1 +;DXC-NEXT: NumDescriptors: 5 +;DXC-NEXT: BaseShaderRegister: 1 +;DXC-NEXT: RegisterSpace: 15 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +;DXC-NEXT: DATA_STATIC_WHILE_SET_AT_EXECUTE: true +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true +;DXC-NEXT: - ParameterType: 0 +;DXC-NEXT: ShaderVisibility: 0 +;DXC-NEXT: Table: +;DXC-NEXT: NumRanges: 3 +;DXC-NEXT: RangesOffset: 328 +;DXC-NEXT: Ranges: +;DXC-NEXT: - RangeType: 3 +;DXC-NEXT: NumDescriptors: 1 +;DXC-NEXT: BaseShaderRegister: 0 +;DXC-NEXT: RegisterSpace: 1 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +;DXC-NEXT: - RangeType: 3 +;DXC-NEXT: NumDescriptors: 1 +;DXC-NEXT: BaseShaderRegister: 0 +;DXC-NEXT: RegisterSpace: 3 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +;DXC-NEXT: DESCRIPTORS_VOLATILE: true +;DXC-NEXT: - RangeType: 3 +;DXC-NEXT: NumDescriptors: 1 +;DXC-NEXT: BaseShaderRegister: 0 +;DXC-NEXT: RegisterSpace: 4 +;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +;DXC-NEXT: DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS: true diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll index 03e6a7bd415ca..ba85c8fb54b7d 100644 --- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinationsV1.ll @@ -19,33 +19,33 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } ; DXC: - Name: RTS0 -;DXC-NEXT: Size: 104 -;DXC-NEXT: RootSignature: -;DXC-NEXT: Version: 1 -;DXC-NEXT: NumRootParameters: 2 -;DXC-NEXT: RootParametersOffset: 24 -;DXC-NEXT: NumStaticSamplers: 0 -;DXC-NEXT: StaticSamplersOffset: 104 -;DXC-NEXT: Parameters: -;DXC-NEXT: - ParameterType: 0 -;DXC-NEXT: ShaderVisibility: 0 -;DXC-NEXT: Table: -;DXC-NEXT: NumRanges: 1 -;DXC-NEXT: RangesOffset: 56 -;DXC-NEXT: Ranges: -;DXC-NEXT: - RangeType: 3 -;DXC-NEXT: NumDescriptors: 1 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 0 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 -;DXC-NEXT: - ParameterType: 0 -;DXC-NEXT: ShaderVisibility: 0 -;DXC-NEXT: Table: -;DXC-NEXT: NumRanges: 1 -;DXC-NEXT: RangesOffset: 84 -;DXC-NEXT: Ranges: -;DXC-NEXT: - RangeType: 1 -;DXC-NEXT: NumDescriptors: 5 -;DXC-NEXT: BaseShaderRegister: 1 -;DXC-NEXT: RegisterSpace: 10 -;DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 +; DXC-NEXT: Size: 104 +; DXC-NEXT: RootSignature: +; DXC-NEXT: Version: 1 +; DXC-NEXT: NumRootParameters: 2 +; DXC-NEXT: RootParametersOffset: 24 +; DXC-NEXT: NumStaticSamplers: 0 +; DXC-NEXT: StaticSamplersOffset: 104 +; DXC-NEXT: Parameters: +; DXC-NEXT: - ParameterType: 0 +; DXC-NEXT: ShaderVisibility: 0 +; DXC-NEXT: Table: +; DXC-NEXT: NumRanges: 1 +; DXC-NEXT: RangesOffset: 56 +; DXC-NEXT: Ranges: +; DXC-NEXT: - RangeType: 3 +; DXC-NEXT: NumDescriptors: 1 +; DXC-NEXT: BaseShaderRegister: 1 +; DXC-NEXT: RegisterSpace: 0 +; DXC-NEXT: OffsetInDescriptorsFromTableStart: 4294967295 +; DXC-NEXT: - ParameterType: 0 +; DXC-NEXT: ShaderVisibility: 0 +; DXC-NEXT: Table: +; DXC-NEXT: NumRanges: 1 +; DXC-NEXT: RangesOffset: 84 +; DXC-NEXT: Ranges: +; DXC-NEXT: - RangeType: 1 +; DXC-NEXT: NumDescriptors: 5 +; DXC-NEXT: BaseShaderRegister: 1 +; DXC-NEXT: RegisterSpace: 10 +; DXC-NEXT: OffsetInDescriptorsFromTableStart: 5 From 3f833088fc114f6685d60a061c8dae3affc7cc1f Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 11:34:58 -0700 Subject: [PATCH 122/143] remove optional from type --- llvm/include/llvm/Frontend/HLSL/HLSLBinding.h | 10 ++++------ .../Target/DirectX/DXILPostOptimizationValidation.cpp | 6 +++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h index 3940cc0253eee..8afa7687a17c6 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLBinding.h @@ -133,21 +133,19 @@ class BoundRegs { public: BoundRegs(SmallVector &&Bindings) : Bindings(std::move(Bindings)) {} - std::optional findBoundReg(dxil::ResourceClass RC, - uint32_t Space, - uint32_t LowerBound, - uint32_t UpperBound) const { + const Binding *findBoundReg(dxil::ResourceClass RC, uint32_t Space, + uint32_t LowerBound, uint32_t UpperBound) const { // UpperBound and Cookie are given dummy values, since they aren't // interesting for operator< const Binding *It = llvm::upper_bound(Bindings, Binding{RC, Space, LowerBound, 0, nullptr}); if (It == Bindings.begin()) - return std::nullopt; + return nullptr; --It; if (It->RC == RC && It->Space == Space && It->LowerBound <= LowerBound && It->UpperBound >= UpperBound) return It; - return std::nullopt; + return nullptr; } }; diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index 9bb6ed0a1a821..e2d03c3c003d1 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -250,13 +250,13 @@ static void validateRootSignature(Module &M, dxil::ResourceClass RC = RTI.getResourceClass(); dxil::ResourceKind RK = RTI.getResourceKind(); - std::optional Reg = + const llvm::hlsl::Binding *Reg = BoundRegs.findBoundReg(RC, Binding.Space, Binding.LowerBound, Binding.LowerBound + Binding.Size - 1); - if (Reg.has_value()) { + if (Reg != nullptr) { const auto *ParamInfo = - static_cast((*Reg)->Cookie); + static_cast(Reg->Cookie); if (RC != ResourceClass::SRV && RC != ResourceClass::UAV) continue; From 8daa97bae27904f0388d9015c1fa6cf243e5cbfb Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 11:36:30 -0700 Subject: [PATCH 123/143] changing small string size --- llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp index e2d03c3c003d1..d88082b54d843 100644 --- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp +++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp @@ -120,7 +120,7 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) { static void reportInvalidHandleTyError(Module &M, ResourceClass RC, ResourceInfo::ResourceBinding Binding) { - SmallString<128> Message; + SmallString<160> Message; raw_svector_ostream OS(Message); StringRef RCName = getResourceClassName(RC); OS << RCName << " at register " << Binding.LowerBound << " and space " From 79f1f487ec56100ef8ab6402e04f609ee5f10151 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 11:44:50 -0700 Subject: [PATCH 124/143] fixing tests --- ...e-validation-textures.ll => rootsignature-valid-textures.ll} | 0 .../CodeGen/DirectX/rootsignature-validation-textures-fail.ll | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename llvm/test/CodeGen/DirectX/{rootsignature-validation-textures.ll => rootsignature-valid-textures.ll} (100%) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll b/llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll similarity index 100% rename from llvm/test/CodeGen/DirectX/rootsignature-validation-textures.ll rename to llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll index a12e884aeec06..7ec9d8047d08f 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-textures-fail.ll @@ -5,7 +5,7 @@ define void @CSMain() "hlsl.shader"="compute" { entry: - %TB = tail call target("dx.Texture", float, 1, 0, 0, 4) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str) + %TB = tail call target("dx.Texture", float, 1, 0, 0, 4) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str) ret void } From 3d10d92faa8680a0777be2218852d5692194a7e5 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 11:47:37 -0700 Subject: [PATCH 125/143] removing type from handlefrombinding --- llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll | 2 +- .../DirectX/rootsignature-validation-typedbuffer-fail.ll | 2 +- .../CodeGen/DirectX/rootsignature-validation-typedbuffer.ll | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll b/llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll index 6ef59cfb0f605..4721db23a766d 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-valid-textures.ll @@ -5,7 +5,7 @@ define void @CSMain() "hlsl.shader"="compute" { entry: - %TB = tail call target("dx.Texture", <4 x float>, 1, 0, 0, 4) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str) + %TB = tail call target("dx.Texture", <4 x float>, 1, 0, 0, 4) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str) ret void } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll index ed9241c13a4b4..a0120c3954ad0 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer-fail.ll @@ -5,7 +5,7 @@ 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, ptr nonnull @TB.str) + %TB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str) ret void } diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll index 4f1b993d0f14d..2a52b3dee9d28 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll @@ -5,7 +5,7 @@ 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, ptr nonnull @TB.str) + %TB = tail call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr nonnull @TB.str) ret void } From 55c2b96b09dc0b3ff9f642efa759203380d42e21 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 14:50:55 -0700 Subject: [PATCH 126/143] renamig tests --- ...lidation-typedbuffer.ll => rootsignature-valid-typedbuffer.ll} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename llvm/test/CodeGen/DirectX/{rootsignature-validation-typedbuffer.ll => rootsignature-valid-typedbuffer.ll} (100%) diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll b/llvm/test/CodeGen/DirectX/rootsignature-valid-typedbuffer.ll similarity index 100% rename from llvm/test/CodeGen/DirectX/rootsignature-validation-typedbuffer.ll rename to llvm/test/CodeGen/DirectX/rootsignature-valid-typedbuffer.ll From fbf67767113f174cfd26aec622ea172de80493d1 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 16:47:52 -0700 Subject: [PATCH 127/143] refactoring to use existing funcs --- .../Frontend/HLSL/RootSignatureValidations.h | 1 - .../Frontend/HLSL/RootSignatureMetadata.cpp | 39 ++++++++++++------- .../HLSL/RootSignatureValidations.cpp | 17 -------- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 24e851933949f..b63b4faf9e735 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -41,7 +41,6 @@ LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc); LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); LLVM_ABI bool verifyLOD(float LOD); - LLVM_ABI bool verifyBoundOffset(uint32_t Offset); LLVM_ABI bool verifyNoOverflowedOffset(uint64_t Offset); LLVM_ABI uint64_t computeRangeBound(uint32_t Offset, uint32_t Size); diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 593c09fc33843..3d74a46dda8fe 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -68,6 +68,11 @@ extractShaderVisibility(MDNode *Node, unsigned int OpId) { return make_error("ShaderVisibility"); } +static uint64_t updateOngoingOffset(uint64_t CurOfset, uint64_t NumDescriptors, + uint64_t Offset) { + return Offset == ~0U ? CurOfset + NumDescriptors : Offset + NumDescriptors; +} + namespace { // We use the OverloadVisit with std::visit to ensure the compiler catches if a @@ -549,32 +554,40 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, uint32_t Location) { uint64_t Offset = 0; - for (const llvm::mcdxbc::DescriptorRange &Range : Table.Ranges) { + for (const mcdxbc::DescriptorRange &Range : Table.Ranges) { + // Errors for this check should be emitted before this point. + if (Range.NumDescriptors <= 0) + continue; dxil::ResourceClass RangeType = static_cast(Range.RangeType); - if (Range.OffsetInDescriptorsFromTableStart != llvm::hlsl::rootsig::DescriptorTableOffsetAppend) + if (Range.OffsetInDescriptorsFromTableStart != DescriptorTableOffsetAppend) Offset = Range.OffsetInDescriptorsFromTableStart; - uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound( - Offset, Range.NumDescriptors); - if (verifyBoundOffset(Offset)) - return make_error( - RangeType, Range.BaseShaderRegister, - Range.RegisterSpace); - else if (!verifyNoOverflowedOffset(Offset)) + if (!verifyNoOverflowedOffset(Offset)) return make_error(RangeType, Range.BaseShaderRegister, Range.RegisterSpace); - if (!verifyNoOverflowedOffset(Range.BaseShaderRegister)) + const uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound( + Range.BaseShaderRegister, Range.NumDescriptors); + + if (!verifyNoOverflowedOffset(RangeBound)) return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); - Offset = RangeBound == llvm::hlsl::rootsig::NumDescriptorsUnbounded - ? uint32_t(RangeBound) - : uint32_t(RangeBound + 1); + const uint64_t OffsetBound = + llvm::hlsl::rootsig::computeRangeBound(Offset, Range.NumDescriptors); + + if (!verifyNoOverflowedOffset(OffsetBound)) + return make_error( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + + // Append to the current offset if DescriptorTableOffsetAppend, otherwise + // calculate the new Offset. + Offset = updateOngoingOffset(Offset, Range.NumDescriptors, + Range.OffsetInDescriptorsFromTableStart); } return Error::success(); diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 3c7a47aa91d4f..01b3120d4156f 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -181,23 +181,6 @@ uint64_t computeRangeBound(uint32_t Offset, uint32_t Size) { return uint64_t(Offset) + uint64_t(Size) - 1; } - -bool verifyOffsetOverflow(uint64_t Register) { return Register > ~0U; } - -bool verifyRegisterOverflow(uint64_t Register, uint32_t NumDescriptors) { - if (NumDescriptors == ~0U) - return false; - - uint64_t UpperBound = - (uint64_t)Register + (uint64_t)NumDescriptors - (uint64_t)1U; - return UpperBound > ~0U; -} - -uint64_t updateAppendingRegister(uint64_t AppendingRegister, - uint64_t NumDescriptors, uint64_t Offset) { - return Offset == ~0U ? AppendingRegister + NumDescriptors - : Offset + NumDescriptors; -} } // namespace rootsig } // namespace hlsl } // namespace llvm From 5633433afd25b915abf2fdb961c0ab8afe345c3e Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 16:51:28 -0700 Subject: [PATCH 128/143] clean up --- llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index b63b4faf9e735..24e851933949f 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -41,6 +41,7 @@ LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc); LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); LLVM_ABI bool verifyLOD(float LOD); + LLVM_ABI bool verifyBoundOffset(uint32_t Offset); LLVM_ABI bool verifyNoOverflowedOffset(uint64_t Offset); LLVM_ABI uint64_t computeRangeBound(uint32_t Offset, uint32_t Size); From b42630a74dc098f4cd54380cc7c53b047bbb3250 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 17:04:43 -0700 Subject: [PATCH 129/143] clean up --- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 15 +++++++-------- .../Frontend/HLSL/RootSignatureValidations.cpp | 1 + .../rootsignature-validation-fail-sampler-mix.ll | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 3d74a46dda8fe..9fa7db79edf3f 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -70,7 +70,10 @@ extractShaderVisibility(MDNode *Node, unsigned int OpId) { static uint64_t updateOngoingOffset(uint64_t CurOfset, uint64_t NumDescriptors, uint64_t Offset) { - return Offset == ~0U ? CurOfset + NumDescriptors : Offset + NumDescriptors; + // Append to the current offset if DescriptorTableOffsetAppend is set, + // otherwise calculate the new Offset. + return Offset == DescriptorTableOffsetAppend ? CurOfset + NumDescriptors + : Offset + NumDescriptors; } namespace { @@ -558,7 +561,7 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, // Errors for this check should be emitted before this point. if (Range.NumDescriptors <= 0) continue; - dxil::ResourceClass RangeType = + const dxil::ResourceClass &RangeType = static_cast(Range.RangeType); if (Range.OffsetInDescriptorsFromTableStart != DescriptorTableOffsetAppend) @@ -584,8 +587,6 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); - // Append to the current offset if DescriptorTableOffsetAppend, otherwise - // calculate the new Offset. Offset = updateOngoingOffset(Offset, Range.NumDescriptors, Range.OffsetInDescriptorsFromTableStart); } @@ -668,14 +669,12 @@ Error MetadataParser::validateRootSignature( "DescriptorFlag", Range.Flags)); if (Error Err = - validateDescriptorTableSamplerMixin(Table, Info.Location)) { + validateDescriptorTableSamplerMixin(Table, Info.Location)) DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err)); - } if (Error Err = - validateDescriptorTableRegisterOverflow(Table, Info.Location)) { + validateDescriptorTableRegisterOverflow(Table, Info.Location)) DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err)); - } } break; } diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 01b3120d4156f..d682dda0bab26 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -181,6 +181,7 @@ uint64_t computeRangeBound(uint32_t Offset, uint32_t Size) { return uint64_t(Offset) + uint64_t(Size) - 1; } + } // namespace rootsig } // namespace hlsl } // namespace llvm diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll index d4caeb2675d82..3bf7b1041af41 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll @@ -15,4 +15,3 @@ entry: !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 bce1ef972fc6045970a08b9354e430c1eed27a0d Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 17:07:31 -0700 Subject: [PATCH 130/143] improve comment message --- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 9fa7db79edf3f..938d9dd631747 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -558,7 +558,7 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, uint64_t Offset = 0; for (const mcdxbc::DescriptorRange &Range : Table.Ranges) { - // Errors for this check should be emitted before this point. + // Validation of NumDescriptors should have happened by this point. if (Range.NumDescriptors <= 0) continue; const dxil::ResourceClass &RangeType = From cf84fcf5531513ccd7907775fcc8acdedd96ee20 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 10 Sep 2025 17:18:25 -0700 Subject: [PATCH 131/143] clean up --- .../DirectX/rootsignature-validation-fail-appending-overflow.ll | 2 -- .../DirectX/rootsignature-validation-fail-offset-overflow.ll | 1 - .../DirectX/rootsignature-validation-fail-register-overflow.ll | 2 -- .../DirectX/rootsignature-validation-fail-sampler-mix.ll | 2 -- 4 files changed, 7 deletions(-) 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 2b5ce4f52b94e..f0009c80c28c1 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll @@ -3,8 +3,6 @@ ; 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 - define void @CSMain() "hlsl.shader"="compute" { entry: ret void diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll index 7517bc7c65121..06177ee3c261e 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll @@ -1,6 +1,5 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s ; CHECK: error: Overflow for descriptor range: UAV(register=0, space=0) -@TB.str = private unnamed_addr constant [3 x i8] c"TB\00", align 1 define void @CSMain() "hlsl.shader"="compute" { entry: 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 935e0e146cecd..bff1727c18924 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-register-overflow.ll @@ -1,7 +1,5 @@ ; RUN: not opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s ; CHECK: error: Overflow for shader register 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" { entry: ret void diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll index 3bf7b1041af41..95d00619b02a0 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-sampler-mix.ll @@ -1,8 +1,6 @@ ; 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 From e5976eef04be22c4fbd322934160e053940d30f7 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 11 Sep 2025 12:15:52 -0700 Subject: [PATCH 132/143] making updateOngoingOffset shared --- clang/lib/Sema/SemaHLSL.cpp | 5 ++--- .../llvm/Frontend/HLSL/RootSignatureValidations.h | 2 ++ llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 9 --------- llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp | 8 ++++++++ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 6062f81d0aed3..2662ebfa0bb30 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1378,9 +1378,8 @@ bool SemaHLSL::handleRootSignatureElements( Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound; } - Offset = RangeBound == llvm::hlsl::rootsig::NumDescriptorsUnbounded - ? uint32_t(RangeBound) - : uint32_t(RangeBound + 1); + Offset = llvm::hlsl::rootsig::updateOngoingOffset( + Offset, Clause->NumDescriptors, Clause->Offset); // Compute the register bounds and track resource binding uint32_t LowerBound(Clause->Reg.Number); diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 24e851933949f..48918f140ff0b 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -45,6 +45,8 @@ LLVM_ABI bool verifyLOD(float LOD); LLVM_ABI bool verifyBoundOffset(uint32_t Offset); LLVM_ABI bool verifyNoOverflowedOffset(uint64_t Offset); LLVM_ABI uint64_t computeRangeBound(uint32_t Offset, uint32_t Size); +LLVM_ABI uint64_t updateOngoingOffset(uint64_t CurOffset, + uint64_t NumDescriptors, uint64_t Offset); } // namespace rootsig } // namespace hlsl diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 938d9dd631747..bf72dd12dd6e0 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -68,14 +68,6 @@ extractShaderVisibility(MDNode *Node, unsigned int OpId) { return make_error("ShaderVisibility"); } -static uint64_t updateOngoingOffset(uint64_t CurOfset, uint64_t NumDescriptors, - uint64_t Offset) { - // Append to the current offset if DescriptorTableOffsetAppend is set, - // otherwise calculate the new Offset. - return Offset == DescriptorTableOffsetAppend ? CurOfset + NumDescriptors - : Offset + NumDescriptors; -} - namespace { // We use the OverloadVisit with std::visit to ensure the compiler catches if a @@ -586,7 +578,6 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, if (!verifyNoOverflowedOffset(OffsetBound)) return make_error( RangeType, Range.BaseShaderRegister, Range.RegisterSpace); - Offset = updateOngoingOffset(Offset, Range.NumDescriptors, Range.OffsetInDescriptorsFromTableStart); } diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index d682dda0bab26..4bba98f0edf16 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -182,6 +182,14 @@ uint64_t computeRangeBound(uint32_t Offset, uint32_t Size) { return uint64_t(Offset) + uint64_t(Size) - 1; } +uint64_t updateOngoingOffset(uint64_t CurOffset, uint64_t NumDescriptors, + uint64_t Offset) { + // Append to the current offset if DescriptorTableOffsetAppend is set, + // otherwise calculate the new Offset. + return Offset == DescriptorTableOffsetAppend ? CurOffset + NumDescriptors + : Offset + NumDescriptors; +} + } // namespace rootsig } // namespace hlsl } // namespace llvm From eb84e1406414fd7b48df241b69efa0f8ea74062b Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 11 Sep 2025 13:14:59 -0700 Subject: [PATCH 133/143] refactoring --- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index bf72dd12dd6e0..26dcf6f6a6139 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -560,17 +560,15 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, Offset = Range.OffsetInDescriptorsFromTableStart; if (!verifyNoOverflowedOffset(Offset)) - return make_error(RangeType, - Range.BaseShaderRegister, - Range.RegisterSpace); + return make_error( + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); const uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound( Range.BaseShaderRegister, Range.NumDescriptors); if (!verifyNoOverflowedOffset(RangeBound)) return make_error( - RangeType, Range.BaseShaderRegister, - Range.RegisterSpace); + RangeType, Range.BaseShaderRegister, Range.RegisterSpace); const uint64_t OffsetBound = llvm::hlsl::rootsig::computeRangeBound(Offset, Range.NumDescriptors); From 6a3c2ab5c54ff9894a95ed83239946576860f7f6 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 11 Sep 2025 14:29:41 -0700 Subject: [PATCH 134/143] formating --- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 26dcf6f6a6139..0bcb9418d7389 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -540,8 +540,7 @@ Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, // Samplers cannot be mixed with other resources in a descriptor table. if (HasSampler && HasOtherRangeType) - return make_error(OtherRangeType, - Location); + return make_error(OtherRangeType, Location); return Error::success(); } From c2d39ed47794d13a778b1887c1a4f5ddf9a9400e Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 17 Sep 2025 12:07:19 -0700 Subject: [PATCH 135/143] addressing comments from bogner --- .../Frontend/HLSL/RootSignatureMetadata.cpp | 32 ++++++------------- ...escriptorTable-AllValidFlagCombinations.ll | 2 +- 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 8510c7efc61d7..6363de2eb4133 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -545,25 +545,13 @@ Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD, Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, uint32_t Location) { - bool HasSampler = false; - bool HasOtherRangeType = false; - dxil::ResourceClass OtherRangeType; - + dxil::ResourceClass CurrRC = dxil::ResourceClass::Sampler; for (const mcdxbc::DescriptorRange &Range : Table.Ranges) { - dxil::ResourceClass RangeType = - static_cast(Range.RangeType); - - if (RangeType == dxil::ResourceClass::Sampler) { - HasSampler = true; - } else { - HasOtherRangeType = true; - OtherRangeType = RangeType; - } + if (Range.RangeType == dxil::ResourceClass::Sampler && + CurrRC != dxil::ResourceClass::Sampler) + return make_error(CurrRC, Location); + CurrRC = Range.RangeType; } - - // Samplers cannot be mixed with other resources in a descriptor table. - if (HasSampler && HasOtherRangeType) - return make_error(OtherRangeType, Location); return Error::success(); } @@ -573,31 +561,29 @@ Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, for (const mcdxbc::DescriptorRange &Range : Table.Ranges) { // Validation of NumDescriptors should have happened by this point. - if (Range.NumDescriptors <= 0) + if (Range.NumDescriptors == 0) continue; - const dxil::ResourceClass &RangeType = - static_cast(Range.RangeType); if (Range.OffsetInDescriptorsFromTableStart != DescriptorTableOffsetAppend) Offset = Range.OffsetInDescriptorsFromTableStart; if (!verifyNoOverflowedOffset(Offset)) return make_error( - RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace); const uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound( Range.BaseShaderRegister, Range.NumDescriptors); if (!verifyNoOverflowedOffset(RangeBound)) return make_error( - RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace); const uint64_t OffsetBound = llvm::hlsl::rootsig::computeRangeBound(Offset, Range.NumDescriptors); if (!verifyNoOverflowedOffset(OffsetBound)) return make_error( - RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace); Offset = updateOngoingOffset(Offset, Range.NumDescriptors, Range.OffsetInDescriptorsFromTableStart); } diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll index 81e2baeca72fb..850b9a7f36ff3 100644 --- a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll +++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-DescriptorTable-AllValidFlagCombinations.ll @@ -13,7 +13,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" } !2 = !{ ptr @main, !3, i32 2 } ; function, root signature !3 = !{ !5, !21 } ; list of root signature elements !5 = !{ !"DescriptorTable", i32 0, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20 } -!21 = !{ !"DescriptorTable", i32 0,!6, !8, !9 } +!21 = !{ !"DescriptorTable", i32 0, !6, !8, !9 } ; typedef enum D3D12_DESCRIPTOR_RANGE_FLAGS { ; NONE = 0, From 592dc62e45a7eb7657ec8870ad5668c5902b20c1 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 17 Sep 2025 16:10:21 -0700 Subject: [PATCH 136/143] adding edge case test --- .../rootsignature-validation-appending-limits.ll | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-appending-limits.ll diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-appending-limits.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-appending-limits.ll new file mode 100644 index 0000000000000..cf5b4e3182f26 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-appending-limits.ll @@ -0,0 +1,16 @@ +; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s +; This is correct according to DXC: https://hlsl.godbolt.org/z/KPG5o74KE +; CHECK-NOT: error: + +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 0, i32 4294967294, i32 0} +!5 = !{!"UAV", i32 1, i32 0, i32 0, i32 -1, i32 0} From f3253edd1544607cc859a1d3560b36e6dd5c36d8 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 17 Sep 2025 16:13:01 -0700 Subject: [PATCH 137/143] changing frontend check back to what it was --- clang/lib/Sema/SemaHLSL.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 8263025f7cb65..0af38472b0fec 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1394,8 +1394,9 @@ bool SemaHLSL::handleRootSignatureElements( Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound; } - Offset = llvm::hlsl::rootsig::updateOngoingOffset( - Offset, Clause->NumDescriptors, Clause->Offset); + Offset = RangeBound == llvm::hlsl::rootsig::NumDescriptorsUnbounded + ? uint32_t(RangeBound) + : uint32_t(RangeBound + 1); // Compute the register bounds and track resource binding uint32_t LowerBound(Clause->Reg.Number); From d442625f9b5b597f6daf4af630ac4d482c9d37ab Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Thu, 18 Sep 2025 11:32:18 -0700 Subject: [PATCH 138/143] removing some copies --- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 6363de2eb4133..03f0e979a1c3b 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -60,8 +60,9 @@ static std::optional extractMdStringValue(MDNode *Node, template && std::is_same_v, uint32_t>>> -Expected extractEnumValue(MDNode *Node, unsigned int OpId, StringRef ErrText, - llvm::function_ref VerifyFn) { +static Expected +extractEnumValue(MDNode *Node, unsigned int OpId, StringRef ErrText, + llvm::function_ref VerifyFn) { if (std::optional Val = extractMdIntValue(Node, OpId)) { if (!VerifyFn(*Val)) return make_error>(ErrText, *Val); @@ -543,8 +544,9 @@ Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD, llvm_unreachable("Unhandled RootSignatureElementKind enum."); } -Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, - uint32_t Location) { +static Error +validateDescriptorTableSamplerMixin(const mcdxbc::DescriptorTable &Table, + uint32_t Location) { dxil::ResourceClass CurrRC = dxil::ResourceClass::Sampler; for (const mcdxbc::DescriptorRange &Range : Table.Ranges) { if (Range.RangeType == dxil::ResourceClass::Sampler && @@ -555,8 +557,9 @@ Error validateDescriptorTableSamplerMixin(mcdxbc::DescriptorTable Table, return Error::success(); } -Error validateDescriptorTableRegisterOverflow(mcdxbc::DescriptorTable Table, - uint32_t Location) { +static Error +validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table, + uint32_t Location) { uint64_t Offset = 0; for (const mcdxbc::DescriptorRange &Range : Table.Ranges) { From f785d25629b239f40c3fc25ae2cf7d6932255596 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 19 Sep 2025 20:26:12 -0700 Subject: [PATCH 139/143] adding same test as frontend --- ...validation-fail-appending-limits-multiples.ll | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-limits-multiples.ll diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-limits-multiples.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-limits-multiples.ll new file mode 100644 index 0000000000000..b047f28cc29cb --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-limits-multiples.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: Cannot append range with implicit lower bound after an unbounded range CBV(register=2, space=0). + +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, !6} +!4 = !{!"CBV", i32 1, i32 0, i32 0, i32 4294967294, i32 0} +!5 = !{!"CBV", i32 1, i32 1, i32 0, i32 -1, i32 0} +!6 = !{!"CBV", i32 1, i32 2, i32 0, i32 -1, i32 0} From eefd22c7477e8eb5d9b5007be17b007f9889304e Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Wed, 24 Sep 2025 04:44:45 +0000 Subject: [PATCH 140/143] refactor to copy frontend --- .../Frontend/HLSL/RootSignatureValidations.h | 2 -- .../Frontend/HLSL/RootSignatureMetadata.cpp | 25 +++++++++++-------- .../HLSL/RootSignatureValidations.cpp | 9 ------- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 5e86fe23e5ec8..ea96094b18300 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -41,8 +41,6 @@ LLVM_ABI bool verifyLOD(float LOD); LLVM_ABI bool verifyBoundOffset(uint32_t Offset); LLVM_ABI bool verifyNoOverflowedOffset(uint64_t Offset); LLVM_ABI uint64_t computeRangeBound(uint32_t Offset, uint32_t Size); -LLVM_ABI uint64_t updateOngoingOffset(uint64_t CurOffset, - uint64_t NumDescriptors, uint64_t Offset); } // namespace rootsig } // namespace hlsl diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 03f0e979a1c3b..4466a861de509 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -561,19 +561,13 @@ static Error validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table, uint32_t Location) { uint64_t Offset = 0; - + bool IsPrevUnbound = false; + for (const mcdxbc::DescriptorRange &Range : Table.Ranges) { // Validation of NumDescriptors should have happened by this point. if (Range.NumDescriptors == 0) continue; - if (Range.OffsetInDescriptorsFromTableStart != DescriptorTableOffsetAppend) - Offset = Range.OffsetInDescriptorsFromTableStart; - - if (!verifyNoOverflowedOffset(Offset)) - return make_error( - Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace); - const uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound( Range.BaseShaderRegister, Range.NumDescriptors); @@ -581,14 +575,25 @@ validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table, return make_error( Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + bool IsAppending = + Range.OffsetInDescriptorsFromTableStart == DescriptorTableOffsetAppend; + if (!IsAppending) + Offset = Range.OffsetInDescriptorsFromTableStart; + + if (IsPrevUnbound && IsAppending) + return make_error( + Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace); + const uint64_t OffsetBound = llvm::hlsl::rootsig::computeRangeBound(Offset, Range.NumDescriptors); if (!verifyNoOverflowedOffset(OffsetBound)) return make_error( Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace); - Offset = updateOngoingOffset(Offset, Range.NumDescriptors, - Range.OffsetInDescriptorsFromTableStart); + + Offset = OffsetBound + 1; + IsPrevUnbound = + Range.NumDescriptors == llvm::hlsl::rootsig::NumDescriptorsUnbounded; } return Error::success(); diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp index 09f136d0a1c2f..cffec5875a8fe 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp @@ -140,15 +140,6 @@ uint64_t computeRangeBound(uint32_t Offset, uint32_t Size) { return uint64_t(Offset) + uint64_t(Size) - 1; } - -uint64_t updateOngoingOffset(uint64_t CurOffset, uint64_t NumDescriptors, - uint64_t Offset) { - // Append to the current offset if DescriptorTableOffsetAppend is set, - // otherwise calculate the new Offset. - return Offset == DescriptorTableOffsetAppend ? CurOffset + NumDescriptors - : Offset + NumDescriptors; -} - } // namespace rootsig } // namespace hlsl } // namespace llvm From b188df1759ede217b1b692d9bbab47bd1398ecc0 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Wed, 24 Sep 2025 05:39:14 +0000 Subject: [PATCH 141/143] fix test and change error message --- .../llvm/Frontend/HLSL/RootSignatureMetadata.h | 18 ++++++++---------- .../Frontend/HLSL/RootSignatureMetadata.cpp | 6 +++--- ...lidation-fail-appending-limits-multiples.ll | 2 +- ...ature-validation-fail-appending-overflow.ll | 2 +- ...ignature-validation-fail-offset-overflow.ll | 2 +- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index 4e2a074e37421..201ef91586fb8 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -48,22 +48,20 @@ class RootSignatureValidationError } }; -class OffsetOverflowError : public ErrorInfo { +class OffsetAppendAfterOverflow : public ErrorInfo { public: static char ID; dxil::ResourceClass Type; uint32_t Register; uint32_t Space; - OffsetOverflowError(dxil::ResourceClass Type, uint32_t Register, + OffsetAppendAfterOverflow(dxil::ResourceClass 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(Type) << "(register=" << Register - << ", space=" << Space << ")."; + OS << "Range " << getResourceClassName(Type) << "(register=" << Register + << ", space=" << Space << ") " << "cannot be appended after an unbounded range "; } std::error_code convertToErrorCode() const override { @@ -93,20 +91,20 @@ class ShaderRegisterOverflowError } }; -class DescriptorRangeOverflowError - : public ErrorInfo { +class OffsetOverflowError + : public ErrorInfo { public: static char ID; dxil::ResourceClass Type; uint32_t Register; uint32_t Space; - DescriptorRangeOverflowError(dxil::ResourceClass Type, uint32_t Register, + OffsetOverflowError(dxil::ResourceClass Type, uint32_t Register, uint32_t Space) : Type(Type), Register(Register), Space(Space) {} void log(raw_ostream &OS) const override { - OS << "Overflow for descriptor range: " << getResourceClassName(Type) + OS << "Offset overflow for descriptor range: " << getResourceClassName(Type) << "(register=" << Register << ", space=" << Space << ")."; } diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 4466a861de509..0a888a6043940 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -30,7 +30,7 @@ char InvalidRSMetadataValue::ID; char TableSamplerMixinError::ID; char ShaderRegisterOverflowError::ID; char OffsetOverflowError::ID; -char DescriptorRangeOverflowError::ID; +char OffsetAppendAfterOverflow::ID; template char RootSignatureValidationError::ID; @@ -581,14 +581,14 @@ validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table, Offset = Range.OffsetInDescriptorsFromTableStart; if (IsPrevUnbound && IsAppending) - return make_error( + return make_error( Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace); const uint64_t OffsetBound = llvm::hlsl::rootsig::computeRangeBound(Offset, Range.NumDescriptors); if (!verifyNoOverflowedOffset(OffsetBound)) - return make_error( + return make_error( Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace); Offset = OffsetBound + 1; diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-limits-multiples.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-limits-multiples.ll index b047f28cc29cb..e51f15a1d3fc2 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-limits-multiples.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-limits-multiples.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 append range with implicit lower bound after an unbounded range CBV(register=2, space=0). +; CHECK: error: Offset overflow for descriptor range: CBV(register=2, space=0). define void @CSMain() "hlsl.shader"="compute" { entry: 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 f0009c80c28c1..f08e1778b8ba0 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 append range with implicit lower bound after an unbounded range UAV(register=0, space=0). +; CHECK: error: Range UAV(register=0, space=0) cannot be appended after an unbounded range define void @CSMain() "hlsl.shader"="compute" { entry: diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll index 06177ee3c261e..6e56949562740 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-overflow.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-offset-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: Overflow for descriptor range: UAV(register=0, space=0) +; CHECK: error: Offset overflow for descriptor range: UAV(register=0, space=0). define void @CSMain() "hlsl.shader"="compute" { entry: From dabb9cd67fefe6a7f427cec9fa5890aa97741aa3 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 24 Sep 2025 10:46:49 -0700 Subject: [PATCH 142/143] format --- .../include/llvm/Frontend/HLSL/RootSignatureMetadata.h | 10 +++++----- .../rootsignature-validation-appending-limits.ll | 2 +- ...rootsignature-validation-fail-appending-overflow.ll | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h index 201ef91586fb8..bfcbf728d415c 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h @@ -56,12 +56,13 @@ class OffsetAppendAfterOverflow : public ErrorInfo { uint32_t Space; OffsetAppendAfterOverflow(dxil::ResourceClass Type, uint32_t Register, - uint32_t Space) + uint32_t Space) : Type(Type), Register(Register), Space(Space) {} void log(raw_ostream &OS) const override { OS << "Range " << getResourceClassName(Type) << "(register=" << Register - << ", space=" << Space << ") " << "cannot be appended after an unbounded range "; + << ", space=" << Space << ") " + << "cannot be appended after an unbounded range "; } std::error_code convertToErrorCode() const override { @@ -91,8 +92,7 @@ class ShaderRegisterOverflowError } }; -class OffsetOverflowError - : public ErrorInfo { +class OffsetOverflowError : public ErrorInfo { public: static char ID; dxil::ResourceClass Type; @@ -100,7 +100,7 @@ class OffsetOverflowError uint32_t Space; OffsetOverflowError(dxil::ResourceClass Type, uint32_t Register, - uint32_t Space) + uint32_t Space) : Type(Type), Register(Register), Space(Space) {} void log(raw_ostream &OS) const override { diff --git a/llvm/test/CodeGen/DirectX/rootsignature-validation-appending-limits.ll b/llvm/test/CodeGen/DirectX/rootsignature-validation-appending-limits.ll index cf5b4e3182f26..7fa42e9697898 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-appending-limits.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-appending-limits.ll @@ -1,5 +1,5 @@ ; RUN: opt -S -passes='dxil-post-optimization-validation' -mtriple=dxil-pc-shadermodel6.6-compute %s 2>&1 | FileCheck %s -; This is correct according to DXC: https://hlsl.godbolt.org/z/KPG5o74KE +; A descriptor range can be placed at UINT_MAX, matching DXC's behaviour ; CHECK-NOT: error: define void @CSMain() "hlsl.shader"="compute" { 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 f08e1778b8ba0..1bc97d9ae2091 100644 --- a/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-overflow.ll +++ b/llvm/test/CodeGen/DirectX/rootsignature-validation-fail-appending-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 -; This test check if a resource is implicitly overflowing. That means, it is appending a resource after an unbounded range. +; This test checks if a resource is implicitly overflowing. That means, it is appending a resource after an unbounded range. ; CHECK: error: Range UAV(register=0, space=0) cannot be appended after an unbounded range From 0e08ceabec713156be11b74946ac0470e07388e8 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 24 Sep 2025 10:53:57 -0700 Subject: [PATCH 143/143] format --- llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp index 0a888a6043940..1fff71928e055 100644 --- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp +++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp @@ -562,7 +562,6 @@ validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table, uint32_t Location) { uint64_t Offset = 0; bool IsPrevUnbound = false; - for (const mcdxbc::DescriptorRange &Range : Table.Ranges) { // Validation of NumDescriptors should have happened by this point. if (Range.NumDescriptors == 0)