xref: /freebsd/contrib/llvm-project/llvm/lib/ObjectYAML/DXContainerYAML.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===- DXContainerYAML.cpp - DXContainer YAMLIO implementation ------------===//
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 // This file defines classes for handling the YAML representation of
10 // DXContainerYAML.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/ObjectYAML/DXContainerYAML.h"
15 #include "llvm/ADT/STLForwardCompat.h"
16 #include "llvm/ADT/ScopeExit.h"
17 #include "llvm/BinaryFormat/DXContainer.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/ScopedPrinter.h"
20 #include <cstdint>
21 #include <system_error>
22 
23 namespace llvm {
24 
25 // This assert is duplicated here to leave a breadcrumb of the places that need
26 // to be updated if flags grow past 64-bits.
27 static_assert((uint64_t)dxbc::FeatureFlags::NextUnusedBit <= 1ull << 63,
28               "Shader flag bits exceed enum size.");
29 
30 DXContainerYAML::ShaderFeatureFlags::ShaderFeatureFlags(uint64_t FlagData) {
31 #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str)                      \
32   Val = (FlagData & (uint64_t)dxbc::FeatureFlags::Val) > 0;
33 #include "llvm/BinaryFormat/DXContainerConstants.def"
34 }
35 
36 template <typename T>
37 static llvm::Error
38 readDescriptorRanges(DXContainerYAML::RootParameterHeaderYaml &Header,
39                      DXContainerYAML::RootSignatureYamlDesc &RootSigDesc,
40                      object::DirectX::DescriptorTableView *DTV) {
41 
42   llvm::Expected<object::DirectX::DescriptorTable<T>> TableOrErr =
43       DTV->read<T>();
44   if (Error E = TableOrErr.takeError())
45     return E;
46   auto Table = *TableOrErr;
47 
48   DXContainerYAML::RootParameterLocationYaml Location(Header);
49   DXContainerYAML::DescriptorTableYaml &TableYaml =
50       RootSigDesc.Parameters.getOrInsertTable(Location);
51   RootSigDesc.Parameters.insertLocation(Location);
52 
53   TableYaml.NumRanges = Table.NumRanges;
54   TableYaml.RangesOffset = Table.RangesOffset;
55 
56   for (const auto &R : Table.Ranges) {
57     DXContainerYAML::DescriptorRangeYaml NewR;
58     NewR.OffsetInDescriptorsFromTableStart =
59         R.OffsetInDescriptorsFromTableStart;
60     NewR.NumDescriptors = R.NumDescriptors;
61     NewR.BaseShaderRegister = R.BaseShaderRegister;
62     NewR.RegisterSpace = R.RegisterSpace;
63     NewR.RangeType = R.RangeType;
64     if constexpr (std::is_same_v<T, dxbc::RTS0::v2::DescriptorRange>) {
65       // Set all flag fields for v2
66 #define DESCRIPTOR_RANGE_FLAG(Num, Enum, Flag)                                 \
67   NewR.Enum =                                                                  \
68       (R.Flags & llvm::to_underlying(dxbc::DescriptorRangeFlags::Enum)) != 0;
69 #include "llvm/BinaryFormat/DXContainerConstants.def"
70     }
71     TableYaml.Ranges.push_back(NewR);
72   }
73 
74   return Error::success();
75 }
76 
77 llvm::Expected<DXContainerYAML::RootSignatureYamlDesc>
78 DXContainerYAML::RootSignatureYamlDesc::create(
79     const object::DirectX::RootSignature &Data) {
80 
81   RootSignatureYamlDesc RootSigDesc;
82   uint32_t Version = Data.getVersion();
83 
84   RootSigDesc.Version = Version;
85   RootSigDesc.NumStaticSamplers = Data.getNumStaticSamplers();
86   RootSigDesc.StaticSamplersOffset = Data.getStaticSamplersOffset();
87   RootSigDesc.NumRootParameters = Data.getNumRootParameters();
88   RootSigDesc.RootParametersOffset = Data.getRootParametersOffset();
89 
90   uint32_t Flags = Data.getFlags();
91   for (const dxbc::RTS0::v1::RootParameterHeader &PH : Data.param_headers()) {
92 
93     if (!dxbc::isValidParameterType(PH.ParameterType))
94       return createStringError(std::errc::invalid_argument,
95                                "Invalid value for parameter type");
96 
97     RootParameterHeaderYaml Header(PH.ParameterType);
98     Header.Offset = PH.ParameterOffset;
99     Header.Type = PH.ParameterType;
100 
101     if (!dxbc::isValidShaderVisibility(PH.ShaderVisibility))
102       return createStringError(std::errc::invalid_argument,
103                                "Invalid value for shader visibility");
104 
105     Header.Visibility = PH.ShaderVisibility;
106 
107     llvm::Expected<object::DirectX::RootParameterView> ParamViewOrErr =
108         Data.getParameter(PH);
109     if (Error E = ParamViewOrErr.takeError())
110       return std::move(E);
111     object::DirectX::RootParameterView ParamView = ParamViewOrErr.get();
112 
113     if (auto *RCV = dyn_cast<object::DirectX::RootConstantView>(&ParamView)) {
114       llvm::Expected<dxbc::RTS0::v1::RootConstants> ConstantsOrErr =
115           RCV->read();
116       if (Error E = ConstantsOrErr.takeError())
117         return std::move(E);
118 
119       auto Constants = *ConstantsOrErr;
120       RootParameterLocationYaml Location(Header);
121       RootConstantsYaml &ConstantYaml =
122           RootSigDesc.Parameters.getOrInsertConstants(Location);
123       RootSigDesc.Parameters.insertLocation(Location);
124       ConstantYaml.Num32BitValues = Constants.Num32BitValues;
125       ConstantYaml.ShaderRegister = Constants.ShaderRegister;
126       ConstantYaml.RegisterSpace = Constants.RegisterSpace;
127 
128     } else if (auto *RDV =
129                    dyn_cast<object::DirectX::RootDescriptorView>(&ParamView)) {
130       llvm::Expected<dxbc::RTS0::v2::RootDescriptor> DescriptorOrErr =
131           RDV->read(Version);
132       if (Error E = DescriptorOrErr.takeError())
133         return std::move(E);
134       auto Descriptor = *DescriptorOrErr;
135       RootParameterLocationYaml Location(Header);
136       RootDescriptorYaml &YamlDescriptor =
137           RootSigDesc.Parameters.getOrInsertDescriptor(Location);
138       RootSigDesc.Parameters.insertLocation(Location);
139 
140       YamlDescriptor.ShaderRegister = Descriptor.ShaderRegister;
141       YamlDescriptor.RegisterSpace = Descriptor.RegisterSpace;
142       if (Version > 1) {
143 #define ROOT_DESCRIPTOR_FLAG(Num, Enum, Flag)                                  \
144   YamlDescriptor.Enum =                                                        \
145       (Descriptor.Flags &                                                      \
146        llvm::to_underlying(dxbc::RootDescriptorFlags::Enum)) > 0;
147 #include "llvm/BinaryFormat/DXContainerConstants.def"
148       }
149     } else if (auto *DTV =
150                    dyn_cast<object::DirectX::DescriptorTableView>(&ParamView)) {
151       if (Version == 1) {
152         if (Error E = readDescriptorRanges<dxbc::RTS0::v1::DescriptorRange>(
153                 Header, RootSigDesc, DTV))
154           return std::move(E);
155       } else if (Version == 2) {
156         if (Error E = readDescriptorRanges<dxbc::RTS0::v2::DescriptorRange>(
157                 Header, RootSigDesc, DTV))
158           return std::move(E);
159       } else
160         llvm_unreachable("Unknown version for DescriptorRanges");
161     }
162   }
163 
164   for (const auto &S : Data.samplers()) {
165     StaticSamplerYamlDesc NewS;
166     NewS.Filter = S.Filter;
167     NewS.AddressU = S.AddressU;
168     NewS.AddressV = S.AddressV;
169     NewS.AddressW = S.AddressW;
170     NewS.MipLODBias = S.MipLODBias;
171     NewS.MaxAnisotropy = S.MaxAnisotropy;
172     NewS.ComparisonFunc = S.ComparisonFunc;
173     NewS.BorderColor = S.BorderColor;
174     NewS.MinLOD = S.MinLOD;
175     NewS.MaxLOD = S.MaxLOD;
176     NewS.ShaderRegister = S.ShaderRegister;
177     NewS.RegisterSpace = S.RegisterSpace;
178     NewS.ShaderVisibility = S.ShaderVisibility;
179 
180     RootSigDesc.StaticSamplers.push_back(NewS);
181   }
182 
183 #define ROOT_SIGNATURE_FLAG(Num, Val)                                          \
184   RootSigDesc.Val = (Flags & llvm::to_underlying(dxbc::RootFlags::Val)) > 0;
185 #include "llvm/BinaryFormat/DXContainerConstants.def"
186   return RootSigDesc;
187 }
188 
189 uint32_t DXContainerYAML::RootDescriptorYaml::getEncodedFlags() const {
190   uint64_t Flags = 0;
191 #define ROOT_DESCRIPTOR_FLAG(Num, Enum, Flag)                                  \
192   if (Enum)                                                                    \
193     Flags |= (uint32_t)dxbc::RootDescriptorFlags::Enum;
194 #include "llvm/BinaryFormat/DXContainerConstants.def"
195   return Flags;
196 }
197 
198 uint32_t DXContainerYAML::RootSignatureYamlDesc::getEncodedFlags() {
199   uint64_t Flag = 0;
200 #define ROOT_SIGNATURE_FLAG(Num, Val)                                          \
201   if (Val)                                                                     \
202     Flag |= (uint32_t)dxbc::RootFlags::Val;
203 #include "llvm/BinaryFormat/DXContainerConstants.def"
204   return Flag;
205 }
206 
207 uint32_t DXContainerYAML::DescriptorRangeYaml::getEncodedFlags() const {
208   uint64_t Flags = 0;
209 #define DESCRIPTOR_RANGE_FLAG(Num, Enum, Flag)                                 \
210   if (Enum)                                                                    \
211     Flags |= (uint32_t)dxbc::DescriptorRangeFlags::Enum;
212 #include "llvm/BinaryFormat/DXContainerConstants.def"
213   return Flags;
214 }
215 
216 uint64_t DXContainerYAML::ShaderFeatureFlags::getEncodedFlags() {
217   uint64_t Flag = 0;
218 #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str)                      \
219   if (Val)                                                                     \
220     Flag |= (uint64_t)dxbc::FeatureFlags::Val;
221 #include "llvm/BinaryFormat/DXContainerConstants.def"
222   return Flag;
223 }
224 
225 DXContainerYAML::ShaderHash::ShaderHash(const dxbc::ShaderHash &Data)
226     : IncludesSource((Data.Flags & static_cast<uint32_t>(
227                                        dxbc::HashFlags::IncludesSource)) != 0),
228       Digest(16, 0) {
229   memcpy(Digest.data(), &Data.Digest[0], 16);
230 }
231 
232 DXContainerYAML::PSVInfo::PSVInfo() : Version(0) {
233   memset(&Info, 0, sizeof(Info));
234 }
235 
236 DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v0::RuntimeInfo *P,
237                                   uint16_t Stage)
238     : Version(0) {
239   memset(&Info, 0, sizeof(Info));
240   memcpy(&Info, P, sizeof(dxbc::PSV::v0::RuntimeInfo));
241 
242   assert(Stage < std::numeric_limits<uint8_t>::max() &&
243          "Stage should be a very small number");
244   // We need to bring the stage in separately since it isn't part of the v1 data
245   // structure.
246   Info.ShaderStage = static_cast<uint8_t>(Stage);
247 }
248 
249 DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v1::RuntimeInfo *P)
250     : Version(1) {
251   memset(&Info, 0, sizeof(Info));
252   memcpy(&Info, P, sizeof(dxbc::PSV::v1::RuntimeInfo));
253 }
254 
255 DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v2::RuntimeInfo *P)
256     : Version(2) {
257   memset(&Info, 0, sizeof(Info));
258   memcpy(&Info, P, sizeof(dxbc::PSV::v2::RuntimeInfo));
259 }
260 
261 DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v3::RuntimeInfo *P,
262                                   StringRef StringTable)
263     : Version(3),
264       EntryName(StringTable.substr(P->EntryNameOffset,
265                                    StringTable.find('\0', P->EntryNameOffset) -
266                                        P->EntryNameOffset)) {
267   memset(&Info, 0, sizeof(Info));
268   memcpy(&Info, P, sizeof(dxbc::PSV::v3::RuntimeInfo));
269 }
270 
271 namespace yaml {
272 
273 void MappingTraits<DXContainerYAML::VersionTuple>::mapping(
274     IO &IO, DXContainerYAML::VersionTuple &Version) {
275   IO.mapRequired("Major", Version.Major);
276   IO.mapRequired("Minor", Version.Minor);
277 }
278 
279 void MappingTraits<DXContainerYAML::FileHeader>::mapping(
280     IO &IO, DXContainerYAML::FileHeader &Header) {
281   IO.mapRequired("Hash", Header.Hash);
282   IO.mapRequired("Version", Header.Version);
283   IO.mapOptional("FileSize", Header.FileSize);
284   IO.mapRequired("PartCount", Header.PartCount);
285   IO.mapOptional("PartOffsets", Header.PartOffsets);
286 }
287 
288 void MappingTraits<DXContainerYAML::DXILProgram>::mapping(
289     IO &IO, DXContainerYAML::DXILProgram &Program) {
290   IO.mapRequired("MajorVersion", Program.MajorVersion);
291   IO.mapRequired("MinorVersion", Program.MinorVersion);
292   IO.mapRequired("ShaderKind", Program.ShaderKind);
293   IO.mapOptional("Size", Program.Size);
294   IO.mapRequired("DXILMajorVersion", Program.DXILMajorVersion);
295   IO.mapRequired("DXILMinorVersion", Program.DXILMinorVersion);
296   IO.mapOptional("DXILSize", Program.DXILSize);
297   IO.mapOptional("DXIL", Program.DXIL);
298 }
299 
300 void MappingTraits<DXContainerYAML::ShaderFeatureFlags>::mapping(
301     IO &IO, DXContainerYAML::ShaderFeatureFlags &Flags) {
302 #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str)                      \
303   IO.mapRequired(#Val, Flags.Val);
304 #include "llvm/BinaryFormat/DXContainerConstants.def"
305 }
306 
307 void MappingTraits<DXContainerYAML::ShaderHash>::mapping(
308     IO &IO, DXContainerYAML::ShaderHash &Hash) {
309   IO.mapRequired("IncludesSource", Hash.IncludesSource);
310   IO.mapRequired("Digest", Hash.Digest);
311 }
312 
313 void MappingTraits<DXContainerYAML::PSVInfo>::mapping(
314     IO &IO, DXContainerYAML::PSVInfo &PSV) {
315   IO.mapRequired("Version", PSV.Version);
316 
317   // Store the PSV version in the YAML context.
318   void *OldContext = IO.getContext();
319   uint32_t Version = PSV.Version;
320   IO.setContext(&Version);
321 
322   // Restore the YAML context on function exit.
323   auto RestoreContext = make_scope_exit([&]() { IO.setContext(OldContext); });
324 
325   // Shader stage is only included in binaries for v1 and later, but we always
326   // include it since it simplifies parsing and file construction.
327   IO.mapRequired("ShaderStage", PSV.Info.ShaderStage);
328   PSV.mapInfoForVersion(IO);
329 
330   IO.mapRequired("ResourceStride", PSV.ResourceStride);
331   IO.mapRequired("Resources", PSV.Resources);
332   if (PSV.Version == 0)
333     return;
334   IO.mapRequired("SigInputElements", PSV.SigInputElements);
335   IO.mapRequired("SigOutputElements", PSV.SigOutputElements);
336   IO.mapRequired("SigPatchOrPrimElements", PSV.SigPatchOrPrimElements);
337 
338   Triple::EnvironmentType Stage = dxbc::getShaderStage(PSV.Info.ShaderStage);
339   if (PSV.Info.UsesViewID) {
340     MutableArrayRef<SmallVector<llvm::yaml::Hex32>> MutableOutMasks(
341         PSV.OutputVectorMasks);
342     IO.mapRequired("OutputVectorMasks", MutableOutMasks);
343     if (Stage == Triple::EnvironmentType::Hull)
344       IO.mapRequired("PatchOrPrimMasks", PSV.PatchOrPrimMasks);
345   }
346   MutableArrayRef<SmallVector<llvm::yaml::Hex32>> MutableIOMap(
347       PSV.InputOutputMap);
348   IO.mapRequired("InputOutputMap", MutableIOMap);
349 
350   if (Stage == Triple::EnvironmentType::Hull)
351     IO.mapRequired("InputPatchMap", PSV.InputPatchMap);
352 
353   if (Stage == Triple::EnvironmentType::Domain)
354     IO.mapRequired("PatchOutputMap", PSV.PatchOutputMap);
355 }
356 
357 void MappingTraits<DXContainerYAML::SignatureParameter>::mapping(
358     IO &IO, DXContainerYAML::SignatureParameter &S) {
359   IO.mapRequired("Stream", S.Stream);
360   IO.mapRequired("Name", S.Name);
361   IO.mapRequired("Index", S.Index);
362   IO.mapRequired("SystemValue", S.SystemValue);
363   IO.mapRequired("CompType", S.CompType);
364   IO.mapRequired("Register", S.Register);
365   IO.mapRequired("Mask", S.Mask);
366   IO.mapRequired("ExclusiveMask", S.ExclusiveMask);
367   IO.mapRequired("MinPrecision", S.MinPrecision);
368 }
369 
370 void MappingTraits<DXContainerYAML::Signature>::mapping(
371     IO &IO, DXContainerYAML::Signature &S) {
372   IO.mapRequired("Parameters", S.Parameters);
373 }
374 
375 void MappingTraits<DXContainerYAML::RootSignatureYamlDesc>::mapping(
376     IO &IO, DXContainerYAML::RootSignatureYamlDesc &S) {
377   IO.mapRequired("Version", S.Version);
378   IO.mapRequired("NumRootParameters", S.NumRootParameters);
379   IO.mapRequired("RootParametersOffset", S.RootParametersOffset);
380   IO.mapRequired("NumStaticSamplers", S.NumStaticSamplers);
381   IO.mapRequired("StaticSamplersOffset", S.StaticSamplersOffset);
382   IO.mapRequired("Parameters", S.Parameters.Locations, S);
383   IO.mapOptional("Samplers", S.StaticSamplers);
384 #define ROOT_SIGNATURE_FLAG(Num, Val) IO.mapOptional(#Val, S.Val, false);
385 #include "llvm/BinaryFormat/DXContainerConstants.def"
386 }
387 
388 void MappingTraits<llvm::DXContainerYAML::DescriptorRangeYaml>::mapping(
389     IO &IO, llvm::DXContainerYAML::DescriptorRangeYaml &R) {
390   IO.mapRequired("RangeType", R.RangeType);
391   // handling the edge case where NumDescriptors might be -1
392   if (IO.outputting()) {
393     if (R.NumDescriptors == UINT_MAX) {
394       int32_t NegOne = -1;
395       IO.mapRequired("NumDescriptors", NegOne);
396     } else
397       IO.mapRequired("NumDescriptors", R.NumDescriptors);
398   } else {
399     int32_t TmpNumDesc = 0;
400     IO.mapRequired("NumDescriptors", TmpNumDesc);
401     R.NumDescriptors = static_cast<uint32_t>(TmpNumDesc);
402   }
403 
404   IO.mapRequired("BaseShaderRegister", R.BaseShaderRegister);
405   IO.mapRequired("RegisterSpace", R.RegisterSpace);
406   IO.mapRequired("OffsetInDescriptorsFromTableStart",
407                  R.OffsetInDescriptorsFromTableStart);
408 #define DESCRIPTOR_RANGE_FLAG(Num, Enum, Flag)                                 \
409   IO.mapOptional(#Flag, R.Enum, false);
410 #include "llvm/BinaryFormat/DXContainerConstants.def"
411 }
412 
413 void MappingTraits<llvm::DXContainerYAML::DescriptorTableYaml>::mapping(
414     IO &IO, llvm::DXContainerYAML::DescriptorTableYaml &T) {
415   IO.mapRequired("NumRanges", T.NumRanges);
416   IO.mapOptional("RangesOffset", T.RangesOffset);
417   IO.mapRequired("Ranges", T.Ranges);
418 }
419 
420 void MappingContextTraits<DXContainerYAML::RootParameterLocationYaml,
421                           DXContainerYAML::RootSignatureYamlDesc>::
422     mapping(IO &IO, DXContainerYAML::RootParameterLocationYaml &L,
423             DXContainerYAML::RootSignatureYamlDesc &S) {
424   IO.mapRequired("ParameterType", L.Header.Type);
425   IO.mapRequired("ShaderVisibility", L.Header.Visibility);
426 
427   switch (L.Header.Type) {
428   case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit): {
429     DXContainerYAML::RootConstantsYaml &Constants =
430         S.Parameters.getOrInsertConstants(L);
431     IO.mapRequired("Constants", Constants);
432     break;
433   }
434   case llvm::to_underlying(dxbc::RootParameterType::CBV):
435   case llvm::to_underlying(dxbc::RootParameterType::SRV):
436   case llvm::to_underlying(dxbc::RootParameterType::UAV): {
437     DXContainerYAML::RootDescriptorYaml &Descriptor =
438         S.Parameters.getOrInsertDescriptor(L);
439     IO.mapRequired("Descriptor", Descriptor);
440     break;
441   }
442   case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
443     DXContainerYAML::DescriptorTableYaml &Table =
444         S.Parameters.getOrInsertTable(L);
445     IO.mapRequired("Table", Table);
446     break;
447   }
448   }
449 }
450 
451 void MappingTraits<llvm::DXContainerYAML::RootConstantsYaml>::mapping(
452     IO &IO, llvm::DXContainerYAML::RootConstantsYaml &C) {
453   IO.mapRequired("Num32BitValues", C.Num32BitValues);
454   IO.mapRequired("RegisterSpace", C.RegisterSpace);
455   IO.mapRequired("ShaderRegister", C.ShaderRegister);
456 }
457 
458 void MappingTraits<llvm::DXContainerYAML::RootDescriptorYaml>::mapping(
459     IO &IO, llvm::DXContainerYAML::RootDescriptorYaml &D) {
460   IO.mapRequired("RegisterSpace", D.RegisterSpace);
461   IO.mapRequired("ShaderRegister", D.ShaderRegister);
462 #define ROOT_DESCRIPTOR_FLAG(Num, Enum, Flag)                                  \
463   IO.mapOptional(#Flag, D.Enum, false);
464 #include "llvm/BinaryFormat/DXContainerConstants.def"
465 }
466 
467 void MappingTraits<llvm::DXContainerYAML::StaticSamplerYamlDesc>::mapping(
468     IO &IO, llvm::DXContainerYAML::StaticSamplerYamlDesc &S) {
469 
470   IO.mapOptional("Filter", S.Filter);
471   IO.mapOptional("AddressU", S.AddressU);
472   IO.mapOptional("AddressV", S.AddressV);
473   IO.mapOptional("AddressW", S.AddressW);
474   IO.mapOptional("MipLODBias", S.MipLODBias);
475   IO.mapOptional("MaxAnisotropy", S.MaxAnisotropy);
476   IO.mapOptional("ComparisonFunc", S.ComparisonFunc);
477   IO.mapOptional("BorderColor", S.BorderColor);
478   IO.mapOptional("MinLOD", S.MinLOD);
479   IO.mapOptional("MaxLOD", S.MaxLOD);
480   IO.mapRequired("ShaderRegister", S.ShaderRegister);
481   IO.mapRequired("RegisterSpace", S.RegisterSpace);
482   IO.mapRequired("ShaderVisibility", S.ShaderVisibility);
483 }
484 
485 void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
486                                                    DXContainerYAML::Part &P) {
487   IO.mapRequired("Name", P.Name);
488   IO.mapRequired("Size", P.Size);
489   IO.mapOptional("Program", P.Program);
490   IO.mapOptional("Flags", P.Flags);
491   IO.mapOptional("Hash", P.Hash);
492   IO.mapOptional("PSVInfo", P.Info);
493   IO.mapOptional("Signature", P.Signature);
494   IO.mapOptional("RootSignature", P.RootSignature);
495 }
496 
497 void MappingTraits<DXContainerYAML::Object>::mapping(
498     IO &IO, DXContainerYAML::Object &Obj) {
499   IO.mapTag("!dxcontainer", true);
500   IO.mapRequired("Header", Obj.Header);
501   IO.mapRequired("Parts", Obj.Parts);
502 }
503 
504 void MappingTraits<DXContainerYAML::ResourceFlags>::mapping(
505     IO &IO, DXContainerYAML::ResourceFlags &Flags) {
506 #define RESOURCE_FLAG(FlagIndex, Enum) IO.mapRequired(#Enum, Flags.Bits.Enum);
507 #include "llvm/BinaryFormat/DXContainerConstants.def"
508 }
509 
510 void MappingTraits<DXContainerYAML::ResourceBindInfo>::mapping(
511     IO &IO, DXContainerYAML::ResourceBindInfo &Res) {
512   IO.mapRequired("Type", Res.Type);
513   IO.mapRequired("Space", Res.Space);
514   IO.mapRequired("LowerBound", Res.LowerBound);
515   IO.mapRequired("UpperBound", Res.UpperBound);
516 
517   const uint32_t *PSVVersion = static_cast<uint32_t *>(IO.getContext());
518   if (*PSVVersion < 2)
519     return;
520 
521   IO.mapRequired("Kind", Res.Kind);
522   IO.mapRequired("Flags", Res.Flags);
523 }
524 
525 void MappingTraits<DXContainerYAML::SignatureElement>::mapping(
526     IO &IO, DXContainerYAML::SignatureElement &El) {
527   IO.mapRequired("Name", El.Name);
528   IO.mapRequired("Indices", El.Indices);
529   IO.mapRequired("StartRow", El.StartRow);
530   IO.mapRequired("Cols", El.Cols);
531   IO.mapRequired("StartCol", El.StartCol);
532   IO.mapRequired("Allocated", El.Allocated);
533   IO.mapRequired("Kind", El.Kind);
534   IO.mapRequired("ComponentType", El.Type);
535   IO.mapRequired("Interpolation", El.Mode);
536   IO.mapRequired("DynamicMask", El.DynamicMask);
537   IO.mapRequired("Stream", El.Stream);
538 }
539 
540 void ScalarEnumerationTraits<dxbc::PSV::SemanticKind>::enumeration(
541     IO &IO, dxbc::PSV::SemanticKind &Value) {
542   for (const auto &E : dxbc::PSV::getSemanticKinds())
543     IO.enumCase(Value, E.Name.str().c_str(), E.Value);
544 }
545 
546 void ScalarEnumerationTraits<dxbc::PSV::ComponentType>::enumeration(
547     IO &IO, dxbc::PSV::ComponentType &Value) {
548   for (const auto &E : dxbc::PSV::getComponentTypes())
549     IO.enumCase(Value, E.Name.str().c_str(), E.Value);
550 }
551 
552 void ScalarEnumerationTraits<dxbc::PSV::InterpolationMode>::enumeration(
553     IO &IO, dxbc::PSV::InterpolationMode &Value) {
554   for (const auto &E : dxbc::PSV::getInterpolationModes())
555     IO.enumCase(Value, E.Name.str().c_str(), E.Value);
556 }
557 
558 void ScalarEnumerationTraits<dxbc::PSV::ResourceType>::enumeration(
559     IO &IO, dxbc::PSV::ResourceType &Value) {
560   for (const auto &E : dxbc::PSV::getResourceTypes())
561     IO.enumCase(Value, E.Name.str().c_str(), E.Value);
562 }
563 
564 void ScalarEnumerationTraits<dxbc::PSV::ResourceKind>::enumeration(
565     IO &IO, dxbc::PSV::ResourceKind &Value) {
566   for (const auto &E : dxbc::PSV::getResourceKinds())
567     IO.enumCase(Value, E.Name.str().c_str(), E.Value);
568 }
569 
570 void ScalarEnumerationTraits<dxbc::D3DSystemValue>::enumeration(
571     IO &IO, dxbc::D3DSystemValue &Value) {
572   for (const auto &E : dxbc::getD3DSystemValues())
573     IO.enumCase(Value, E.Name.str().c_str(), E.Value);
574 }
575 
576 void ScalarEnumerationTraits<dxbc::SigMinPrecision>::enumeration(
577     IO &IO, dxbc::SigMinPrecision &Value) {
578   for (const auto &E : dxbc::getSigMinPrecisions())
579     IO.enumCase(Value, E.Name.str().c_str(), E.Value);
580 }
581 
582 void ScalarEnumerationTraits<dxbc::SigComponentType>::enumeration(
583     IO &IO, dxbc::SigComponentType &Value) {
584   for (const auto &E : dxbc::getSigComponentTypes())
585     IO.enumCase(Value, E.Name.str().c_str(), E.Value);
586 }
587 
588 } // namespace yaml
589 
590 void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
591   dxbc::PipelinePSVInfo &StageInfo = Info.StageInfo;
592   Triple::EnvironmentType Stage = dxbc::getShaderStage(Info.ShaderStage);
593 
594   switch (Stage) {
595   case Triple::EnvironmentType::Pixel:
596     IO.mapRequired("DepthOutput", StageInfo.PS.DepthOutput);
597     IO.mapRequired("SampleFrequency", StageInfo.PS.SampleFrequency);
598     break;
599   case Triple::EnvironmentType::Vertex:
600     IO.mapRequired("OutputPositionPresent", StageInfo.VS.OutputPositionPresent);
601     break;
602   case Triple::EnvironmentType::Geometry:
603     IO.mapRequired("InputPrimitive", StageInfo.GS.InputPrimitive);
604     IO.mapRequired("OutputTopology", StageInfo.GS.OutputTopology);
605     IO.mapRequired("OutputStreamMask", StageInfo.GS.OutputStreamMask);
606     IO.mapRequired("OutputPositionPresent", StageInfo.GS.OutputPositionPresent);
607     break;
608   case Triple::EnvironmentType::Hull:
609     IO.mapRequired("InputControlPointCount",
610                    StageInfo.HS.InputControlPointCount);
611     IO.mapRequired("OutputControlPointCount",
612                    StageInfo.HS.OutputControlPointCount);
613     IO.mapRequired("TessellatorDomain", StageInfo.HS.TessellatorDomain);
614     IO.mapRequired("TessellatorOutputPrimitive",
615                    StageInfo.HS.TessellatorOutputPrimitive);
616     break;
617   case Triple::EnvironmentType::Domain:
618     IO.mapRequired("InputControlPointCount",
619                    StageInfo.DS.InputControlPointCount);
620     IO.mapRequired("OutputPositionPresent", StageInfo.DS.OutputPositionPresent);
621     IO.mapRequired("TessellatorDomain", StageInfo.DS.TessellatorDomain);
622     break;
623   case Triple::EnvironmentType::Mesh:
624     IO.mapRequired("GroupSharedBytesUsed", StageInfo.MS.GroupSharedBytesUsed);
625     IO.mapRequired("GroupSharedBytesDependentOnViewID",
626                    StageInfo.MS.GroupSharedBytesDependentOnViewID);
627     IO.mapRequired("PayloadSizeInBytes", StageInfo.MS.PayloadSizeInBytes);
628     IO.mapRequired("MaxOutputVertices", StageInfo.MS.MaxOutputVertices);
629     IO.mapRequired("MaxOutputPrimitives", StageInfo.MS.MaxOutputPrimitives);
630     break;
631   case Triple::EnvironmentType::Amplification:
632     IO.mapRequired("PayloadSizeInBytes", StageInfo.AS.PayloadSizeInBytes);
633     break;
634   default:
635     break;
636   }
637 
638   IO.mapRequired("MinimumWaveLaneCount", Info.MinimumWaveLaneCount);
639   IO.mapRequired("MaximumWaveLaneCount", Info.MaximumWaveLaneCount);
640 
641   if (Version == 0)
642     return;
643 
644   IO.mapRequired("UsesViewID", Info.UsesViewID);
645 
646   switch (Stage) {
647   case Triple::EnvironmentType::Geometry:
648     IO.mapRequired("MaxVertexCount", Info.GeomData.MaxVertexCount);
649     break;
650   case Triple::EnvironmentType::Hull:
651   case Triple::EnvironmentType::Domain:
652     IO.mapRequired("SigPatchConstOrPrimVectors",
653                    Info.GeomData.SigPatchConstOrPrimVectors);
654     break;
655   case Triple::EnvironmentType::Mesh:
656     IO.mapRequired("SigPrimVectors", Info.GeomData.MeshInfo.SigPrimVectors);
657     IO.mapRequired("MeshOutputTopology",
658                    Info.GeomData.MeshInfo.MeshOutputTopology);
659     break;
660   default:
661     break;
662   }
663 
664   IO.mapRequired("SigInputVectors", Info.SigInputVectors);
665   MutableArrayRef<uint8_t> Vec(Info.SigOutputVectors);
666   IO.mapRequired("SigOutputVectors", Vec);
667 
668   if (Version == 1)
669     return;
670 
671   IO.mapRequired("NumThreadsX", Info.NumThreadsX);
672   IO.mapRequired("NumThreadsY", Info.NumThreadsY);
673   IO.mapRequired("NumThreadsZ", Info.NumThreadsZ);
674 
675   if (Version == 2)
676     return;
677 
678   IO.mapRequired("EntryName", EntryName);
679 }
680 
681 } // namespace llvm
682