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
34
35template <typename T> char RootSignatureValidationError<T>::ID;
36
37static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
38 unsigned int OpId) {
39 if (auto *CI =
40 mdconst::dyn_extract<ConstantInt>(Node->getOperand(OpId).get()))
41 return CI->getZExtValue();
42 return std::nullopt;
43}
44
45static std::optional<float> extractMdFloatValue(MDNode *Node,
46 unsigned int OpId) {
47 if (auto *CI = mdconst::dyn_extract<ConstantFP>(Node->getOperand(OpId).get()))
48 return CI->getValueAPF().convertToFloat();
49 return std::nullopt;
50}
51
52static std::optional<StringRef> extractMdStringValue(MDNode *Node,
53 unsigned int OpId) {
54 MDString *NodeText = dyn_cast<MDString>(Node->getOperand(OpId));
55 if (NodeText == nullptr)
56 return std::nullopt;
57 return NodeText->getString();
58}
59
60template <typename T, typename = std::enable_if_t<
61 std::is_enum_v<T> &&
62 std::is_same_v<std::underlying_type_t<T>, uint32_t>>>
63static Expected<T>
64extractEnumValue(MDNode *Node, unsigned int OpId, StringRef ErrText,
65 llvm::function_ref<bool(uint32_t)> VerifyFn) {
66 if (std::optional<uint32_t> Val = extractMdIntValue(Node, OpId)) {
67 if (!VerifyFn(*Val))
69 return static_cast<T>(*Val);
70 }
71 return make_error<InvalidRSMetadataValue>("ShaderVisibility");
72}
73
74namespace {
75
76// We use the OverloadVisit with std::visit to ensure the compiler catches if a
77// new RootElement variant type is added but it's metadata generation isn't
78// handled.
79template <class... Ts> struct OverloadedVisit : Ts... {
80 using Ts::operator()...;
81};
82template <class... Ts> OverloadedVisit(Ts...) -> OverloadedVisit<Ts...>;
83
84} // namespace
85
87 const auto Visitor = OverloadedVisit{
88 [this](const dxbc::RootFlags &Flags) -> MDNode * {
89 return BuildRootFlags(Flags);
90 },
91 [this](const RootConstants &Constants) -> MDNode * {
92 return BuildRootConstants(Constants);
93 },
94 [this](const RootDescriptor &Descriptor) -> MDNode * {
95 return BuildRootDescriptor(Descriptor);
96 },
97 [this](const DescriptorTableClause &Clause) -> MDNode * {
98 return BuildDescriptorTableClause(Clause);
99 },
100 [this](const DescriptorTable &Table) -> MDNode * {
101 return BuildDescriptorTable(Table);
102 },
103 [this](const StaticSampler &Sampler) -> MDNode * {
104 return BuildStaticSampler(Sampler);
105 },
106 };
107
108 for (const RootElement &Element : Elements) {
109 MDNode *ElementMD = std::visit(Visitor, Element);
110 assert(ElementMD != nullptr &&
111 "Root Element must be initialized and validated");
112 GeneratedMetadata.push_back(ElementMD);
113 }
114
115 return MDNode::get(Ctx, GeneratedMetadata);
116}
117
118MDNode *MetadataBuilder::BuildRootFlags(const dxbc::RootFlags &Flags) {
119 IRBuilder<> Builder(Ctx);
120 Metadata *Operands[] = {
121 MDString::get(Ctx, "RootFlags"),
122 ConstantAsMetadata::get(Builder.getInt32(to_underlying(Flags))),
123 };
124 return MDNode::get(Ctx, Operands);
125}
126
127MDNode *MetadataBuilder::BuildRootConstants(const RootConstants &Constants) {
128 IRBuilder<> Builder(Ctx);
129 Metadata *Operands[] = {
130 MDString::get(Ctx, "RootConstants"),
132 Builder.getInt32(to_underlying(Constants.Visibility))),
133 ConstantAsMetadata::get(Builder.getInt32(Constants.Reg.Number)),
134 ConstantAsMetadata::get(Builder.getInt32(Constants.Space)),
135 ConstantAsMetadata::get(Builder.getInt32(Constants.Num32BitConstants)),
136 };
137 return MDNode::get(Ctx, Operands);
138}
139
140MDNode *MetadataBuilder::BuildRootDescriptor(const RootDescriptor &Descriptor) {
141 IRBuilder<> Builder(Ctx);
142 StringRef ResName = dxil::getResourceClassName(Descriptor.Type);
143 assert(!ResName.empty() && "Provided an invalid Resource Class");
144 SmallString<7> Name({"Root", ResName});
145 Metadata *Operands[] = {
146 MDString::get(Ctx, Name),
148 Builder.getInt32(to_underlying(Descriptor.Visibility))),
149 ConstantAsMetadata::get(Builder.getInt32(Descriptor.Reg.Number)),
150 ConstantAsMetadata::get(Builder.getInt32(Descriptor.Space)),
152 Builder.getInt32(to_underlying(Descriptor.Flags))),
153 };
154 return MDNode::get(Ctx, Operands);
155}
156
157MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) {
158 IRBuilder<> Builder(Ctx);
159 SmallVector<Metadata *> TableOperands;
160 // Set the mandatory arguments
161 TableOperands.push_back(MDString::get(Ctx, "DescriptorTable"));
163 Builder.getInt32(to_underlying(Table.Visibility))));
164
165 // Remaining operands are references to the table's clauses. The in-memory
166 // representation of the Root Elements created from parsing will ensure that
167 // the previous N elements are the clauses for this table.
168 assert(Table.NumClauses <= GeneratedMetadata.size() &&
169 "Table expected all owned clauses to be generated already");
170 // So, add a refence to each clause to our operands
171 TableOperands.append(GeneratedMetadata.end() - Table.NumClauses,
172 GeneratedMetadata.end());
173 // Then, remove those clauses from the general list of Root Elements
174 GeneratedMetadata.pop_back_n(Table.NumClauses);
175
176 return MDNode::get(Ctx, TableOperands);
177}
178
179MDNode *MetadataBuilder::BuildDescriptorTableClause(
180 const DescriptorTableClause &Clause) {
181 IRBuilder<> Builder(Ctx);
182 StringRef ResName = dxil::getResourceClassName(Clause.Type);
183 assert(!ResName.empty() && "Provided an invalid Resource Class");
184 Metadata *Operands[] = {
185 MDString::get(Ctx, ResName),
186 ConstantAsMetadata::get(Builder.getInt32(Clause.NumDescriptors)),
187 ConstantAsMetadata::get(Builder.getInt32(Clause.Reg.Number)),
188 ConstantAsMetadata::get(Builder.getInt32(Clause.Space)),
189 ConstantAsMetadata::get(Builder.getInt32(Clause.Offset)),
190 ConstantAsMetadata::get(Builder.getInt32(to_underlying(Clause.Flags))),
191 };
192 return MDNode::get(Ctx, Operands);
193}
194
195MDNode *MetadataBuilder::BuildStaticSampler(const StaticSampler &Sampler) {
196 IRBuilder<> Builder(Ctx);
197 Metadata *Operands[] = {
198 MDString::get(Ctx, "StaticSampler"),
199 ConstantAsMetadata::get(Builder.getInt32(to_underlying(Sampler.Filter))),
201 Builder.getInt32(to_underlying(Sampler.AddressU))),
203 Builder.getInt32(to_underlying(Sampler.AddressV))),
205 Builder.getInt32(to_underlying(Sampler.AddressW))),
207 ConstantFP::get(Type::getFloatTy(Ctx), Sampler.MipLODBias)),
208 ConstantAsMetadata::get(Builder.getInt32(Sampler.MaxAnisotropy)),
210 Builder.getInt32(to_underlying(Sampler.CompFunc))),
212 Builder.getInt32(to_underlying(Sampler.BorderColor))),
214 ConstantFP::get(Type::getFloatTy(Ctx), Sampler.MinLOD)),
216 ConstantFP::get(Type::getFloatTy(Ctx), Sampler.MaxLOD)),
217 ConstantAsMetadata::get(Builder.getInt32(Sampler.Reg.Number)),
218 ConstantAsMetadata::get(Builder.getInt32(Sampler.Space)),
220 Builder.getInt32(to_underlying(Sampler.Visibility))),
221 ConstantAsMetadata::get(Builder.getInt32(to_underlying(Sampler.Flags))),
222 };
223 return MDNode::get(Ctx, Operands);
224}
225
226Error MetadataParser::parseRootFlags(mcdxbc::RootSignatureDesc &RSD,
227 MDNode *RootFlagNode) {
228 if (RootFlagNode->getNumOperands() != 2)
229 return make_error<InvalidRSMetadataFormat>("RootFlag Element");
230
231 if (std::optional<uint32_t> Val = extractMdIntValue(RootFlagNode, 1))
232 RSD.Flags = *Val;
233 else
234 return make_error<InvalidRSMetadataValue>("RootFlag");
235
236 return Error::success();
237}
238
239Error MetadataParser::parseRootConstants(mcdxbc::RootSignatureDesc &RSD,
240 MDNode *RootConstantNode) {
241 if (RootConstantNode->getNumOperands() != 5)
242 return make_error<InvalidRSMetadataFormat>("RootConstants Element");
243
244 Expected<dxbc::ShaderVisibility> Visibility =
246 "ShaderVisibility",
248 if (auto E = Visibility.takeError())
249 return Error(std::move(E));
250
251 mcdxbc::RootConstants Constants;
252 if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 2))
253 Constants.ShaderRegister = *Val;
254 else
255 return make_error<InvalidRSMetadataValue>("ShaderRegister");
256
257 if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 3))
258 Constants.RegisterSpace = *Val;
259 else
260 return make_error<InvalidRSMetadataValue>("RegisterSpace");
261
262 if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 4))
263 Constants.Num32BitValues = *Val;
264 else
265 return make_error<InvalidRSMetadataValue>("Num32BitValues");
266
267 RSD.ParametersContainer.addParameter(dxbc::RootParameterType::Constants32Bit,
268 *Visibility, Constants);
269
270 return Error::success();
271}
272
273Error MetadataParser::parseRootDescriptors(
274 mcdxbc::RootSignatureDesc &RSD, MDNode *RootDescriptorNode,
275 RootSignatureElementKind ElementKind) {
276 assert((ElementKind == RootSignatureElementKind::SRV ||
277 ElementKind == RootSignatureElementKind::UAV ||
278 ElementKind == RootSignatureElementKind::CBV) &&
279 "parseRootDescriptors should only be called with RootDescriptor "
280 "element kind.");
281 if (RootDescriptorNode->getNumOperands() != 5)
282 return make_error<InvalidRSMetadataFormat>("Root Descriptor Element");
283
285 switch (ElementKind) {
287 Type = dxbc::RootParameterType::SRV;
288 break;
290 Type = dxbc::RootParameterType::UAV;
291 break;
293 Type = dxbc::RootParameterType::CBV;
294 break;
295 default:
296 llvm_unreachable("invalid Root Descriptor kind");
297 break;
298 }
299
300 Expected<dxbc::ShaderVisibility> Visibility =
301 extractEnumValue<dxbc::ShaderVisibility>(RootDescriptorNode, 1,
302 "ShaderVisibility",
304 if (auto E = Visibility.takeError())
305 return Error(std::move(E));
306
307 mcdxbc::RootDescriptor Descriptor;
308 if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 2))
309 Descriptor.ShaderRegister = *Val;
310 else
311 return make_error<InvalidRSMetadataValue>("ShaderRegister");
312
313 if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 3))
314 Descriptor.RegisterSpace = *Val;
315 else
316 return make_error<InvalidRSMetadataValue>("RegisterSpace");
317
318 if (RSD.Version == 1) {
319 RSD.ParametersContainer.addParameter(Type, *Visibility, Descriptor);
320 return Error::success();
321 }
322 assert(RSD.Version > 1);
323
324 if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 4))
325 Descriptor.Flags = *Val;
326 else
327 return make_error<InvalidRSMetadataValue>("Root Descriptor Flags");
328
329 RSD.ParametersContainer.addParameter(Type, *Visibility, Descriptor);
330 return Error::success();
331}
332
333Error MetadataParser::parseDescriptorRange(mcdxbc::DescriptorTable &Table,
334 MDNode *RangeDescriptorNode) {
335 if (RangeDescriptorNode->getNumOperands() != 6)
336 return make_error<InvalidRSMetadataFormat>("Descriptor Range");
337
338 mcdxbc::DescriptorRange Range;
339
340 std::optional<StringRef> ElementText =
341 extractMdStringValue(RangeDescriptorNode, 0);
342
343 if (!ElementText.has_value())
344 return make_error<InvalidRSMetadataFormat>("Descriptor Range");
345
346 if (*ElementText == "CBV")
348 else if (*ElementText == "SRV")
350 else if (*ElementText == "UAV")
352 else if (*ElementText == "Sampler")
354 else
355 return make_error<GenericRSMetadataError>("Invalid Descriptor Range type.",
356 RangeDescriptorNode);
357
358 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 1))
359 Range.NumDescriptors = *Val;
360 else
361 return make_error<GenericRSMetadataError>("Number of Descriptor in Range",
362 RangeDescriptorNode);
363
364 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 2))
365 Range.BaseShaderRegister = *Val;
366 else
367 return make_error<InvalidRSMetadataValue>("BaseShaderRegister");
368
369 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 3))
370 Range.RegisterSpace = *Val;
371 else
372 return make_error<InvalidRSMetadataValue>("RegisterSpace");
373
374 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 4))
375 Range.OffsetInDescriptorsFromTableStart = *Val;
376 else
378 "OffsetInDescriptorsFromTableStart");
379
380 if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 5))
381 Range.Flags = *Val;
382 else
383 return make_error<InvalidRSMetadataValue>("Descriptor Range Flags");
384
385 Table.Ranges.push_back(Range);
386 return Error::success();
387}
388
389Error MetadataParser::parseDescriptorTable(mcdxbc::RootSignatureDesc &RSD,
390 MDNode *DescriptorTableNode) {
391 const unsigned int NumOperands = DescriptorTableNode->getNumOperands();
392 if (NumOperands < 2)
393 return make_error<InvalidRSMetadataFormat>("Descriptor Table");
394
395 Expected<dxbc::ShaderVisibility> Visibility =
396 extractEnumValue<dxbc::ShaderVisibility>(DescriptorTableNode, 1,
397 "ShaderVisibility",
399 if (auto E = Visibility.takeError())
400 return Error(std::move(E));
401
402 mcdxbc::DescriptorTable Table;
403
404 for (unsigned int I = 2; I < NumOperands; I++) {
405 MDNode *Element = dyn_cast<MDNode>(DescriptorTableNode->getOperand(I));
406 if (Element == nullptr)
408 "Missing Root Element Metadata Node.", DescriptorTableNode);
409
410 if (auto Err = parseDescriptorRange(Table, Element))
411 return Err;
412 }
413
414 RSD.ParametersContainer.addParameter(dxbc::RootParameterType::DescriptorTable,
415 *Visibility, Table);
416 return Error::success();
417}
418
419Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
420 MDNode *StaticSamplerNode) {
421 if (StaticSamplerNode->getNumOperands() != 15)
422 return make_error<InvalidRSMetadataFormat>("Static Sampler");
423
424 mcdxbc::StaticSampler Sampler;
425
426 Expected<dxbc::SamplerFilter> Filter = extractEnumValue<dxbc::SamplerFilter>(
427 StaticSamplerNode, 1, "Filter", dxbc::isValidSamplerFilter);
428 if (auto E = Filter.takeError())
429 return Error(std::move(E));
430 Sampler.Filter = *Filter;
431
432 Expected<dxbc::TextureAddressMode> AddressU =
434 StaticSamplerNode, 2, "AddressU", dxbc::isValidAddress);
435 if (auto E = AddressU.takeError())
436 return Error(std::move(E));
437 Sampler.AddressU = *AddressU;
438
439 Expected<dxbc::TextureAddressMode> AddressV =
441 StaticSamplerNode, 3, "AddressV", dxbc::isValidAddress);
442 if (auto E = AddressV.takeError())
443 return Error(std::move(E));
444 Sampler.AddressV = *AddressV;
445
446 Expected<dxbc::TextureAddressMode> AddressW =
448 StaticSamplerNode, 4, "AddressW", dxbc::isValidAddress);
449 if (auto E = AddressW.takeError())
450 return Error(std::move(E));
451 Sampler.AddressW = *AddressW;
452
453 if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 5))
454 Sampler.MipLODBias = *Val;
455 else
456 return make_error<InvalidRSMetadataValue>("MipLODBias");
457
458 if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 6))
459 Sampler.MaxAnisotropy = *Val;
460 else
461 return make_error<InvalidRSMetadataValue>("MaxAnisotropy");
462
463 Expected<dxbc::ComparisonFunc> ComparisonFunc =
465 StaticSamplerNode, 7, "ComparisonFunc", dxbc::isValidComparisonFunc);
466 if (auto E = ComparisonFunc.takeError())
467 return Error(std::move(E));
468 Sampler.ComparisonFunc = *ComparisonFunc;
469
470 Expected<dxbc::StaticBorderColor> BorderColor =
472 StaticSamplerNode, 8, "BorderColor", dxbc::isValidBorderColor);
473 if (auto E = BorderColor.takeError())
474 return Error(std::move(E));
475 Sampler.BorderColor = *BorderColor;
476
477 if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 9))
478 Sampler.MinLOD = *Val;
479 else
480 return make_error<InvalidRSMetadataValue>("MinLOD");
481
482 if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 10))
483 Sampler.MaxLOD = *Val;
484 else
485 return make_error<InvalidRSMetadataValue>("MaxLOD");
486
487 if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 11))
488 Sampler.ShaderRegister = *Val;
489 else
490 return make_error<InvalidRSMetadataValue>("ShaderRegister");
491
492 if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 12))
493 Sampler.RegisterSpace = *Val;
494 else
495 return make_error<InvalidRSMetadataValue>("RegisterSpace");
496
497 Expected<dxbc::ShaderVisibility> Visibility =
498 extractEnumValue<dxbc::ShaderVisibility>(StaticSamplerNode, 13,
499 "ShaderVisibility",
501 if (auto E = Visibility.takeError())
502 return Error(std::move(E));
503 Sampler.ShaderVisibility = *Visibility;
504
505 if (RSD.Version < 3) {
506 RSD.StaticSamplers.push_back(Sampler);
507 return Error::success();
508 }
509 assert(RSD.Version >= 3);
510
511 if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 14))
512 Sampler.Flags = *Val;
513 else
514 return make_error<InvalidRSMetadataValue>("Static Sampler Flags");
515
516 RSD.StaticSamplers.push_back(Sampler);
517 return Error::success();
518}
519
520Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD,
521 MDNode *Element) {
522 std::optional<StringRef> ElementText = extractMdStringValue(Element, 0);
523 if (!ElementText.has_value())
524 return make_error<InvalidRSMetadataFormat>("Root Element");
525
526 RootSignatureElementKind ElementKind =
527 StringSwitch<RootSignatureElementKind>(*ElementText)
528 .Case("RootFlags", RootSignatureElementKind::RootFlags)
529 .Case("RootConstants", RootSignatureElementKind::RootConstants)
530 .Case("RootCBV", RootSignatureElementKind::CBV)
531 .Case("RootSRV", RootSignatureElementKind::SRV)
532 .Case("RootUAV", RootSignatureElementKind::UAV)
533 .Case("DescriptorTable", RootSignatureElementKind::DescriptorTable)
534 .Case("StaticSampler", RootSignatureElementKind::StaticSamplers)
536
537 switch (ElementKind) {
538
540 return parseRootFlags(RSD, Element);
542 return parseRootConstants(RSD, Element);
546 return parseRootDescriptors(RSD, Element, ElementKind);
548 return parseDescriptorTable(RSD, Element);
550 return parseStaticSampler(RSD, Element);
552 return make_error<GenericRSMetadataError>("Invalid Root Signature Element",
553 Element);
554 }
555
556 llvm_unreachable("Unhandled RootSignatureElementKind enum.");
557}
558
559static Error
561 uint32_t Location) {
563 for (const mcdxbc::DescriptorRange &Range : Table.Ranges) {
564 if (Range.RangeType == dxil::ResourceClass::Sampler &&
566 return make_error<TableSamplerMixinError>(CurrRC, Location);
567 CurrRC = Range.RangeType;
568 }
569 return Error::success();
570}
571
572static Error
574 uint32_t Location) {
575 uint64_t Offset = 0;
576 bool IsPrevUnbound = false;
577 for (const mcdxbc::DescriptorRange &Range : Table.Ranges) {
578 // Validation of NumDescriptors should have happened by this point.
579 if (Range.NumDescriptors == 0)
580 continue;
581
583 Range.BaseShaderRegister, Range.NumDescriptors);
584
585 if (!verifyNoOverflowedOffset(RangeBound))
587 Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace);
588
589 bool IsAppending =
590 Range.OffsetInDescriptorsFromTableStart == DescriptorTableOffsetAppend;
591 if (!IsAppending)
592 Offset = Range.OffsetInDescriptorsFromTableStart;
593
594 if (IsPrevUnbound && IsAppending)
596 Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace);
597
598 const uint64_t OffsetBound =
600
601 if (!verifyNoOverflowedOffset(OffsetBound))
603 Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace);
604
605 Offset = OffsetBound + 1;
606 IsPrevUnbound =
608 }
609
610 return Error::success();
611}
612
613Error MetadataParser::validateRootSignature(
614 const mcdxbc::RootSignatureDesc &RSD) {
615 Error DeferredErrs = Error::success();
617 DeferredErrs =
618 joinErrors(std::move(DeferredErrs),
619 make_error<RootSignatureValidationError<uint32_t>>(
620 "Version", RSD.Version));
621 }
622
624 DeferredErrs =
625 joinErrors(std::move(DeferredErrs),
626 make_error<RootSignatureValidationError<uint32_t>>(
627 "RootFlags", RSD.Flags));
628 }
629
631
632 switch (Info.Type) {
633 case dxbc::RootParameterType::Constants32Bit:
634 break;
635
636 case dxbc::RootParameterType::CBV:
637 case dxbc::RootParameterType::UAV:
638 case dxbc::RootParameterType::SRV: {
639 const mcdxbc::RootDescriptor &Descriptor =
642 DeferredErrs =
643 joinErrors(std::move(DeferredErrs),
644 make_error<RootSignatureValidationError<uint32_t>>(
645 "ShaderRegister", Descriptor.ShaderRegister));
646
648 DeferredErrs =
649 joinErrors(std::move(DeferredErrs),
650 make_error<RootSignatureValidationError<uint32_t>>(
651 "RegisterSpace", Descriptor.RegisterSpace));
652
653 if (RSD.Version > 1) {
655 Descriptor.Flags))
656 DeferredErrs =
657 joinErrors(std::move(DeferredErrs),
658 make_error<RootSignatureValidationError<uint32_t>>(
659 "RootDescriptorFlag", Descriptor.Flags));
660 }
661 break;
662 }
663 case dxbc::RootParameterType::DescriptorTable: {
664 const mcdxbc::DescriptorTable &Table =
666 for (const mcdxbc::DescriptorRange &Range : Table) {
667 if (!hlsl::rootsig::verifyRegisterSpace(Range.RegisterSpace))
668 DeferredErrs =
669 joinErrors(std::move(DeferredErrs),
670 make_error<RootSignatureValidationError<uint32_t>>(
671 "RegisterSpace", Range.RegisterSpace));
672
673 if (!hlsl::rootsig::verifyNumDescriptors(Range.NumDescriptors))
674 DeferredErrs =
675 joinErrors(std::move(DeferredErrs),
676 make_error<RootSignatureValidationError<uint32_t>>(
677 "NumDescriptors", Range.NumDescriptors));
678
680 RSD.Version, Range.RangeType,
682 DeferredErrs =
683 joinErrors(std::move(DeferredErrs),
684 make_error<RootSignatureValidationError<uint32_t>>(
685 "DescriptorFlag", Range.Flags));
686
687 if (Error Err =
689 DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));
690
691 if (Error Err =
693 DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));
694 }
695 break;
696 }
697 }
698 }
699
700 for (const mcdxbc::StaticSampler &Sampler : RSD.StaticSamplers) {
701
703 DeferredErrs = joinErrors(std::move(DeferredErrs),
704 make_error<RootSignatureValidationError<float>>(
705 "MipLODBias", Sampler.MipLODBias));
706
708 DeferredErrs =
709 joinErrors(std::move(DeferredErrs),
710 make_error<RootSignatureValidationError<uint32_t>>(
711 "MaxAnisotropy", Sampler.MaxAnisotropy));
712
714 DeferredErrs = joinErrors(std::move(DeferredErrs),
715 make_error<RootSignatureValidationError<float>>(
716 "MinLOD", Sampler.MinLOD));
717
719 DeferredErrs = joinErrors(std::move(DeferredErrs),
720 make_error<RootSignatureValidationError<float>>(
721 "MaxLOD", Sampler.MaxLOD));
722
723 if (!hlsl::rootsig::verifyRegisterValue(Sampler.ShaderRegister))
724 DeferredErrs =
725 joinErrors(std::move(DeferredErrs),
726 make_error<RootSignatureValidationError<uint32_t>>(
727 "ShaderRegister", Sampler.ShaderRegister));
728
730 DeferredErrs =
731 joinErrors(std::move(DeferredErrs),
732 make_error<RootSignatureValidationError<uint32_t>>(
733 "RegisterSpace", Sampler.RegisterSpace));
734
736 DeferredErrs =
737 joinErrors(std::move(DeferredErrs),
738 make_error<RootSignatureValidationError<uint32_t>>(
739 "Static Sampler Flag", Sampler.Flags));
740 }
741
742 return DeferredErrs;
743}
744
745Expected<mcdxbc::RootSignatureDesc>
747 Error DeferredErrs = Error::success();
749 RSD.Version = Version;
750 for (const auto &Operand : Root->operands()) {
751 MDNode *Element = dyn_cast<MDNode>(Operand);
752 if (Element == nullptr)
753 return joinErrors(std::move(DeferredErrs),
755 "Missing Root Element Metadata Node.", nullptr));
756
757 if (auto Err = parseRootSignatureElement(RSD, Element))
758 DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));
759 }
760
761 if (auto Err = validateRootSignature(RSD))
762 DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));
763
764 if (DeferredErrs)
765 return std::move(DeferredErrs);
766
767 return std::move(RSD);
768}
769} // namespace rootsig
770} // namespace hlsl
771} // 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
Tagged union holding either a T or a Error.
Definition Error.h:485
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:2780
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
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
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 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, uint32_t FlagsVal)
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 verifyStaticSamplerFlags(uint32_t Version, uint32_t FlagsNumber)
LLVM_ABI bool verifyRegisterSpace(uint32_t RegisterSpace)
static const uint32_t DescriptorTableOffsetAppend
LLVM_ABI bool verifyDescriptorRangeFlag(uint32_t Version, dxil::ResourceClass Type, dxbc::DescriptorRangeFlags FlagsVal)
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 verifyRootFlag(uint32_t Flags)
LLVM_ABI bool verifyLOD(float LOD)
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 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
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