1010#include " DXILRootSignature.h"
1111#include " DXILShaderFlags.h"
1212#include " DirectX.h"
13+ #include " llvm/ADT/STLForwardCompat.h"
1314#include " llvm/ADT/SmallString.h"
15+ #include " llvm/ADT/iterator_range.h"
1416#include " llvm/Analysis/DXILMetadataAnalysis.h"
1517#include " llvm/Analysis/DXILResource.h"
18+ #include " llvm/BinaryFormat/DXContainer.h"
1619#include " llvm/IR/DiagnosticInfo.h"
1720#include " llvm/IR/Instructions.h"
1821#include " llvm/IR/IntrinsicsDirectX.h"
@@ -123,6 +126,70 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) {
123126 }
124127}
125128
129+ static uint32_t parameterToRangeType (uint32_t Type) {
130+ switch (Type) {
131+ case llvm::to_underlying (dxbc::RootParameterType::CBV):
132+ return llvm::to_underlying (dxbc::DescriptorRangeType::CBV);
133+ break ;
134+ case llvm::to_underlying (dxbc::RootParameterType::SRV):
135+ return llvm::to_underlying (dxbc::DescriptorRangeType::SRV);
136+ break ;
137+ case llvm::to_underlying (dxbc::RootParameterType::UAV):
138+ return llvm::to_underlying (dxbc::DescriptorRangeType::UAV);
139+ break ;
140+ default :
141+ llvm_unreachable (" Root Parameter Type has no Range Type equivalent" );
142+ }
143+ }
144+
145+ static RootSignatureBindingValidation initRsBindingValdation (const mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) {
146+
147+ RootSignatureBindingValidation Validation;
148+
149+ for (size_t I = 0 ; I < RSD.ParametersContainer .size (); I++) {
150+ const auto &[Type, Loc] =
151+ RSD.ParametersContainer .getTypeAndLocForParameter (I);
152+
153+ const auto &Header = RSD.ParametersContainer .getHeader (I);
154+ if (Header.ShaderVisibility !=
155+ llvm::to_underlying (dxbc::ShaderVisibility::All) &&
156+ Header.ShaderVisibility != llvm::to_underlying (Visibility))
157+ continue ;
158+
159+ switch (Type) {
160+ case llvm::to_underlying (dxbc::RootParameterType::SRV):
161+ case llvm::to_underlying (dxbc::RootParameterType::UAV):
162+ case llvm::to_underlying (dxbc::RootParameterType::CBV): {
163+ dxbc::RTS0::v2::RootDescriptor Desc =
164+ RSD.ParametersContainer .getRootDescriptor (Loc);
165+
166+ llvm::dxil::ResourceInfo::ResourceBinding Binding;
167+ Binding.LowerBound = Desc.ShaderRegister ;
168+ Binding.Space = Desc.RegisterSpace ;
169+ Binding.Size = 1 ;
170+
171+ Validation.addBinding (parameterToRangeType (Type), Binding);
172+ break ;
173+ }
174+ case llvm::to_underlying (dxbc::RootParameterType::DescriptorTable): {
175+ const mcdxbc::DescriptorTable &Table =
176+ RSD.ParametersContainer .getDescriptorTable (Loc);
177+
178+ for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges ) {
179+ llvm::dxil::ResourceInfo::ResourceBinding Binding;
180+ Binding.LowerBound = Range.BaseShaderRegister ;
181+ Binding.Space = Range.RegisterSpace ;
182+ Binding.Size = Range.NumDescriptors ;
183+ Validation.addBinding (Range.RangeType , Binding);
184+ }
185+ break ;
186+ }
187+ }
188+ }
189+
190+ return Validation;
191+ }
192+
126193std::optional<mcdxbc::RootSignatureDesc>
127194getRootSignature (RootSignatureBindingInfo &RSBI,
128195 dxil::ModuleMetadataInfo &MMI) {
@@ -135,6 +202,27 @@ getRootSignature(RootSignatureBindingInfo &RSBI,
135202 return RootSigDesc;
136203}
137204
205+ static void reportUnboundRegisters (
206+ Module &M,
207+ const std::vector<llvm::dxil::ResourceInfo::ResourceBinding> &Bindings,
208+ iterator_range<SmallVector<dxil::ResourceInfo>::iterator> &Resources) {
209+ for (auto Res = Resources.begin (), End = Resources.end (); Res != End; Res++) {
210+ bool Bound = false ;
211+ ResourceInfo::ResourceBinding ResBinding = Res->getBinding ();
212+ for (const auto &Binding : Bindings) {
213+ if (ResBinding.Space == Binding.Space &&
214+ ResBinding.LowerBound >= Binding.LowerBound &&
215+ ResBinding.LowerBound < Binding.LowerBound + Binding.Size ) {
216+ Bound = true ;
217+ break ;
218+ }
219+ }
220+ if (!Bound) {
221+ reportRegNotBound (M, Res->getName (), Res->getBinding ());
222+ }
223+ }
224+ }
225+
138226static void reportErrors (Module &M, DXILResourceMap &DRM,
139227 DXILResourceBindingInfo &DRBI,
140228 RootSignatureBindingInfo &RSBI,
@@ -150,72 +238,21 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
150238
151239 if (auto RSD = getRootSignature (RSBI, MMI)) {
152240
153- RootSignatureBindingValidation Validation;
154- Validation.addRsBindingInfo (*RSD, tripleToVisibility (MMI.ShaderProfile ));
155-
156- for (const ResourceInfo &CBuf : DRM.cbuffers ()) {
157- ResourceInfo::ResourceBinding Binding = CBuf.getBinding ();
158- if (!Validation.checkCRegBinding (Binding))
159- reportRegNotBound (M, " cbuffer" , Binding);
160- }
161-
162- for (const ResourceInfo &SRV : DRM.srvs ()) {
163- ResourceInfo::ResourceBinding Binding = SRV.getBinding ();
164- if (!Validation.checkTRegBinding (Binding))
165- reportRegNotBound (M, " srv" , Binding);
166- }
241+ RootSignatureBindingValidation Validation = initRsBindingValdation (*RSD, tripleToVisibility (MMI.ShaderProfile ));
167242
168- for (const ResourceInfo &UAV : DRM.uavs ()) {
169- ResourceInfo::ResourceBinding Binding = UAV.getBinding ();
170- if (!Validation.checkURegBinding (Binding))
171- reportRegNotBound (M, " uav" , Binding);
172- }
243+ auto Cbufs = DRM.cbuffers ();
244+ auto SRVs = DRM.srvs ();
245+ auto UAVs = DRM.uavs ();
246+ auto Samplers = DRM.samplers ();
173247
174- for (const ResourceInfo &Sampler : DRM.samplers ()) {
175- ResourceInfo::ResourceBinding Binding = Sampler.getBinding ();
176- if (!Validation.checkSamplerBinding (Binding))
177- reportRegNotBound (M, " sampler" , Binding);
178- }
248+ reportUnboundRegisters (M, Validation.getBindingsOfType (dxbc::DescriptorRangeType::CBV), Cbufs);
249+ reportUnboundRegisters (M, Validation.getBindingsOfType (dxbc::DescriptorRangeType::UAV), UAVs);
250+ reportUnboundRegisters (M, Validation.getBindingsOfType (dxbc::DescriptorRangeType::Sampler), Samplers);
251+ reportUnboundRegisters (M, Validation.getBindingsOfType (dxbc::DescriptorRangeType::SRV), SRVs);
179252 }
180253}
181254} // namespace
182255
183- void RootSignatureBindingValidation::addRsBindingInfo (
184- mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) {
185- for (size_t I = 0 ; I < RSD.ParametersContainer .size (); I++) {
186- const auto &[Type, Loc] =
187- RSD.ParametersContainer .getTypeAndLocForParameter (I);
188-
189- const auto &Header = RSD.ParametersContainer .getHeader (I);
190- switch (Type) {
191- case llvm::to_underlying (dxbc::RootParameterType::SRV):
192- case llvm::to_underlying (dxbc::RootParameterType::UAV):
193- case llvm::to_underlying (dxbc::RootParameterType::CBV): {
194- dxbc::RTS0::v2::RootDescriptor Desc =
195- RSD.ParametersContainer .getRootDescriptor (Loc);
196-
197- if (Header.ShaderVisibility ==
198- llvm::to_underlying (dxbc::ShaderVisibility::All) ||
199- Header.ShaderVisibility == llvm::to_underlying (Visibility))
200- addRange (Desc, Type);
201- break ;
202- }
203- case llvm::to_underlying (dxbc::RootParameterType::DescriptorTable): {
204- const mcdxbc::DescriptorTable &Table =
205- RSD.ParametersContainer .getDescriptorTable (Loc);
206-
207- for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges ) {
208- if (Header.ShaderVisibility ==
209- llvm::to_underlying (dxbc::ShaderVisibility::All) ||
210- Header.ShaderVisibility == llvm::to_underlying (Visibility))
211- addRange (Range);
212- }
213- break ;
214- }
215- }
216- }
217- }
218-
219256PreservedAnalyses
220257DXILPostOptimizationValidation::run (Module &M, ModuleAnalysisManager &MAM) {
221258 DXILResourceMap &DRM = MAM.getResult <DXILResourceAnalysis>(M);
@@ -252,8 +289,8 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
252289 void getAnalysisUsage (llvm::AnalysisUsage &AU) const override {
253290 AU.addRequired <DXILResourceWrapperPass>();
254291 AU.addRequired <DXILResourceBindingWrapperPass>();
255- AU.addRequired <RootSignatureAnalysisWrapper>();
256292 AU.addRequired <DXILMetadataAnalysisWrapperPass>();
293+ AU.addRequired <RootSignatureAnalysisWrapper>();
257294 AU.addPreserved <DXILResourceWrapperPass>();
258295 AU.addPreserved <DXILResourceBindingWrapperPass>();
259296 AU.addPreserved <DXILMetadataAnalysisWrapperPass>();
@@ -269,6 +306,7 @@ INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
269306INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass)
270307INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
271308INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
309+ INITIALIZE_PASS_DEPENDENCY(RootSignatureAnalysisWrapper)
272310INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
273311 " DXIL Post Optimization Validation" , false , false )
274312
0 commit comments