@@ -84,9 +84,57 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
8484 }
8585 }
8686}
87- uint64_t combine_uint32_to_uint64 (uint32_t high, uint32_t low) {
88- return (static_cast <uint64_t >(high) << 32 ) | low;
87+
88+ static void reportRegNotBound (Module &M, Twine Type,
89+ ResourceInfo::ResourceBinding Binding) {
90+ SmallString<128 > Message;
91+ raw_svector_ostream OS (Message);
92+ OS << " register " << Type << " (space=" << Binding.Space
93+ << " , register=" << Binding.LowerBound << " )"
94+ << " is not defined in Root Signature" ;
95+ M.getContext ().diagnose (DiagnosticInfoGeneric (Message));
96+ }
97+
98+ static dxbc::ShaderVisibility
99+ tripleToVisibility (llvm::Triple::EnvironmentType ET) {
100+ assert ((ET == Triple::Pixel || ET == Triple::Vertex ||
101+ ET == Triple::Geometry || ET == Triple::Hull ||
102+ ET == Triple::Domain || ET == Triple::Mesh ||
103+ ET == Triple::Compute) &&
104+ " Invalid Triple to shader stage conversion" );
105+
106+ switch (ET) {
107+ case Triple::Pixel:
108+ return dxbc::ShaderVisibility::Pixel;
109+ case Triple::Vertex:
110+ return dxbc::ShaderVisibility::Vertex;
111+ case Triple::Geometry:
112+ return dxbc::ShaderVisibility::Geometry;
113+ case Triple::Hull:
114+ return dxbc::ShaderVisibility::Hull;
115+ case Triple::Domain:
116+ return dxbc::ShaderVisibility::Domain;
117+ case Triple::Mesh:
118+ return dxbc::ShaderVisibility::Mesh;
119+ case Triple::Compute:
120+ return dxbc::ShaderVisibility::All;
121+ default :
122+ llvm_unreachable (" Invalid triple to shader stage conversion" );
89123 }
124+ }
125+
126+ std::optional<mcdxbc::RootSignatureDesc>
127+ getRootSignature (RootSignatureBindingInfo &RSBI,
128+ dxil::ModuleMetadataInfo &MMI) {
129+ if (MMI.EntryPropertyVec .size () == 0 )
130+ return std::nullopt ;
131+ std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
132+ RSBI.getDescForFunction (MMI.EntryPropertyVec [0 ].Entry );
133+ if (!RootSigDesc)
134+ return std::nullopt ;
135+ return RootSigDesc;
136+ }
137+
90138static void reportErrors (Module &M, DXILResourceMap &DRM,
91139 DXILResourceBindingInfo &DRBI,
92140 RootSignatureBindingInfo &RSBI,
@@ -99,57 +147,95 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
99147
100148 assert (!DRBI.hasImplicitBinding () && " implicit bindings should be handled in "
101149 " DXILResourceImplicitBinding pass" );
102- // Assuming this is used to validate only the root signature assigned to the
103- // entry function.
104- // Start test stuff
105- if (MMI.EntryPropertyVec .size () == 0 )
106- return ;
107150
108- std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
109- RSBI.getDescForFunction (MMI.EntryPropertyVec [0 ].Entry );
110- if (!RootSigDesc)
111- return ;
151+ if (auto RSD = getRootSignature (RSBI, MMI)) {
152+
153+ RootSignatureBindingValidation Validation;
154+ Validation.addRsBindingInfo (*RSD, tripleToVisibility (MMI.ShaderProfile ));
155+
156+ for (const auto &CBuf : DRM.cbuffers ()) {
157+ ResourceInfo::ResourceBinding Binding = CBuf.getBinding ();
158+ if (!Validation.checkCregBinding (Binding))
159+ reportRegNotBound (M, " cbuffer" , Binding);
160+ }
161+
162+ for (const auto &CBuf : DRM.srvs ()) {
163+ ResourceInfo::ResourceBinding Binding = CBuf.getBinding ();
164+ if (!Validation.checkTRegBinding (Binding))
165+ reportRegNotBound (M, " srv" , Binding);
166+ }
112167
113- using MapT = llvm::IntervalMap<uint64_t , llvm::dxil::ResourceInfo::ResourceBinding, sizeof (llvm::dxil::ResourceInfo::ResourceBinding), llvm::IntervalMapInfo<uint64_t >>;
114- MapT::Allocator Allocator;
115- MapT BindingsMap (Allocator);
116- auto RSD = *RootSigDesc;
117- for (size_t I = 0 ; I < RSD.ParametersContainer .size (); I++) {
168+ for (const auto &CBuf : DRM.uavs ()) {
169+ ResourceInfo::ResourceBinding Binding = CBuf.getBinding ();
170+ if (!Validation.checkURegBinding (Binding))
171+ reportRegNotBound (M, " uav" , Binding);
172+ }
173+ }
174+ }
175+ } // namespace
176+
177+ void RootSignatureBindingValidation::addRsBindingInfo (
178+ mcdxbc::RootSignatureDesc &RSD, dxbc::ShaderVisibility Visibility) {
179+ for (size_t I = 0 ; I < RSD.ParametersContainer .size (); I++) {
118180 const auto &[Type, Loc] =
119- RootSigDesc->ParametersContainer .getTypeAndLocForParameter (I);
181+ RSD.ParametersContainer .getTypeAndLocForParameter (I);
182+
183+ const auto &Header = RSD.ParametersContainer .getHeader (I);
120184 switch (Type) {
121- case llvm::to_underlying (dxbc::RootParameterType::CBV):{
185+ case llvm::to_underlying (dxbc::RootParameterType::SRV):
186+ case llvm::to_underlying (dxbc::RootParameterType::UAV):
187+ case llvm::to_underlying (dxbc::RootParameterType::CBV): {
122188 dxbc::RTS0::v2::RootDescriptor Desc =
123- RootSigDesc-> ParametersContainer .getRootDescriptor (Loc);
189+ RSD. ParametersContainer .getRootDescriptor (Loc);
124190
125- llvm::dxil::ResourceInfo::ResourceBinding Binding;
126- Binding.LowerBound = Desc.ShaderRegister ;
127- Binding.Space = Desc.RegisterSpace ;
128- Binding.Size = 1 ;
191+ if (Header.ShaderVisibility ==
192+ llvm::to_underlying (dxbc::ShaderVisibility::All) ||
193+ Header.ShaderVisibility == llvm::to_underlying (Visibility))
194+ addRange (Desc, Type);
195+ break ;
196+ }
197+ case llvm::to_underlying (dxbc::RootParameterType::DescriptorTable): {
198+ const mcdxbc::DescriptorTable &Table =
199+ RSD.ParametersContainer .getDescriptorTable (Loc);
129200
130- BindingsMap.insert (combine_uint32_to_uint64 (Binding.Space , Binding.LowerBound ), combine_uint32_to_uint64 (Binding.Space , Binding.LowerBound + Binding.Size -1 ), Binding);
201+ for (const dxbc::RTS0::v2::DescriptorRange &Range : Table.Ranges ) {
202+ if (Range.RangeType ==
203+ llvm::to_underlying (dxbc::DescriptorRangeType::Sampler))
204+ continue ;
205+
206+ if (Header.ShaderVisibility ==
207+ llvm::to_underlying (dxbc::ShaderVisibility::All) ||
208+ Header.ShaderVisibility == llvm::to_underlying (Visibility))
209+ addRange (Range);
210+ }
131211 break ;
132212 }
133- // case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):{
134- // mcdxbc::DescriptorTable Table =
135- // RootSigDesc->ParametersContainer.getDescriptorTable(Loc);
136- // for (const dxbc::RTS0::v2::DescriptorRange &Range : Table){
137- // Range.
138- // }
139-
140- // break;
141- // }
142213 }
143-
144214 }
215+ }
145216
146- for (const auto &CBuf : DRM.cbuffers ()) {
147- auto Binding = CBuf.getBinding ();
148- if (!BindingsMap.overlaps (combine_uint32_to_uint64 (Binding.Space , Binding.LowerBound ), combine_uint32_to_uint64 (Binding.Space , Binding.LowerBound + Binding.Size -1 )))
149- auto X = 1 ;
150- }
217+ bool RootSignatureBindingValidation::checkCregBinding (
218+ ResourceInfo::ResourceBinding Binding) {
219+ return CRegBindingsMap.overlaps (
220+ combineUint32ToUint64 (Binding.Space , Binding.LowerBound ),
221+ combineUint32ToUint64 (Binding.Space ,
222+ Binding.LowerBound + Binding.Size - 1 ));
223+ }
224+
225+ bool RootSignatureBindingValidation::checkTRegBinding (
226+ ResourceInfo::ResourceBinding Binding) {
227+ return TRegBindingsMap.overlaps (
228+ combineUint32ToUint64 (Binding.Space , Binding.LowerBound ),
229+ combineUint32ToUint64 (Binding.Space , Binding.LowerBound + Binding.Size ));
230+ }
231+
232+ bool RootSignatureBindingValidation::checkURegBinding (
233+ ResourceInfo::ResourceBinding Binding) {
234+ return URegBindingsMap.overlaps (
235+ combineUint32ToUint64 (Binding.Space , Binding.LowerBound ),
236+ combineUint32ToUint64 (Binding.Space ,
237+ Binding.LowerBound + Binding.Size - 1 ));
151238}
152- } // namespace
153239
154240PreservedAnalyses
155241DXILPostOptimizationValidation::run (Module &M, ModuleAnalysisManager &MAM) {
0 commit comments