1818#include " llvm/IR/IntrinsicsDirectX.h"
1919#include " llvm/IR/Module.h"
2020#include " llvm/InitializePasses.h"
21+ #include " llvm/Support/DXILABI.h"
2122
2223#define DEBUG_TYPE " dxil-post-optimization-validation"
2324
2425using namespace llvm ;
2526using namespace llvm ::dxil;
2627
27- namespace {
28- static ResourceClass RangeToResourceClass (uint32_t RangeType) {
28+ static ResourceClass toResourceClass (dxbc::DescriptorRangeType RangeType) {
2929 using namespace dxbc ;
30- switch (static_cast <DescriptorRangeType>( RangeType) ) {
30+ switch (RangeType) {
3131 case DescriptorRangeType::SRV:
3232 return ResourceClass::SRV;
3333 case DescriptorRangeType::UAV:
@@ -39,20 +39,21 @@ static ResourceClass RangeToResourceClass(uint32_t RangeType) {
3939 }
4040}
4141
42- ResourceClass ParameterToResourceClass ( uint32_t Type) {
42+ static ResourceClass toResourceClass (dxbc::RootParameterType Type) {
4343 using namespace dxbc ;
4444 switch (Type) {
45- case llvm::to_underlying ( RootParameterType::Constants32Bit) :
45+ case RootParameterType::Constants32Bit:
4646 return ResourceClass::CBuffer;
47- case llvm::to_underlying ( RootParameterType::SRV) :
47+ case RootParameterType::SRV:
4848 return ResourceClass::SRV;
49- case llvm::to_underlying ( RootParameterType::UAV) :
49+ case RootParameterType::UAV:
5050 return ResourceClass::UAV;
51- case llvm::to_underlying ( RootParameterType::CBV) :
51+ case RootParameterType::CBV:
5252 return ResourceClass::CBuffer;
53- default :
54- llvm_unreachable ( " Unknown RootParameterType " ) ;
53+ case dxbc::RootParameterType::DescriptorTable :
54+ break ;
5555 }
56+ llvm_unreachable (" Unconvertible RootParameterType" );
5657}
5758
5859static void reportInvalidDirection (Module &M, DXILResourceMap &DRM) {
@@ -143,12 +144,6 @@ reportRegNotBound(Module &M, ResourceClass Class,
143144
144145static dxbc::ShaderVisibility
145146tripleToVisibility (llvm::Triple::EnvironmentType ET) {
146- assert ((ET == Triple::Pixel || ET == Triple::Vertex ||
147- ET == Triple::Geometry || ET == Triple::Hull ||
148- ET == Triple::Domain || ET == Triple::Mesh ||
149- ET == Triple::Compute) &&
150- " Invalid Triple to shader stage conversion" );
151-
152147 switch (ET) {
153148 case Triple::Pixel:
154149 return dxbc::ShaderVisibility::Pixel;
@@ -169,73 +164,103 @@ tripleToVisibility(llvm::Triple::EnvironmentType ET) {
169164 }
170165}
171166
172- static void trackRootSigDescBinding (hlsl::BindingInfoBuilder &Builder,
173- const mcdxbc::RootSignatureDesc &RSD,
174- dxbc::ShaderVisibility Visibility) {
175- for (size_t I = 0 ; I < RSD.ParametersContainer .size (); I++) {
176- const auto &[Type, Loc] =
177- RSD.ParametersContainer .getTypeAndLocForParameter (I);
178-
179- const auto &Header = RSD.ParametersContainer .getHeader (I);
180- if (Header.ShaderVisibility !=
181- llvm::to_underlying (dxbc::ShaderVisibility::All) &&
182- Header.ShaderVisibility != llvm::to_underlying (Visibility))
167+ static void validateRootSignature (Module &M,
168+ const mcdxbc::RootSignatureDesc &RSD,
169+ dxil::ModuleMetadataInfo &MMI,
170+ DXILResourceMap &DRM) {
171+
172+ hlsl::BindingInfoBuilder Builder;
173+ dxbc::ShaderVisibility Visibility = tripleToVisibility (MMI.ShaderProfile );
174+ SmallVector<char > IDs;
175+ for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer ) {
176+ dxbc::ShaderVisibility ParamVisibility =
177+ static_cast <dxbc::ShaderVisibility>(ParamInfo.Header .ShaderVisibility );
178+ if (ParamVisibility != dxbc::ShaderVisibility::All &&
179+ ParamVisibility != Visibility)
183180 continue ;
184-
185- switch (Type) {
186- case llvm::to_underlying (dxbc::RootParameterType::Constants32Bit): {
181+ dxbc::RootParameterType ParamType =
182+ static_cast <dxbc::RootParameterType>(ParamInfo.Header .ParameterType );
183+ switch (ParamType) {
184+ case dxbc::RootParameterType::Constants32Bit: {
187185 dxbc::RTS0::v1::RootConstants Const =
188- RSD.ParametersContainer .getConstant (Loc );
186+ RSD.ParametersContainer .getConstant (ParamInfo. Location );
189187 Builder.trackBinding (dxil::ResourceClass::CBuffer, Const.RegisterSpace ,
190- Const.ShaderRegister ,
191- Const. ShaderRegister + Const. Num32BitValues , &Const );
188+ Const.ShaderRegister , Const. ShaderRegister ,
189+ &IDs. emplace_back () );
192190 break ;
193191 }
194192
195- case llvm::to_underlying ( dxbc::RootParameterType::SRV) :
196- case llvm::to_underlying ( dxbc::RootParameterType::UAV) :
197- case llvm::to_underlying ( dxbc::RootParameterType::CBV) : {
193+ case dxbc::RootParameterType::SRV:
194+ case dxbc::RootParameterType::UAV:
195+ case dxbc::RootParameterType::CBV: {
198196 dxbc::RTS0::v2::RootDescriptor Desc =
199- RSD.ParametersContainer .getRootDescriptor (Loc);
200- Builder.trackBinding (ParameterToResourceClass (Type), Desc.RegisterSpace ,
201- Desc.ShaderRegister , Desc.ShaderRegister , &Desc);
197+ RSD.ParametersContainer .getRootDescriptor (ParamInfo.Location );
198+ Builder.trackBinding (toResourceClass (static_cast <dxbc::RootParameterType>(
199+ ParamInfo.Header .ParameterType )),
200+ Desc.RegisterSpace , Desc.ShaderRegister ,
201+ Desc.ShaderRegister , &IDs.emplace_back ());
202202
203203 break ;
204204 }
205- case llvm::to_underlying ( dxbc::RootParameterType::DescriptorTable) : {
205+ case dxbc::RootParameterType::DescriptorTable: {
206206 const mcdxbc::DescriptorTable &Table =
207- RSD.ParametersContainer .getDescriptorTable (Loc );
207+ RSD.ParametersContainer .getDescriptorTable (ParamInfo. Location );
208208
209209 for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges ) {
210- Builder.trackBinding (RangeToResourceClass (Range.RangeType ),
211- Range.RegisterSpace , Range.BaseShaderRegister ,
212- Range.NumDescriptors == ~0U
213- ? Range.NumDescriptors
214- : Range.BaseShaderRegister +
215- Range.NumDescriptors ,
216- &Range);
210+ uint32_t UpperBound =
211+ Range.NumDescriptors == ~0U
212+ ? Range.BaseShaderRegister
213+ : Range.BaseShaderRegister + Range.NumDescriptors - 1 ;
214+ Builder.trackBinding (
215+ toResourceClass (
216+ static_cast <dxbc::DescriptorRangeType>(Range.RangeType )),
217+ Range.RegisterSpace , Range.BaseShaderRegister , UpperBound,
218+ &IDs.emplace_back ());
217219 }
218220 break ;
219221 }
220222 }
221223 }
222224
223- for (auto &S : RSD.StaticSamplers ) {
225+ for (const dxbc::RTS0::v1::StaticSampler &S : RSD.StaticSamplers )
224226 Builder.trackBinding (dxil::ResourceClass::Sampler, S.RegisterSpace ,
225- S.ShaderRegister , S.ShaderRegister , &S);
226- }
227+ S.ShaderRegister , S.ShaderRegister ,
228+ &IDs.emplace_back ());
229+ bool HasOverlap = false ;
230+ hlsl::BindingInfo Info = Builder.calculateBindingInfo (
231+ [&M, &HasOverlap](const llvm::hlsl::BindingInfoBuilder &Builder,
232+ const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) {
233+ HasOverlap = true ;
234+ const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping =
235+ Builder.findOverlapping (ReportedBinding);
236+ reportOverlappingRegisters (M, ReportedBinding, Overlaping);
237+ });
238+ // Next checks require that the root signature definition is valid.
239+ if (!HasOverlap) {
240+ for (const auto &ResList :
241+ {std::make_pair (ResourceClass::SRV, DRM.srvs ()),
242+ std::make_pair (ResourceClass::UAV, DRM.uavs ()),
243+ std::make_pair (ResourceClass::CBuffer, DRM.cbuffers ()),
244+ std::make_pair (ResourceClass::Sampler, DRM.samplers ())}) {
245+ for (auto Res : ResList.second ) {
246+ llvm::dxil::ResourceInfo::ResourceBinding ResBinding =
247+ Res.getBinding ();
248+ llvm::hlsl::BindingInfo::BindingRange ResRange (
249+ ResBinding.LowerBound , ResBinding.LowerBound + ResBinding.Size );
250+
251+ if (!Info.isBound (ResList.first , ResBinding.Space , ResRange))
252+ reportRegNotBound (M, ResList.first , ResBinding);
253+ }
254+ }
255+ }
227256}
228257
229- std::optional< mcdxbc::RootSignatureDesc>
258+ static mcdxbc::RootSignatureDesc *
230259getRootSignature (RootSignatureBindingInfo &RSBI,
231260 dxil::ModuleMetadataInfo &MMI) {
232261 if (MMI.EntryPropertyVec .size () == 0 )
233- return std::nullopt ;
234- std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
235- RSBI.getDescForFunction (MMI.EntryPropertyVec [0 ].Entry );
236- if (!RootSigDesc)
237- return std::nullopt ;
238- return RootSigDesc;
262+ return nullptr ;
263+ return RSBI.getDescForFunction (MMI.EntryPropertyVec [0 ].Entry );
239264}
240265
241266static void reportErrors (Module &M, DXILResourceMap &DRM,
@@ -251,42 +276,9 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
251276 assert (!DRBI.hasImplicitBinding () && " implicit bindings should be handled in "
252277 " DXILResourceImplicitBinding pass" );
253278
254- if (auto RSD = getRootSignature (RSBI, MMI)) {
255-
256- hlsl::BindingInfoBuilder Builder;
257- dxbc::ShaderVisibility Visibility = tripleToVisibility (MMI.ShaderProfile );
258- trackRootSigDescBinding (Builder, *RSD, Visibility);
259- bool HasOverlap = false ;
260- hlsl::BindingInfo Info = Builder.calculateBindingInfo (
261- [&M, &HasOverlap](
262- const llvm::hlsl::BindingInfoBuilder &Builder,
263- const llvm::hlsl::BindingInfoBuilder::Binding &ReportedBinding) {
264- HasOverlap = true ;
265- const llvm::hlsl::BindingInfoBuilder::Binding &Overlaping =
266- Builder.findOverlapping (ReportedBinding);
267- reportOverlappingRegisters (M, ReportedBinding, Overlaping);
268- });
269- // Next checks require that the root signature definition is valid.
270- if (!HasOverlap) {
271- for (const auto &ResList :
272- {std::make_pair (ResourceClass::SRV, DRM.srvs ()),
273- std::make_pair (ResourceClass::UAV, DRM.uavs ()),
274- std::make_pair (ResourceClass::CBuffer, DRM.cbuffers ()),
275- std::make_pair (ResourceClass::Sampler, DRM.samplers ())}) {
276- for (auto Res : ResList.second ) {
277- llvm::dxil::ResourceInfo::ResourceBinding ResBinding =
278- Res.getBinding ();
279- llvm::hlsl::BindingInfo::BindingRange ResRange (
280- ResBinding.LowerBound , ResBinding.LowerBound + ResBinding.Size );
281-
282- if (!Info.isBound (ResList.first , ResBinding.Space , ResRange))
283- reportRegNotBound (M, ResList.first , ResBinding);
284- }
285- }
286- }
287- }
279+ if (mcdxbc::RootSignatureDesc *RSD = getRootSignature (RSBI, MMI))
280+ validateRootSignature (M, *RSD, MMI, DRM);
288281}
289- } // namespace
290282
291283PreservedAnalyses
292284DXILPostOptimizationValidation::run (Module &M, ModuleAnalysisManager &MAM) {
0 commit comments