12
12
// ===----------------------------------------------------------------------===//
13
13
#include " DXILRootSignature.h"
14
14
#include " DirectX.h"
15
+ #include " llvm/ADT/STLForwardCompat.h"
15
16
#include " llvm/ADT/StringSwitch.h"
16
17
#include " llvm/ADT/Twine.h"
17
18
#include " llvm/Analysis/DXILMetadataAnalysis.h"
27
28
#include " llvm/Support/Error.h"
28
29
#include " llvm/Support/ErrorHandling.h"
29
30
#include " llvm/Support/raw_ostream.h"
31
+ #include < cstddef>
30
32
#include < cstdint>
31
33
#include < optional>
32
34
#include < utility>
@@ -166,6 +168,88 @@ static bool parseRootDescriptors(LLVMContext *Ctx,
166
168
return false ;
167
169
}
168
170
171
+ static bool parseDescriptorRange (LLVMContext *Ctx,
172
+ mcdxbc::RootSignatureDesc &RSD,
173
+ mcdxbc::DescriptorTable &Table,
174
+ MDNode *RangeDescriptorNode) {
175
+
176
+ if (RangeDescriptorNode->getNumOperands () != 6 )
177
+ return reportError (Ctx, " Invalid format for Descriptor Range" );
178
+
179
+ dxbc::RTS0::v2::DescriptorRange Range;
180
+
181
+ std::optional<StringRef> ElementText =
182
+ extractMdStringValue (RangeDescriptorNode, 0 );
183
+
184
+ if (!ElementText.has_value ())
185
+ return reportError (Ctx, " Descriptor Range, first element is not a string." );
186
+
187
+ Range.RangeType =
188
+ StringSwitch<uint32_t >(*ElementText)
189
+ .Case (" CBV" , llvm::to_underlying (dxbc::DescriptorRangeType::CBV))
190
+ .Case (" SRV" , llvm::to_underlying (dxbc::DescriptorRangeType::SRV))
191
+ .Case (" UAV" , llvm::to_underlying (dxbc::DescriptorRangeType::UAV))
192
+ .Case (" Sampler" ,
193
+ llvm::to_underlying (dxbc::DescriptorRangeType::Sampler))
194
+ .Default (llvm::to_underlying (dxbc::DescriptorRangeType::ERROR));
195
+
196
+ if (std::optional<uint32_t > Val = extractMdIntValue (RangeDescriptorNode, 1 ))
197
+ Range.NumDescriptors = *Val;
198
+ else
199
+ return reportError (Ctx, " Invalid value for Number of Descriptor in Range" );
200
+
201
+ if (std::optional<uint32_t > Val = extractMdIntValue (RangeDescriptorNode, 2 ))
202
+ Range.BaseShaderRegister = *Val;
203
+ else
204
+ return reportError (Ctx, " Invalid value for BaseShaderRegister" );
205
+
206
+ if (std::optional<uint32_t > Val = extractMdIntValue (RangeDescriptorNode, 3 ))
207
+ Range.RegisterSpace = *Val;
208
+ else
209
+ return reportError (Ctx, " Invalid value for RegisterSpace" );
210
+
211
+ if (std::optional<uint32_t > Val = extractMdIntValue (RangeDescriptorNode, 4 ))
212
+ Range.OffsetInDescriptorsFromTableStart = *Val;
213
+ else
214
+ return reportError (Ctx,
215
+ " Invalid value for OffsetInDescriptorsFromTableStart" );
216
+
217
+ if (std::optional<uint32_t > Val = extractMdIntValue (RangeDescriptorNode, 5 ))
218
+ Range.Flags = *Val;
219
+ else
220
+ return reportError (Ctx, " Invalid value for Descriptor Range Flags" );
221
+
222
+ Table.Ranges .push_back (Range);
223
+ return false ;
224
+ }
225
+
226
+ static bool parseDescriptorTable (LLVMContext *Ctx,
227
+ mcdxbc::RootSignatureDesc &RSD,
228
+ MDNode *DescriptorTableNode) {
229
+ if (DescriptorTableNode->getNumOperands () < 2 )
230
+ return reportError (Ctx, " Invalid format for Descriptor Table" );
231
+
232
+ dxbc::RTS0::v1::RootParameterHeader Header;
233
+ if (std::optional<uint32_t > Val = extractMdIntValue (DescriptorTableNode, 1 ))
234
+ Header.ShaderVisibility = *Val;
235
+ else
236
+ return reportError (Ctx, " Invalid value for ShaderVisibility" );
237
+
238
+ mcdxbc::DescriptorTable Table;
239
+
240
+ for (unsigned int I = 2 ; I < DescriptorTableNode->getNumOperands (); I++) {
241
+ MDNode *Element = dyn_cast<MDNode>(DescriptorTableNode->getOperand (I));
242
+ if (Element == nullptr )
243
+ return reportError (Ctx, " Missing Root Element Metadata Node." );
244
+
245
+ if (parseDescriptorRange (Ctx, RSD, Table, Element))
246
+ return true ;
247
+ }
248
+
249
+ RSD.ParametersContainer .addParameter (Header, Table);
250
+ return false ;
251
+ }
252
+
169
253
static bool parseRootSignatureElement (LLVMContext *Ctx,
170
254
mcdxbc::RootSignatureDesc &RSD,
171
255
MDNode *Element) {
@@ -180,6 +264,7 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
180
264
.Case (" RootCBV" , RootSignatureElementKind::RootDescriptors)
181
265
.Case (" RootSRV" , RootSignatureElementKind::RootDescriptors)
182
266
.Case (" RootUAV" , RootSignatureElementKind::RootDescriptors)
267
+ .Case (" DescriptorTable" , RootSignatureElementKind::DescriptorTable)
183
268
.Default (RootSignatureElementKind::Error);
184
269
185
270
switch (ElementKind) {
@@ -190,6 +275,8 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
190
275
return parseRootConstants (Ctx, RSD, Element);
191
276
case RootSignatureElementKind::RootDescriptors:
192
277
return parseRootDescriptors (Ctx, RSD, Element);
278
+ case RootSignatureElementKind::DescriptorTable:
279
+ return parseDescriptorTable (Ctx, RSD, Element);
193
280
case RootSignatureElementKind::Error:
194
281
return reportError (Ctx, " Invalid Root Signature Element: " +
195
282
ElementText->getString ());
@@ -230,6 +317,79 @@ static bool verifyRegisterSpace(uint32_t RegisterSpace) {
230
317
231
318
static bool verifyDescriptorFlag (uint32_t Flags) { return (Flags & ~0xE ) == 0 ; }
232
319
320
+ static bool verifyRangeType (uint32_t Type) {
321
+ switch (Type) {
322
+ case llvm::to_underlying (dxbc::DescriptorRangeType::CBV):
323
+ case llvm::to_underlying (dxbc::DescriptorRangeType::SRV):
324
+ case llvm::to_underlying (dxbc::DescriptorRangeType::UAV):
325
+ case llvm::to_underlying (dxbc::DescriptorRangeType::Sampler):
326
+ return true ;
327
+ };
328
+
329
+ return false ;
330
+ }
331
+
332
+ static bool verifyDescriptorRangeFlag (uint32_t Version, uint32_t Type,
333
+ uint32_t Flags) {
334
+ if (Version == 1 &&
335
+ Type == llvm::to_underlying (dxbc::DescriptorRangeType::Sampler))
336
+ return Flags == 0 ;
337
+
338
+ if (Version == 2 &&
339
+ Type == llvm::to_underlying (dxbc::DescriptorRangeType::Sampler)) {
340
+ switch (Flags) {
341
+ case 0 :
342
+ case llvm::to_underlying (dxbc::DescriptorRangeFlag::DATA_VOLATILE):
343
+ case llvm::to_underlying (
344
+ dxbc::DescriptorRangeFlag::
345
+ DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS):
346
+ return true ;
347
+ }
348
+ return false ;
349
+ }
350
+
351
+ if (Version == 1 &&
352
+ Type != llvm::to_underlying (dxbc::DescriptorRangeType::Sampler))
353
+ return Flags ==
354
+ llvm::to_underlying (dxbc::DescriptorRangeFlag::DESCRIPTORS_VOLATILE);
355
+
356
+ if (Version == 2 &&
357
+ Type != llvm::to_underlying (dxbc::DescriptorRangeType::Sampler)) {
358
+ switch (Flags) {
359
+ case 0 :
360
+ case llvm::to_underlying (dxbc::DescriptorRangeFlag::DESCRIPTORS_VOLATILE):
361
+ case llvm::to_underlying (dxbc::DescriptorRangeFlag::DATA_VOLATILE):
362
+ case llvm::to_underlying (dxbc::DescriptorRangeFlag::DATA_STATIC):
363
+ case llvm::to_underlying (
364
+ dxbc::DescriptorRangeFlag::DATA_STATIC_WHILE_SET_AT_EXECUTE):
365
+ case llvm::to_underlying (
366
+ dxbc::DescriptorRangeFlag::
367
+ DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS):
368
+ case llvm::to_underlying (dxbc::DescriptorRangeFlag::DESCRIPTORS_VOLATILE) |
369
+ llvm::to_underlying (dxbc::DescriptorRangeFlag::DATA_VOLATILE):
370
+ case llvm::to_underlying (dxbc::DescriptorRangeFlag::DESCRIPTORS_VOLATILE) |
371
+ llvm::to_underlying (
372
+ dxbc::DescriptorRangeFlag::DATA_STATIC_WHILE_SET_AT_EXECUTE):
373
+ case llvm::to_underlying (
374
+ dxbc::DescriptorRangeFlag::
375
+ DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS) |
376
+ llvm::to_underlying (dxbc::DescriptorRangeFlag::DATA_VOLATILE):
377
+ case llvm::to_underlying (
378
+ dxbc::DescriptorRangeFlag::
379
+ DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS) |
380
+ llvm::to_underlying (dxbc::DescriptorRangeFlag::DATA_STATIC):
381
+ case llvm::to_underlying (
382
+ dxbc::DescriptorRangeFlag::
383
+ DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS) |
384
+ llvm::to_underlying (
385
+ dxbc::DescriptorRangeFlag::DATA_STATIC_WHILE_SET_AT_EXECUTE):
386
+ return true ;
387
+ }
388
+ return false ;
389
+ }
390
+ return false ;
391
+ }
392
+
233
393
static bool validate (LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
234
394
235
395
if (!verifyVersion (RSD.Version )) {
@@ -268,6 +428,22 @@ static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
268
428
}
269
429
break ;
270
430
}
431
+ case llvm::to_underlying (dxbc::RootParameterType::DescriptorTable): {
432
+ const mcdxbc::DescriptorTable &Table =
433
+ RSD.ParametersContainer .getDescriptorTable (Info.Location );
434
+ for (const dxbc::RTS0::v2::DescriptorRange &Range : Table) {
435
+ if (!verifyRangeType (Range.RangeType ))
436
+ return reportValueError (Ctx, " RangeType" , Range.RangeType );
437
+
438
+ if (!verifyRegisterSpace (Range.RegisterSpace ))
439
+ return reportValueError (Ctx, " RegisterSpace" , Range.RegisterSpace );
440
+
441
+ if (!verifyDescriptorRangeFlag (RSD.Version , Range.RangeType ,
442
+ Range.Flags ))
443
+ return reportValueError (Ctx, " DescriptorFlag" , Range.Flags );
444
+ }
445
+ break ;
446
+ }
271
447
}
272
448
}
273
449
0 commit comments