LLVM 22.0.0git
RootSignatureMetadata.cpp
Go to the documentation of this file.
1//===- RootSignatureMetadata.h - HLSL Root Signature helpers --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file This file implements a library for working with HLSL Root Signatures
10/// and their metadata representation.
11///
12//===----------------------------------------------------------------------===//
13
16#include "llvm/IR/IRBuilder.h"
17#include "llvm/IR/Metadata.h"
20
21using namespace llvm;
22
23namespace llvm {
24namespace hlsl {
25namespace rootsig {
26
28
29static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
30 unsigned int OpId) {
31 if (auto *CI =
32 mdconst::dyn_extract<ConstantInt>(Node->getOperand(OpId).get()))
33 return CI->getZExtValue();
34 return std::nullopt;
35}
36
37static std::optional<float> extractMdFloatValue(MDNode *Node,
38 unsigned int OpId) {
39 if (auto *CI = mdconst::dyn_extract<ConstantFP>(Node->getOperand(OpId).get()))
40 return CI->getValueAPF().convertToFloat();
41 return std::nullopt;
42}
43
44static std::optional<StringRef> extractMdStringValue(MDNode *Node,
45 unsigned int OpId) {
46 MDString *NodeText = dyn_cast<MDString>(Node->getOperand(OpId));
47 if (NodeText == nullptr)
48 return std::nullopt;
49 return NodeText->getString();
50}
51
52namespace {
53
54// We use the OverloadVisit with std::visit to ensure the compiler catches if a
55// new RootElement variant type is added but it's metadata generation isn't
56// handled.
57template <class... Ts> struct OverloadedVisit : Ts... {
58 using Ts::operator()...;
59};
60template <class... Ts> OverloadedVisit(Ts...) -> OverloadedVisit<Ts...>;
61
62struct FmtRange {
65 uint32_t Space;
66
67 FmtRange(const mcdxbc::DescriptorRange &Range)
68 : Type(Range.RangeType), Register(Range.BaseShaderRegister),
69 Space(Range.RegisterSpace) {}
70};
71
72raw_ostream &operator<<(llvm::raw_ostream &OS, const FmtRange &Range) {
73 OS << getResourceClassName(Range.Type) << "(register=" << Range.Register
74 << ", space=" << Range.Space << ")";
75 return OS;
76}
77
78struct FmtMDNode {
79 const MDNode *Node;
80
81 FmtMDNode(const MDNode *Node) : Node(Node) {}
82};
83
84raw_ostream &operator<<(llvm::raw_ostream &OS, FmtMDNode Fmt) {
85 Fmt.Node->printTree(OS);
86 return OS;
87}
88
89static Error makeRSError(const Twine &Msg) {
91}
92} // namespace
93
94template <typename T, typename = std::enable_if_t<
95 std::is_enum_v<T> &&
96 std::is_same_v<std::underlying_type_t<T>, uint32_t>>>
97static Expected<T>
98extractEnumValue(MDNode *Node, unsigned int OpId, StringRef ErrText,
99 llvm::function_ref<bool(uint32_t)> VerifyFn) {
100 if (std::optional<uint32_t> Val = extractMdIntValue(Node, OpId)) {
101 if (!VerifyFn(*Val))
102 return makeRSError(formatv("Invalid value for {0}: {1}", ErrText, Val));
103 return static_cast<T>(*Val);
104 }
105 return makeRSError(formatv("Invalid value for {0}:", ErrText));
106}
107
109 const auto Visitor = OverloadedVisit{
110 [this](const dxbc::RootFlags &Flags) -> MDNode * {
111 return BuildRootFlags(Flags);
112 },
113 [this](const RootConstants &Constants) -> MDNode * {
114 return BuildRootConstants(Constants);
115 },
116 [this](const RootDescriptor &Descriptor) -> MDNode * {
117 return BuildRootDescriptor(Descriptor);
118 },
119 [this](const DescriptorTableClause &Clause) -> MDNode * {
120 return BuildDescriptorTableClause(Clause);
121 },
122 [this](const DescriptorTable &Table) -> MDNode * {
123 return BuildDescriptorTable(Table);
124 },
125 [this](const StaticSampler &Sampler) -> MDNode * {
126 return BuildStaticSampler(Sampler);
127 },
128 };
129
130 for (const RootElement &Element : Elements) {
131 MDNode *ElementMD = std::visit(Visitor, Element);
132 assert(ElementMD != nullptr &&
133 "Root Element must be initialized and validated");
134 GeneratedMetadata.push_back(ElementMD);
135 }
136
137 return MDNode::get(Ctx, GeneratedMetadata);
138}
139
140MDNode *MetadataBuilder::BuildRootFlags(const dxbc::RootFlags &Flags) {
141 IRBuilder<> Builder(Ctx);
142 Metadata *Operands[] = {
143 MDString::get(Ctx, "RootFlags"),
144 ConstantAsMetadata::get(Builder.getInt32(to_underlying(Flags))),
145 };
146 return MDNode::get(Ctx, Operands);
147}
148
149MDNode *MetadataBuilder::BuildRootConstants(const RootConstants &Constants) {
150 IRBuilder<> Builder(Ctx);
151 Metadata *Operands[] = {
152 MDString::get(Ctx, "RootConstants"),
154 Builder.getInt32(to_underlying(Constants.Visibility))),
155 ConstantAsMetadata::get(Builder.getInt32(Constants.Reg.Number)),
156 ConstantAsMetadata::get(Builder.getInt32(Constants.Space)),
157 ConstantAsMetadata::get(Builder.getInt32(Constants.Num32BitConstants)),
158 };
159 return MDNode::get(Ctx, Operands);
160}
161
162MDNode *MetadataBuilder::BuildRootDescriptor(const RootDescriptor &Descriptor) {
163 IRBuilder<> Builder(Ctx);
164 StringRef ResName = dxil::getResourceClassName(Descriptor.Type);
165 assert(!ResName.empty() && "Provided an invalid Resource Class");
166 SmallString<7> Name({"Root", ResName});
167 Metadata *Operands[] = {
168 MDString::get(Ctx, Name),
170 Builder.getInt32(to_underlying(Descriptor.Visibility))),
171 ConstantAsMetadata::get(Builder.getInt32(Descriptor.Reg.Number)),
172 ConstantAsMetadata::get(Builder.getInt32(Descriptor.Space)),
174 Builder.getInt32(to_underlying(Descriptor.Flags))),
175 };
176 return MDNode::get(Ctx, Operands);
177}
178
179MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) {
180 IRBuilder<> Builder(Ctx);
181 SmallVector<Metadata *> TableOperands;
182 // Set the mandatory arguments
183 TableOperands.push_back(MDString::get(Ctx, "DescriptorTable"));
185 Builder.getInt32(to_underlying(Table.Visibility))));
186
187 // Remaining operands are references to the table's clauses. The in-memory
188 // representation of the Root Elements created from parsing will ensure that
189 // the previous N elements are the clauses for this table.
190 assert(Table.NumClauses <= GeneratedMetadata.size() &&
191 "Table expected all owned clauses to be generated already");
192 // So, add a refence to each clause to our operands
193 TableOperands.append(GeneratedMetadata.end() - Table.NumClauses,
194 GeneratedMetadata.end());
195 // Then, remove those clauses from the general list of Root Elements
196 GeneratedMetadata.pop_back_n(Table.NumClauses);
197
198 return MDNode::get(Ctx, TableOperands);
199}
200
201MDNode *MetadataBuilder::BuildDescriptorTableClause(
202 const DescriptorTableClause &Clause) {
203 IRBuilder<> Builder(Ctx);
204 StringRef ResName = dxil::getResourceClassName(Clause.Type);
205 assert(!ResName.empty() && "Provided an invalid Resource Class");
206 Metadata *Operands[] = {
207 MDString::get(Ctx, ResName),
208 ConstantAsMetadata::get(Builder.getInt32(Clause.NumDescriptors)),
209 ConstantAsMetadata::get(Builder.getInt32(Clause.Reg.Number)),
210 ConstantAsMetadata::get(Builder.getInt32(Clause.Space)),
211 ConstantAsMetadata::get(Builder.getInt32(Clause.Offset)),
212 ConstantAsMetadata::get(Builder.getInt32(to_underlying(Clause.Flags))),
213 };
214 return MDNode::get(Ctx, Operands);
215}
216
217MDNode *MetadataBuilder::BuildStaticSampler(const StaticSampler &Sampler) {
218 IRBuilder<> Builder(Ctx);
219 Metadata *Operands[] = {
220 MDString::get(Ctx, "StaticSampler"),
221 ConstantAsMetadata::get(Builder.getInt32(to_underlying(Sampler.Filter))),
223 Builder.getInt32(to_underlying(Sampler.AddressU))),
225 Builder.getInt32(to_underlying(Sampler.AddressV))),
227 Builder.getInt32(to_underlying(Sampler.AddressW))),
229 ConstantFP::get(Type::getFloatTy(Ctx), Sampler.MipLODBias)),
230 ConstantAsMetadata::get(Builder.getInt32(Sampler.MaxAnisotropy)),
232 Builder.getInt32(to_underlying(Sampler.CompFunc))),
234 Builder.getInt32(to_underlying(Sampler.BorderColor))),
236 ConstantFP::get(Type::getFloatTy(Ctx), Sampler.MinLOD)),
238 ConstantFP::get(Type::getFloatTy(Ctx), Sampler.MaxLOD)),
239 ConstantAsMetadata::get(Builder.getInt32(Sampler.Reg.Number)),
240 ConstantAsMetadata::get(Builder.getInt32(Sampler.Space)),
242 Builder.getInt32(to_underlying(Sampler.Visibility))),
243 ConstantAsMetadata::get(Builder.getInt32(to_underlying(Sampler.Flags))),
244 };
245 return MDNode::get(Ctx, Operands);
246}
247
248Error MetadataParser::parseRootFlags(mcdxbc::RootSignatureDesc &RSD,
249 MDNode *RootFlagNode) {
250 if (RootFlagNode->getNumOperands() != 2)
251 return makeRSError("Invalid format for RootFlags Element");
252
253 if (std::optional<uint32_t> Val = extractMdIntValue(RootFlagNode, 1))
254 RSD.Flags = *Val;
255 else
256 return makeRSError("Invalid value for RootFlag");
257
258 return Error::success();
259}
260
261Error MetadataParser::parseRootConstants(mcdxbc::RootSignatureDesc &RSD,
262 MDNode *RootConstantNode) {
263 if (RootConstantNode->getNumOperands() != 5)
264 return makeRSError("Invalid format for RootConstants Element");
265
266 Expected<dxbc::ShaderVisibility> Visibility =
268 "ShaderVisibility",
270 if (auto E = Visibility.takeError())
271 return Error(std::move(E));
272
273 mcdxbc::RootConstants Constants;
274 if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 2))
275 Constants.ShaderRegister = *Val;
276 else
277 return makeRSError("Invalid value for ShaderRegister");
278
279 if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 3))
280 Constants.RegisterSpace = *Val;
281 else
282 return makeRSError("Invalid value for RegisterSpace");
283
284 if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 4))
285 Constants.Num32BitValues = *Val;
286 else
287 return makeRSError("Invalid value for Num32BitValues");
288
289 RSD.ParametersContainer.addParameter(dxbc::RootParameterType::Constants32Bit,
290 *Visibility, Constants);
291
292 return Error::success();
293}
294
295Error MetadataParser::parseRootDescriptors(
296 mcdxbc::RootSignatureDesc &RSD, MDNode *RootDescriptorNode,
297 RootSignatureElementKind ElementKind) {
298 assert((ElementKind == RootSignatureElementKind::SRV ||
299 ElementKind == RootSignatureElementKind::UAV ||
300 ElementKind == RootSignatureElementKind::CBV) &&
301 "parseRootDescriptors should only be called with RootDescriptor "
302 "element kind.");
303 if (RootDescriptorNode->getNumOperands() != 5)
304 return makeRSError("Invalid format for Root Descriptor Element");
305
307 switch (ElementKind) {
309 Type = dxbc::RootParameterType::SRV;
310 break;
312 Type = dxbc::RootParameterType::UAV;
313 break;
315 Type = dxbc::RootParameterType::CBV;
316 break;
317 default:
318 llvm_unreachable("invalid Root Descriptor kind");
319 break;
320 }
321
322 Expected<dxbc::ShaderVisibility> Visibility =
323 extractEnumValue<dxbc::ShaderVisibility>(RootDescriptorNode, 1,
324 "ShaderVisibility",
326 if (auto E = Visibility.takeError())
327 return Error(std::move(E));
328
329 mcdxbc::RootDescriptor Descriptor;
330 if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 2))
331 Descriptor.ShaderRegister = *Val;
332 else
333 return makeRSError("Invalid value for ShaderRegister");
334
335 if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 3))
336 Descriptor.RegisterSpace = *Val;
337 else
338 return makeRSError("Invalid value for RegisterSpace");
339
340 if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 4))
341 Descriptor.Flags = *Val;
342 else
343 return makeRSError("Invalid value for Root Descriptor Flags");
344
345 RSD.ParametersContainer.addParameter(Type, *Visibility, Descriptor);
346 return Error::success();
347}
348
349Error MetadataParser::parseDescriptorRange(mcdxbc::DescriptorTable &Table,
350 MDNode *RangeDescriptorNode) {
351 if (RangeDescriptorNode->getNumOperands() != 6)
352 return makeRSError("Invalid format for Descriptor Range");
353
354 mcdxbc::DescriptorRange Range;
355
356 std::optional<StringRef> ElementText =
357 extractMdStringValue(RangeDescriptorNode, 0);
358
359 if (!ElementText.has_value())
360 return makeRSError("Invalid format for Descriptor Range");
361
362 if (*ElementText == "CBV")
364 else if (*ElementText == "SRV")
366 else if (*ElementText == "UAV")
368 else if (*ElementText == "Sampler")
370 else
371 return makeRSError(formatv("Invalid Descriptor Range type.\n{0}",
372 FmtMDNode{RangeDescriptorNode}));
373
374 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 1))
375 Range.NumDescriptors = *Val;
376 else
377 return makeRSError(formatv("Invalid number of Descriptor in Range.\n{0}",
378 FmtMDNode{RangeDescriptorNode}));
379
380 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 2))
381 Range.BaseShaderRegister = *Val;
382 else
383 return makeRSError("Invalid value for BaseShaderRegister");
384
385 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 3))
386 Range.RegisterSpace = *Val;
387 else
388 return makeRSError("Invalid value for RegisterSpace");
389
390 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 4))
391 Range.OffsetInDescriptorsFromTableStart = *Val;
392 else
393 return makeRSError("Invalid value for OffsetInDescriptorsFromTableStart");
394
395 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 5))
396 Range.Flags = *Val;
397 else
398 return makeRSError("Invalid value for Descriptor Range Flags");
399
400 Table.Ranges.push_back(Range);
401 return Error::success();
402}
403
404Error MetadataParser::parseDescriptorTable(mcdxbc::RootSignatureDesc &RSD,
405 MDNode *DescriptorTableNode) {
406 const unsigned int NumOperands = DescriptorTableNode->getNumOperands();
407 if (NumOperands < 2)
408 return makeRSError("Invalid format for Descriptor Table");
409
410 Expected<dxbc::ShaderVisibility> Visibility =
411 extractEnumValue<dxbc::ShaderVisibility>(DescriptorTableNode, 1,
412 "ShaderVisibility",
414 if (auto E = Visibility.takeError())
415 return Error(std::move(E));
416
417 mcdxbc::DescriptorTable Table;
418
419 for (unsigned int I = 2; I < NumOperands; I++) {
420 MDNode *Element = dyn_cast<MDNode>(DescriptorTableNode->getOperand(I));
421 if (Element == nullptr)
422 return makeRSError(formatv("Missing Root Element Metadata Node.\n{0}",
423 FmtMDNode{DescriptorTableNode}));
424
425 if (auto Err = parseDescriptorRange(Table, Element))
426 return Err;
427 }
428
429 RSD.ParametersContainer.addParameter(dxbc::RootParameterType::DescriptorTable,
430 *Visibility, Table);
431 return Error::success();
432}
433
434Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
435 MDNode *StaticSamplerNode) {
436 if (StaticSamplerNode->getNumOperands() != 15)
437 return makeRSError("Invalid format for Static Sampler");
438
439 mcdxbc::StaticSampler Sampler;
440
441 Expected<dxbc::SamplerFilter> Filter = extractEnumValue<dxbc::SamplerFilter>(
442 StaticSamplerNode, 1, "Filter", dxbc::isValidSamplerFilter);
443 if (auto E = Filter.takeError())
444 return Error(std::move(E));
445 Sampler.Filter = *Filter;
446
447 Expected<dxbc::TextureAddressMode> AddressU =
449 StaticSamplerNode, 2, "AddressU", dxbc::isValidAddress);
450 if (auto E = AddressU.takeError())
451 return Error(std::move(E));
452 Sampler.AddressU = *AddressU;
453
454 Expected<dxbc::TextureAddressMode> AddressV =
456 StaticSamplerNode, 3, "AddressV", dxbc::isValidAddress);
457 if (auto E = AddressV.takeError())
458 return Error(std::move(E));
459 Sampler.AddressV = *AddressV;
460
461 Expected<dxbc::TextureAddressMode> AddressW =
463 StaticSamplerNode, 4, "AddressW", dxbc::isValidAddress);
464 if (auto E = AddressW.takeError())
465 return Error(std::move(E));
466 Sampler.AddressW = *AddressW;
467
468 if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 5))
469 Sampler.MipLODBias = *Val;
470 else
471 return makeRSError("Invalid value for MipLODBias");
472
473 if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 6))
474 Sampler.MaxAnisotropy = *Val;
475 else
476 return makeRSError("Invalid value for MaxAnisotropy");
477
478 Expected<dxbc::ComparisonFunc> ComparisonFunc =
480 StaticSamplerNode, 7, "ComparisonFunc", dxbc::isValidComparisonFunc);
481 if (auto E = ComparisonFunc.takeError())
482 return Error(std::move(E));
483 Sampler.ComparisonFunc = *ComparisonFunc;
484
485 Expected<dxbc::StaticBorderColor> BorderColor =
487 StaticSamplerNode, 8, "BorderColor", dxbc::isValidBorderColor);
488 if (auto E = BorderColor.takeError())
489 return Error(std::move(E));
490 Sampler.BorderColor = *BorderColor;
491
492 if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 9))
493 Sampler.MinLOD = *Val;
494 else
495 return makeRSError("Invalid value for MinLOD");
496
497 if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 10))
498 Sampler.MaxLOD = *Val;
499 else
500 return makeRSError("Invalid value for MaxLOD");
501
502 if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 11))
503 Sampler.ShaderRegister = *Val;
504 else
505 return makeRSError("Invalid value for ShaderRegister");
506
507 if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 12))
508 Sampler.RegisterSpace = *Val;
509 else
510 return makeRSError("Invalid value for RegisterSpace");
511
512 Expected<dxbc::ShaderVisibility> Visibility =
513 extractEnumValue<dxbc::ShaderVisibility>(StaticSamplerNode, 13,
514 "ShaderVisibility",
516 if (auto E = Visibility.takeError())
517 return Error(std::move(E));
518 Sampler.ShaderVisibility = *Visibility;
519
520 if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 14))
521 Sampler.Flags = *Val;
522 else
523 return makeRSError("Invalid value for Static Sampler Flags");
524
525 RSD.StaticSamplers.push_back(Sampler);
526 return Error::success();
527}
528
529Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD,
530 MDNode *Element) {
531 std::optional<StringRef> ElementText = extractMdStringValue(Element, 0);
532 if (!ElementText.has_value())
533 return makeRSError("Invalid format for Root Element");
534
535 RootSignatureElementKind ElementKind =
536 StringSwitch<RootSignatureElementKind>(*ElementText)
537 .Case("RootFlags", RootSignatureElementKind::RootFlags)
538 .Case("RootConstants", RootSignatureElementKind::RootConstants)
539 .Case("RootCBV", RootSignatureElementKind::CBV)
540 .Case("RootSRV", RootSignatureElementKind::SRV)
541 .Case("RootUAV", RootSignatureElementKind::UAV)
542 .Case("DescriptorTable", RootSignatureElementKind::DescriptorTable)
543 .Case("StaticSampler", RootSignatureElementKind::StaticSamplers)
545
546 switch (ElementKind) {
547
549 return parseRootFlags(RSD, Element);
551 return parseRootConstants(RSD, Element);
555 return parseRootDescriptors(RSD, Element, ElementKind);
557 return parseDescriptorTable(RSD, Element);
559 return parseStaticSampler(RSD, Element);
561 return makeRSError(
562 formatv("Invalid Root Signature Element\n{0}", FmtMDNode{Element}));
563 }
564
565 llvm_unreachable("Unhandled RootSignatureElementKind enum.");
566}
567
568static Error
570 uint32_t Location) {
572 for (const mcdxbc::DescriptorRange &Range : Table.Ranges) {
573 if (Range.RangeType == dxil::ResourceClass::Sampler &&
575 return makeRSError(
576 formatv("Samplers cannot be mixed with other resource types in a "
577 "descriptor table, {0}(location={1})",
578 getResourceClassName(CurrRC), Location));
579 CurrRC = Range.RangeType;
580 }
581 return Error::success();
582}
583
584static Error
586 uint32_t Location) {
587 uint64_t Offset = 0;
588 bool IsPrevUnbound = false;
589 for (const mcdxbc::DescriptorRange &Range : Table.Ranges) {
590 // Validation of NumDescriptors should have happened by this point.
591 if (Range.NumDescriptors == 0)
592 continue;
593
595 Range.BaseShaderRegister, Range.NumDescriptors);
596
597 if (!verifyNoOverflowedOffset(RangeBound))
598 return makeRSError(
599 formatv("Overflow for shader register range: {0}", FmtRange{Range}));
600
601 bool IsAppending =
602 Range.OffsetInDescriptorsFromTableStart == DescriptorTableOffsetAppend;
603 if (!IsAppending)
604 Offset = Range.OffsetInDescriptorsFromTableStart;
605
606 if (IsPrevUnbound && IsAppending)
607 return makeRSError(
608 formatv("Range {0} cannot be appended after an unbounded range",
609 FmtRange{Range}));
610
611 const uint64_t OffsetBound =
613
614 if (!verifyNoOverflowedOffset(OffsetBound))
615 return makeRSError(formatv("Offset overflow for descriptor range: {0}.",
616 FmtRange{Range}));
617
618 Offset = OffsetBound + 1;
619 IsPrevUnbound =
621 }
622
623 return Error::success();
624}
625
626Error MetadataParser::validateRootSignature(
627 const mcdxbc::RootSignatureDesc &RSD) {
628 Error DeferredErrs = Error::success();
630 DeferredErrs = joinErrors(
631 std::move(DeferredErrs),
632 makeRSError(formatv("Invalid value for Version: {0}", RSD.Version)));
633 }
634
636 DeferredErrs = joinErrors(
637 std::move(DeferredErrs),
638 makeRSError(formatv("Invalid value for RootFlags: {0}", RSD.Flags)));
639 }
640
642
643 switch (Info.Type) {
644 case dxbc::RootParameterType::Constants32Bit:
645 break;
646
647 case dxbc::RootParameterType::CBV:
648 case dxbc::RootParameterType::UAV:
649 case dxbc::RootParameterType::SRV: {
650 const mcdxbc::RootDescriptor &Descriptor =
653 DeferredErrs = joinErrors(
654 std::move(DeferredErrs),
655 makeRSError(formatv("Invalid value for ShaderRegister: {0}",
656 Descriptor.ShaderRegister)));
657
659 DeferredErrs = joinErrors(
660 std::move(DeferredErrs),
661 makeRSError(formatv("Invalid value for RegisterSpace: {0}",
662 Descriptor.RegisterSpace)));
663
664 bool IsValidFlag =
667 RSD.Version, dxbc::RootDescriptorFlags(Descriptor.Flags));
668 if (!IsValidFlag)
669 DeferredErrs = joinErrors(
670 std::move(DeferredErrs),
671 makeRSError(formatv("Invalid value for RootDescriptorFlag: {0}",
672 Descriptor.Flags)));
673 break;
674 }
675 case dxbc::RootParameterType::DescriptorTable: {
676 const mcdxbc::DescriptorTable &Table =
678 for (const mcdxbc::DescriptorRange &Range : Table) {
679 if (!hlsl::rootsig::verifyRegisterSpace(Range.RegisterSpace))
680 DeferredErrs = joinErrors(
681 std::move(DeferredErrs),
682 makeRSError(formatv("Invalid value for RegisterSpace: {0}",
683 Range.RegisterSpace)));
684
685 if (!hlsl::rootsig::verifyNumDescriptors(Range.NumDescriptors))
686 DeferredErrs = joinErrors(
687 std::move(DeferredErrs),
688 makeRSError(formatv("Invalid value for NumDescriptors: {0}",
689 Range.NumDescriptors)));
690
691 bool IsValidFlag = dxbc::isValidDescriptorRangeFlags(Range.Flags) &&
693 RSD.Version, Range.RangeType,
695 if (!IsValidFlag)
696 DeferredErrs = joinErrors(
697 std::move(DeferredErrs),
698 makeRSError(formatv("Invalid value for DescriptorFlag: {0}",
699 Range.Flags)));
700
701 if (Error Err =
703 DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));
704
705 if (Error Err =
707 DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));
708 }
709 break;
710 }
711 }
712 }
713
714 for (const mcdxbc::StaticSampler &Sampler : RSD.StaticSamplers) {
715
717 DeferredErrs =
718 joinErrors(std::move(DeferredErrs),
719 makeRSError(formatv("Invalid value for MipLODBias: {0:e}",
720 Sampler.MipLODBias)));
721
723 DeferredErrs =
724 joinErrors(std::move(DeferredErrs),
725 makeRSError(formatv("Invalid value for MaxAnisotropy: {0}",
726 Sampler.MaxAnisotropy)));
727
729 DeferredErrs =
730 joinErrors(std::move(DeferredErrs),
731 makeRSError(formatv("Invalid value for MinLOD: {0}",
732 Sampler.MinLOD)));
733
735 DeferredErrs =
736 joinErrors(std::move(DeferredErrs),
737 makeRSError(formatv("Invalid value for MaxLOD: {0}",
738 Sampler.MaxLOD)));
739
740 if (!hlsl::rootsig::verifyRegisterValue(Sampler.ShaderRegister))
741 DeferredErrs = joinErrors(
742 std::move(DeferredErrs),
743 makeRSError(formatv("Invalid value for ShaderRegister: {0}",
744 Sampler.ShaderRegister)));
745
747 DeferredErrs =
748 joinErrors(std::move(DeferredErrs),
749 makeRSError(formatv("Invalid value for RegisterSpace: {0}",
750 Sampler.RegisterSpace)));
751 bool IsValidFlag =
755 if (!IsValidFlag)
756 DeferredErrs = joinErrors(
757 std::move(DeferredErrs),
758 makeRSError(formatv("Invalid value for Static Sampler Flag: {0}",
759 Sampler.Flags)));
760 }
761
762 return DeferredErrs;
763}
764
765Expected<mcdxbc::RootSignatureDesc>
767 Error DeferredErrs = Error::success();
769 RSD.Version = Version;
770 for (const auto &Operand : Root->operands()) {
771 MDNode *Element = dyn_cast<MDNode>(Operand);
772 if (Element == nullptr)
773 return joinErrors(
774 std::move(DeferredErrs),
775 makeRSError(formatv("Missing Root Element Metadata Node.")));
776
777 if (auto Err = parseRootSignatureElement(RSD, Element))
778 DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));
779 }
780
781 if (auto Err = validateRootSignature(RSD))
782 DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));
783
784 if (DeferredErrs)
785 return std::move(DeferredErrs);
786
787 return std::move(RSD);
788}
789} // namespace rootsig
790} // namespace hlsl
791} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
dxil translate DXIL Translate Metadata
#define I(x, y, z)
Definition MD5.cpp:58
mir Rename Register Operands
This file contains the declarations for metadata subclasses.
#define T
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:536
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2783
Metadata node.
Definition Metadata.h:1078
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1442
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1569
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1448
A single uniqued string.
Definition Metadata.h:721
LLVM_ABI StringRef getString() const
Definition Metadata.cpp:618
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:608
Root of the metadata hierarchy.
Definition Metadata.h:64
Wrapper class representing virtual and physical registers.
Definition Register.h:19
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:143
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:285
An efficient, type-erasing, non-owning reference to a callable.
LLVM_ABI MDNode * BuildRootSignature()
Iterates through elements and dispatches onto the correct Build* method.
LLVM_ABI llvm::Expected< llvm::mcdxbc::RootSignatureDesc > ParseRootSignature(uint32_t Version)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isValidShaderVisibility(uint32_t V)
bool isValidSamplerFilter(uint32_t V)
bool isValidStaticSamplerFlags(uint32_t V)
bool isValidRootDesciptorFlags(uint32_t V)
bool isValidDescriptorRangeFlags(uint32_t V)
bool isValidBorderColor(uint32_t V)
bool isValidComparisonFunc(uint32_t V)
bool isValidAddress(uint32_t V)
LLVM_ABI StringRef getResourceClassName(ResourceClass RC)
Definition DXILABI.cpp:21
static std::optional< uint32_t > extractMdIntValue(MDNode *Node, unsigned int OpId)
LLVM_ABI bool verifyRootDescriptorFlag(uint32_t Version, dxbc::RootDescriptorFlags Flags)
LLVM_ABI uint64_t computeRangeBound(uint64_t Offset, uint32_t Size)
static const uint32_t NumDescriptorsUnbounded
static Error validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table, uint32_t Location)
LLVM_ABI bool verifyRegisterSpace(uint32_t RegisterSpace)
static const uint32_t DescriptorTableOffsetAppend
static Error validateDescriptorTableSamplerMixin(const mcdxbc::DescriptorTable &Table, uint32_t Location)
LLVM_ABI bool verifyVersion(uint32_t Version)
static std::optional< StringRef > extractMdStringValue(MDNode *Node, unsigned int OpId)
LLVM_ABI bool verifyStaticSamplerFlags(uint32_t Version, dxbc::StaticSamplerFlags Flags)
LLVM_ABI bool verifyRootFlag(uint32_t Flags)
LLVM_ABI bool verifyLOD(float LOD)
LLVM_ABI bool verifyDescriptorRangeFlag(uint32_t Version, dxil::ResourceClass Type, dxbc::DescriptorRangeFlags Flags)
std::variant< dxbc::RootFlags, RootConstants, RootDescriptor, DescriptorTable, DescriptorTableClause, StaticSampler > RootElement
Models RootElement : RootFlags | RootConstants | RootParam | DescriptorTable | DescriptorTableClause ...
LLVM_ABI bool verifyNoOverflowedOffset(uint64_t Offset)
LLVM_ABI bool verifyMipLODBias(float MipLODBias)
LLVM_ABI bool verifyNumDescriptors(uint32_t NumDescriptors)
LLVM_ABI raw_ostream & operator<<(raw_ostream &OS, const dxbc::RootFlags &Flags)
The following contains the serialization interface for root elements.
LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy)
static Expected< T > extractEnumValue(MDNode *Node, unsigned int OpId, StringRef ErrText, llvm::function_ref< bool(uint32_t)> VerifyFn)
LLVM_ABI bool verifyRegisterValue(uint32_t RegisterValue)
static std::optional< float > extractMdFloatValue(MDNode *Node, unsigned int OpId)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:695
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:644
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
Definition InstrProf.h:302
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition Error.h:442
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
SmallVector< DescriptorRange > Ranges
const RootDescriptor & getRootDescriptor(size_t Index) const
const DescriptorTable & getDescriptorTable(size_t Index) const
void addParameter(dxbc::RootParameterType Type, dxbc::ShaderVisibility Visibility, RootConstants Constant)
SmallVector< StaticSampler > StaticSamplers
mcdxbc::RootParametersContainer ParametersContainer