27
27
#include " llvm/Support/Error.h"
28
28
#include " llvm/Support/ErrorHandling.h"
29
29
#include " llvm/Support/raw_ostream.h"
30
+ #include < cmath>
30
31
#include < cstdint>
31
32
#include < optional>
32
33
#include < utility>
@@ -55,6 +56,13 @@ static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
55
56
return std::nullopt;
56
57
}
57
58
59
+ static std::optional<float > extractMdFloatValue (MDNode *Node,
60
+ unsigned int OpId) {
61
+ if (auto *CI = mdconst::dyn_extract<ConstantFP>(Node->getOperand (OpId).get ()))
62
+ return CI->getValueAPF ().convertToFloat ();
63
+ return std::nullopt;
64
+ }
65
+
58
66
static std::optional<StringRef> extractMdStringValue (MDNode *Node,
59
67
unsigned int OpId) {
60
68
MDString *NodeText = dyn_cast<MDString>(Node->getOperand (OpId));
@@ -261,6 +269,81 @@ static bool parseDescriptorTable(LLVMContext *Ctx,
261
269
return false ;
262
270
}
263
271
272
+ static bool parseStaticSampler (LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
273
+ MDNode *StaticSamplerNode) {
274
+ if (StaticSamplerNode->getNumOperands () != 14 )
275
+ return reportError (Ctx, " Invalid format for Static Sampler" );
276
+
277
+ dxbc::RTS0::v1::StaticSampler Sampler;
278
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 1 ))
279
+ Sampler.Filter = *Val;
280
+ else
281
+ return reportError (Ctx, " Invalid value for Filter" );
282
+
283
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 2 ))
284
+ Sampler.AddressU = *Val;
285
+ else
286
+ return reportError (Ctx, " Invalid value for AddressU" );
287
+
288
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 3 ))
289
+ Sampler.AddressV = *Val;
290
+ else
291
+ return reportError (Ctx, " Invalid value for AddressV" );
292
+
293
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 4 ))
294
+ Sampler.AddressW = *Val;
295
+ else
296
+ return reportError (Ctx, " Invalid value for AddressW" );
297
+
298
+ if (std::optional<float > Val = extractMdFloatValue (StaticSamplerNode, 5 ))
299
+ Sampler.MipLODBias = *Val;
300
+ else
301
+ return reportError (Ctx, " Invalid value for MipLODBias" );
302
+
303
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 6 ))
304
+ Sampler.MaxAnisotropy = *Val;
305
+ else
306
+ return reportError (Ctx, " Invalid value for MaxAnisotropy" );
307
+
308
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 7 ))
309
+ Sampler.ComparisonFunc = *Val;
310
+ else
311
+ return reportError (Ctx, " Invalid value for ComparisonFunc " );
312
+
313
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 8 ))
314
+ Sampler.BorderColor = *Val;
315
+ else
316
+ return reportError (Ctx, " Invalid value for ComparisonFunc " );
317
+
318
+ if (std::optional<float > Val = extractMdFloatValue (StaticSamplerNode, 9 ))
319
+ Sampler.MinLOD = *Val;
320
+ else
321
+ return reportError (Ctx, " Invalid value for MinLOD" );
322
+
323
+ if (std::optional<float > Val = extractMdFloatValue (StaticSamplerNode, 10 ))
324
+ Sampler.MaxLOD = *Val;
325
+ else
326
+ return reportError (Ctx, " Invalid value for MaxLOD" );
327
+
328
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 11 ))
329
+ Sampler.ShaderRegister = *Val;
330
+ else
331
+ return reportError (Ctx, " Invalid value for ShaderRegister" );
332
+
333
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 12 ))
334
+ Sampler.RegisterSpace = *Val;
335
+ else
336
+ return reportError (Ctx, " Invalid value for RegisterSpace" );
337
+
338
+ if (std::optional<uint32_t > Val = extractMdIntValue (StaticSamplerNode, 13 ))
339
+ Sampler.ShaderVisibility = *Val;
340
+ else
341
+ return reportError (Ctx, " Invalid value for ShaderVisibility" );
342
+
343
+ RSD.StaticSamplers .push_back (Sampler);
344
+ return false ;
345
+ }
346
+
264
347
static bool parseRootSignatureElement (LLVMContext *Ctx,
265
348
mcdxbc::RootSignatureDesc &RSD,
266
349
MDNode *Element) {
@@ -276,6 +359,7 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
276
359
.Case (" RootSRV" , RootSignatureElementKind::SRV)
277
360
.Case (" RootUAV" , RootSignatureElementKind::UAV)
278
361
.Case (" DescriptorTable" , RootSignatureElementKind::DescriptorTable)
362
+ .Case (" StaticSampler" , RootSignatureElementKind::StaticSamplers)
279
363
.Default (RootSignatureElementKind::Error);
280
364
281
365
switch (ElementKind) {
@@ -290,6 +374,8 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
290
374
return parseRootDescriptors (Ctx, RSD, Element, ElementKind);
291
375
case RootSignatureElementKind::DescriptorTable:
292
376
return parseDescriptorTable (Ctx, RSD, Element);
377
+ case RootSignatureElementKind::StaticSamplers:
378
+ return parseStaticSampler (Ctx, RSD, Element);
293
379
case RootSignatureElementKind::Error:
294
380
return reportError (Ctx, " Invalid Root Signature Element: " + *ElementText);
295
381
}
@@ -406,6 +492,58 @@ static bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
406
492
return (Flags & ~Mask) == FlagT::NONE;
407
493
}
408
494
495
+ static bool verifySamplerFilter (uint32_t Value) {
496
+ switch (Value) {
497
+ #define STATIC_SAMPLER_FILTER (Num, Val ) \
498
+ case llvm::to_underlying (dxbc::StaticSamplerFilter::Val):
499
+ #include " llvm/BinaryFormat/DXContainerConstants.def"
500
+ return true ;
501
+ }
502
+ return false ;
503
+ }
504
+
505
+ // Values allowed here:
506
+ // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode#syntax
507
+ static bool verifyAddress (uint32_t Address) {
508
+ switch (Address) {
509
+ #define TEXTURE_ADDRESS_MODE (Num, Val ) \
510
+ case llvm::to_underlying (dxbc::TextureAddressMode::Val):
511
+ #include " llvm/BinaryFormat/DXContainerConstants.def"
512
+ return true ;
513
+ }
514
+ return false ;
515
+ }
516
+
517
+ static bool verifyMipLODBias (float MipLODBias) {
518
+ return MipLODBias >= -16 .f && MipLODBias <= 15 .99f ;
519
+ }
520
+
521
+ static bool verifyMaxAnisotropy (uint32_t MaxAnisotropy) {
522
+ return MaxAnisotropy <= 16u ;
523
+ }
524
+
525
+ static bool verifyComparisonFunc (uint32_t ComparisonFunc) {
526
+ switch (ComparisonFunc) {
527
+ #define COMPARISON_FUNCTION (Num, Val ) \
528
+ case llvm::to_underlying (dxbc::SamplersComparisonFunction::Val):
529
+ #include " llvm/BinaryFormat/DXContainerConstants.def"
530
+ return true ;
531
+ }
532
+ return false ;
533
+ }
534
+
535
+ static bool verifyBorderColor (uint32_t BorderColor) {
536
+ switch (BorderColor) {
537
+ #define STATIC_BORDER_COLOR (Num, Val ) \
538
+ case llvm::to_underlying (dxbc::SamplersBorderColor::Val):
539
+ #include " llvm/BinaryFormat/DXContainerConstants.def"
540
+ return true ;
541
+ }
542
+ return false ;
543
+ }
544
+
545
+ static bool verifyLOD (float LOD) { return !std::isnan (LOD); }
546
+
409
547
static bool validate (LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
410
548
411
549
if (!verifyVersion (RSD.Version )) {
@@ -463,6 +601,48 @@ static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
463
601
}
464
602
}
465
603
604
+ for (const dxbc::RTS0::v1::StaticSampler &Sampler : RSD.StaticSamplers ) {
605
+ if (!verifySamplerFilter (Sampler.Filter ))
606
+ return reportValueError (Ctx, " Filter" , Sampler.Filter );
607
+
608
+ if (!verifyAddress (Sampler.AddressU ))
609
+ return reportValueError (Ctx, " AddressU" , Sampler.AddressU );
610
+
611
+ if (!verifyAddress (Sampler.AddressV ))
612
+ return reportValueError (Ctx, " AddressV" , Sampler.AddressV );
613
+
614
+ if (!verifyAddress (Sampler.AddressW ))
615
+ return reportValueError (Ctx, " AddressW" , Sampler.AddressW );
616
+
617
+ if (!verifyMipLODBias (Sampler.MipLODBias ))
618
+ return reportValueError (Ctx, " MipLODBias" , Sampler.MipLODBias );
619
+
620
+ if (!verifyMaxAnisotropy (Sampler.MaxAnisotropy ))
621
+ return reportValueError (Ctx, " MaxAnisotropy" , Sampler.MaxAnisotropy );
622
+
623
+ if (!verifyComparisonFunc (Sampler.ComparisonFunc ))
624
+ return reportValueError (Ctx, " ComparisonFunc" , Sampler.ComparisonFunc );
625
+
626
+ if (!verifyBorderColor (Sampler.BorderColor ))
627
+ return reportValueError (Ctx, " BorderColor" , Sampler.BorderColor );
628
+
629
+ if (!verifyLOD (Sampler.MinLOD ))
630
+ return reportValueError (Ctx, " MinLOD" , Sampler.MinLOD );
631
+
632
+ if (!verifyLOD (Sampler.MaxLOD ))
633
+ return reportValueError (Ctx, " MaxLOD" , Sampler.MaxLOD );
634
+
635
+ if (!verifyRegisterValue (Sampler.ShaderRegister ))
636
+ return reportValueError (Ctx, " ShaderRegister" , Sampler.ShaderRegister );
637
+
638
+ if (!verifyRegisterSpace (Sampler.RegisterSpace ))
639
+ return reportValueError (Ctx, " RegisterSpace" , Sampler.RegisterSpace );
640
+
641
+ if (!dxbc::isValidShaderVisibility (Sampler.ShaderVisibility ))
642
+ return reportValueError (Ctx, " ShaderVisibility" ,
643
+ Sampler.ShaderVisibility );
644
+ }
645
+
466
646
return false ;
467
647
}
468
648
@@ -542,6 +722,9 @@ analyzeModule(Module &M) {
542
722
// offset will always equal to the header size.
543
723
RSD.RootParameterOffset = sizeof (dxbc::RTS0::v1::RootSignatureHeader);
544
724
725
+ // static sampler offset is calculated when writting dxcontainer.
726
+ RSD.StaticSamplersOffset = 0u ;
727
+
545
728
if (parse (Ctx, RSD, RootElementListNode) || validate (Ctx, RSD)) {
546
729
return RSDMap;
547
730
}
0 commit comments