xref: /freebsd/contrib/llvm-project/llvm/lib/ObjectYAML/DXContainerYAML.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/ScopeExit.h"
16  #include "llvm/BinaryFormat/DXContainer.h"
17  #include "llvm/Support/ScopedPrinter.h"
18  
19  namespace llvm {
20  
21  // This assert is duplicated here to leave a breadcrumb of the places that need
22  // to be updated if flags grow past 64-bits.
23  static_assert((uint64_t)dxbc::FeatureFlags::NextUnusedBit <= 1ull << 63,
24                "Shader flag bits exceed enum size.");
25  
ShaderFeatureFlags(uint64_t FlagData)26  DXContainerYAML::ShaderFeatureFlags::ShaderFeatureFlags(uint64_t FlagData) {
27  #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str)                      \
28    Val = (FlagData & (uint64_t)dxbc::FeatureFlags::Val) > 0;
29  #include "llvm/BinaryFormat/DXContainerConstants.def"
30  }
31  
getEncodedFlags()32  uint64_t DXContainerYAML::ShaderFeatureFlags::getEncodedFlags() {
33    uint64_t Flag = 0;
34  #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str)                      \
35    if (Val)                                                                     \
36      Flag |= (uint64_t)dxbc::FeatureFlags::Val;
37  #include "llvm/BinaryFormat/DXContainerConstants.def"
38    return Flag;
39  }
40  
ShaderHash(const dxbc::ShaderHash & Data)41  DXContainerYAML::ShaderHash::ShaderHash(const dxbc::ShaderHash &Data)
42      : IncludesSource((Data.Flags & static_cast<uint32_t>(
43                                         dxbc::HashFlags::IncludesSource)) != 0),
44        Digest(16, 0) {
45    memcpy(Digest.data(), &Data.Digest[0], 16);
46  }
47  
PSVInfo()48  DXContainerYAML::PSVInfo::PSVInfo() : Version(0) {
49    memset(&Info, 0, sizeof(Info));
50  }
51  
PSVInfo(const dxbc::PSV::v0::RuntimeInfo * P,uint16_t Stage)52  DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v0::RuntimeInfo *P,
53                                    uint16_t Stage)
54      : Version(0) {
55    memset(&Info, 0, sizeof(Info));
56    memcpy(&Info, P, sizeof(dxbc::PSV::v0::RuntimeInfo));
57  
58    assert(Stage < std::numeric_limits<uint8_t>::max() &&
59           "Stage should be a very small number");
60    // We need to bring the stage in separately since it isn't part of the v1 data
61    // structure.
62    Info.ShaderStage = static_cast<uint8_t>(Stage);
63  }
64  
PSVInfo(const dxbc::PSV::v1::RuntimeInfo * P)65  DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v1::RuntimeInfo *P)
66      : Version(1) {
67    memset(&Info, 0, sizeof(Info));
68    memcpy(&Info, P, sizeof(dxbc::PSV::v1::RuntimeInfo));
69  }
70  
PSVInfo(const dxbc::PSV::v2::RuntimeInfo * P)71  DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v2::RuntimeInfo *P)
72      : Version(2) {
73    memset(&Info, 0, sizeof(Info));
74    memcpy(&Info, P, sizeof(dxbc::PSV::v2::RuntimeInfo));
75  }
76  
PSVInfo(const dxbc::PSV::v3::RuntimeInfo * P,StringRef StringTable)77  DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v3::RuntimeInfo *P,
78                                    StringRef StringTable)
79      : Version(3),
80        EntryName(StringTable.substr(P->EntryNameOffset,
81                                     StringTable.find('\0', P->EntryNameOffset) -
82                                         P->EntryNameOffset)) {
83    memset(&Info, 0, sizeof(Info));
84    memcpy(&Info, P, sizeof(dxbc::PSV::v3::RuntimeInfo));
85  }
86  
87  namespace yaml {
88  
mapping(IO & IO,DXContainerYAML::VersionTuple & Version)89  void MappingTraits<DXContainerYAML::VersionTuple>::mapping(
90      IO &IO, DXContainerYAML::VersionTuple &Version) {
91    IO.mapRequired("Major", Version.Major);
92    IO.mapRequired("Minor", Version.Minor);
93  }
94  
mapping(IO & IO,DXContainerYAML::FileHeader & Header)95  void MappingTraits<DXContainerYAML::FileHeader>::mapping(
96      IO &IO, DXContainerYAML::FileHeader &Header) {
97    IO.mapRequired("Hash", Header.Hash);
98    IO.mapRequired("Version", Header.Version);
99    IO.mapOptional("FileSize", Header.FileSize);
100    IO.mapRequired("PartCount", Header.PartCount);
101    IO.mapOptional("PartOffsets", Header.PartOffsets);
102  }
103  
mapping(IO & IO,DXContainerYAML::DXILProgram & Program)104  void MappingTraits<DXContainerYAML::DXILProgram>::mapping(
105      IO &IO, DXContainerYAML::DXILProgram &Program) {
106    IO.mapRequired("MajorVersion", Program.MajorVersion);
107    IO.mapRequired("MinorVersion", Program.MinorVersion);
108    IO.mapRequired("ShaderKind", Program.ShaderKind);
109    IO.mapOptional("Size", Program.Size);
110    IO.mapRequired("DXILMajorVersion", Program.DXILMajorVersion);
111    IO.mapRequired("DXILMinorVersion", Program.DXILMinorVersion);
112    IO.mapOptional("DXILSize", Program.DXILSize);
113    IO.mapOptional("DXIL", Program.DXIL);
114  }
115  
mapping(IO & IO,DXContainerYAML::ShaderFeatureFlags & Flags)116  void MappingTraits<DXContainerYAML::ShaderFeatureFlags>::mapping(
117      IO &IO, DXContainerYAML::ShaderFeatureFlags &Flags) {
118  #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str)                      \
119    IO.mapRequired(#Val, Flags.Val);
120  #include "llvm/BinaryFormat/DXContainerConstants.def"
121  }
122  
mapping(IO & IO,DXContainerYAML::ShaderHash & Hash)123  void MappingTraits<DXContainerYAML::ShaderHash>::mapping(
124      IO &IO, DXContainerYAML::ShaderHash &Hash) {
125    IO.mapRequired("IncludesSource", Hash.IncludesSource);
126    IO.mapRequired("Digest", Hash.Digest);
127  }
128  
mapping(IO & IO,DXContainerYAML::PSVInfo & PSV)129  void MappingTraits<DXContainerYAML::PSVInfo>::mapping(
130      IO &IO, DXContainerYAML::PSVInfo &PSV) {
131    IO.mapRequired("Version", PSV.Version);
132  
133    // Store the PSV version in the YAML context.
134    void *OldContext = IO.getContext();
135    uint32_t Version = PSV.Version;
136    IO.setContext(&Version);
137  
138    // Restore the YAML context on function exit.
139    auto RestoreContext = make_scope_exit([&]() { IO.setContext(OldContext); });
140  
141    // Shader stage is only included in binaries for v1 and later, but we always
142    // include it since it simplifies parsing and file construction.
143    IO.mapRequired("ShaderStage", PSV.Info.ShaderStage);
144    PSV.mapInfoForVersion(IO);
145  
146    IO.mapRequired("ResourceStride", PSV.ResourceStride);
147    IO.mapRequired("Resources", PSV.Resources);
148    if (PSV.Version == 0)
149      return;
150    IO.mapRequired("SigInputElements", PSV.SigInputElements);
151    IO.mapRequired("SigOutputElements", PSV.SigOutputElements);
152    IO.mapRequired("SigPatchOrPrimElements", PSV.SigPatchOrPrimElements);
153  
154    Triple::EnvironmentType Stage = dxbc::getShaderStage(PSV.Info.ShaderStage);
155    if (PSV.Info.UsesViewID) {
156      MutableArrayRef<SmallVector<llvm::yaml::Hex32>> MutableOutMasks(
157          PSV.OutputVectorMasks);
158      IO.mapRequired("OutputVectorMasks", MutableOutMasks);
159      if (Stage == Triple::EnvironmentType::Hull)
160        IO.mapRequired("PatchOrPrimMasks", PSV.PatchOrPrimMasks);
161    }
162    MutableArrayRef<SmallVector<llvm::yaml::Hex32>> MutableIOMap(
163        PSV.InputOutputMap);
164    IO.mapRequired("InputOutputMap", MutableIOMap);
165  
166    if (Stage == Triple::EnvironmentType::Hull)
167      IO.mapRequired("InputPatchMap", PSV.InputPatchMap);
168  
169    if (Stage == Triple::EnvironmentType::Domain)
170      IO.mapRequired("PatchOutputMap", PSV.PatchOutputMap);
171  }
172  
mapping(IO & IO,DXContainerYAML::SignatureParameter & S)173  void MappingTraits<DXContainerYAML::SignatureParameter>::mapping(
174      IO &IO, DXContainerYAML::SignatureParameter &S) {
175    IO.mapRequired("Stream", S.Stream);
176    IO.mapRequired("Name", S.Name);
177    IO.mapRequired("Index", S.Index);
178    IO.mapRequired("SystemValue", S.SystemValue);
179    IO.mapRequired("CompType", S.CompType);
180    IO.mapRequired("Register", S.Register);
181    IO.mapRequired("Mask", S.Mask);
182    IO.mapRequired("ExclusiveMask", S.ExclusiveMask);
183    IO.mapRequired("MinPrecision", S.MinPrecision);
184  }
185  
mapping(IO & IO,DXContainerYAML::Signature & S)186  void MappingTraits<DXContainerYAML::Signature>::mapping(
187      IO &IO, DXContainerYAML::Signature &S) {
188    IO.mapRequired("Parameters", S.Parameters);
189  }
190  
mapping(IO & IO,DXContainerYAML::Part & P)191  void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO,
192                                                     DXContainerYAML::Part &P) {
193    IO.mapRequired("Name", P.Name);
194    IO.mapRequired("Size", P.Size);
195    IO.mapOptional("Program", P.Program);
196    IO.mapOptional("Flags", P.Flags);
197    IO.mapOptional("Hash", P.Hash);
198    IO.mapOptional("PSVInfo", P.Info);
199    IO.mapOptional("Signature", P.Signature);
200  }
201  
mapping(IO & IO,DXContainerYAML::Object & Obj)202  void MappingTraits<DXContainerYAML::Object>::mapping(
203      IO &IO, DXContainerYAML::Object &Obj) {
204    IO.mapTag("!dxcontainer", true);
205    IO.mapRequired("Header", Obj.Header);
206    IO.mapRequired("Parts", Obj.Parts);
207  }
208  
mapping(IO & IO,DXContainerYAML::ResourceBindInfo & Res)209  void MappingTraits<DXContainerYAML::ResourceBindInfo>::mapping(
210      IO &IO, DXContainerYAML::ResourceBindInfo &Res) {
211    IO.mapRequired("Type", Res.Type);
212    IO.mapRequired("Space", Res.Space);
213    IO.mapRequired("LowerBound", Res.LowerBound);
214    IO.mapRequired("UpperBound", Res.UpperBound);
215  
216    const uint32_t *PSVVersion = static_cast<uint32_t *>(IO.getContext());
217    if (*PSVVersion < 2)
218      return;
219  
220    IO.mapRequired("Kind", Res.Kind);
221    IO.mapRequired("Flags", Res.Flags);
222  }
223  
mapping(IO & IO,DXContainerYAML::SignatureElement & El)224  void MappingTraits<DXContainerYAML::SignatureElement>::mapping(
225      IO &IO, DXContainerYAML::SignatureElement &El) {
226    IO.mapRequired("Name", El.Name);
227    IO.mapRequired("Indices", El.Indices);
228    IO.mapRequired("StartRow", El.StartRow);
229    IO.mapRequired("Cols", El.Cols);
230    IO.mapRequired("StartCol", El.StartCol);
231    IO.mapRequired("Allocated", El.Allocated);
232    IO.mapRequired("Kind", El.Kind);
233    IO.mapRequired("ComponentType", El.Type);
234    IO.mapRequired("Interpolation", El.Mode);
235    IO.mapRequired("DynamicMask", El.DynamicMask);
236    IO.mapRequired("Stream", El.Stream);
237  }
238  
enumeration(IO & IO,dxbc::PSV::SemanticKind & Value)239  void ScalarEnumerationTraits<dxbc::PSV::SemanticKind>::enumeration(
240      IO &IO, dxbc::PSV::SemanticKind &Value) {
241    for (const auto &E : dxbc::PSV::getSemanticKinds())
242      IO.enumCase(Value, E.Name.str().c_str(), E.Value);
243  }
244  
enumeration(IO & IO,dxbc::PSV::ComponentType & Value)245  void ScalarEnumerationTraits<dxbc::PSV::ComponentType>::enumeration(
246      IO &IO, dxbc::PSV::ComponentType &Value) {
247    for (const auto &E : dxbc::PSV::getComponentTypes())
248      IO.enumCase(Value, E.Name.str().c_str(), E.Value);
249  }
250  
enumeration(IO & IO,dxbc::PSV::InterpolationMode & Value)251  void ScalarEnumerationTraits<dxbc::PSV::InterpolationMode>::enumeration(
252      IO &IO, dxbc::PSV::InterpolationMode &Value) {
253    for (const auto &E : dxbc::PSV::getInterpolationModes())
254      IO.enumCase(Value, E.Name.str().c_str(), E.Value);
255  }
256  
enumeration(IO & IO,dxbc::D3DSystemValue & Value)257  void ScalarEnumerationTraits<dxbc::D3DSystemValue>::enumeration(
258      IO &IO, dxbc::D3DSystemValue &Value) {
259    for (const auto &E : dxbc::getD3DSystemValues())
260      IO.enumCase(Value, E.Name.str().c_str(), E.Value);
261  }
262  
enumeration(IO & IO,dxbc::SigMinPrecision & Value)263  void ScalarEnumerationTraits<dxbc::SigMinPrecision>::enumeration(
264      IO &IO, dxbc::SigMinPrecision &Value) {
265    for (const auto &E : dxbc::getSigMinPrecisions())
266      IO.enumCase(Value, E.Name.str().c_str(), E.Value);
267  }
268  
enumeration(IO & IO,dxbc::SigComponentType & Value)269  void ScalarEnumerationTraits<dxbc::SigComponentType>::enumeration(
270      IO &IO, dxbc::SigComponentType &Value) {
271    for (const auto &E : dxbc::getSigComponentTypes())
272      IO.enumCase(Value, E.Name.str().c_str(), E.Value);
273  }
274  
275  } // namespace yaml
276  
mapInfoForVersion(yaml::IO & IO)277  void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) {
278    dxbc::PipelinePSVInfo &StageInfo = Info.StageInfo;
279    Triple::EnvironmentType Stage = dxbc::getShaderStage(Info.ShaderStage);
280  
281    switch (Stage) {
282    case Triple::EnvironmentType::Pixel:
283      IO.mapRequired("DepthOutput", StageInfo.PS.DepthOutput);
284      IO.mapRequired("SampleFrequency", StageInfo.PS.SampleFrequency);
285      break;
286    case Triple::EnvironmentType::Vertex:
287      IO.mapRequired("OutputPositionPresent", StageInfo.VS.OutputPositionPresent);
288      break;
289    case Triple::EnvironmentType::Geometry:
290      IO.mapRequired("InputPrimitive", StageInfo.GS.InputPrimitive);
291      IO.mapRequired("OutputTopology", StageInfo.GS.OutputTopology);
292      IO.mapRequired("OutputStreamMask", StageInfo.GS.OutputStreamMask);
293      IO.mapRequired("OutputPositionPresent", StageInfo.GS.OutputPositionPresent);
294      break;
295    case Triple::EnvironmentType::Hull:
296      IO.mapRequired("InputControlPointCount",
297                     StageInfo.HS.InputControlPointCount);
298      IO.mapRequired("OutputControlPointCount",
299                     StageInfo.HS.OutputControlPointCount);
300      IO.mapRequired("TessellatorDomain", StageInfo.HS.TessellatorDomain);
301      IO.mapRequired("TessellatorOutputPrimitive",
302                     StageInfo.HS.TessellatorOutputPrimitive);
303      break;
304    case Triple::EnvironmentType::Domain:
305      IO.mapRequired("InputControlPointCount",
306                     StageInfo.DS.InputControlPointCount);
307      IO.mapRequired("OutputPositionPresent", StageInfo.DS.OutputPositionPresent);
308      IO.mapRequired("TessellatorDomain", StageInfo.DS.TessellatorDomain);
309      break;
310    case Triple::EnvironmentType::Mesh:
311      IO.mapRequired("GroupSharedBytesUsed", StageInfo.MS.GroupSharedBytesUsed);
312      IO.mapRequired("GroupSharedBytesDependentOnViewID",
313                     StageInfo.MS.GroupSharedBytesDependentOnViewID);
314      IO.mapRequired("PayloadSizeInBytes", StageInfo.MS.PayloadSizeInBytes);
315      IO.mapRequired("MaxOutputVertices", StageInfo.MS.MaxOutputVertices);
316      IO.mapRequired("MaxOutputPrimitives", StageInfo.MS.MaxOutputPrimitives);
317      break;
318    case Triple::EnvironmentType::Amplification:
319      IO.mapRequired("PayloadSizeInBytes", StageInfo.AS.PayloadSizeInBytes);
320      break;
321    default:
322      break;
323    }
324  
325    IO.mapRequired("MinimumWaveLaneCount", Info.MinimumWaveLaneCount);
326    IO.mapRequired("MaximumWaveLaneCount", Info.MaximumWaveLaneCount);
327  
328    if (Version == 0)
329      return;
330  
331    IO.mapRequired("UsesViewID", Info.UsesViewID);
332  
333    switch (Stage) {
334    case Triple::EnvironmentType::Geometry:
335      IO.mapRequired("MaxVertexCount", Info.GeomData.MaxVertexCount);
336      break;
337    case Triple::EnvironmentType::Hull:
338    case Triple::EnvironmentType::Domain:
339      IO.mapRequired("SigPatchConstOrPrimVectors",
340                     Info.GeomData.SigPatchConstOrPrimVectors);
341      break;
342    case Triple::EnvironmentType::Mesh:
343      IO.mapRequired("SigPrimVectors", Info.GeomData.MeshInfo.SigPrimVectors);
344      IO.mapRequired("MeshOutputTopology",
345                     Info.GeomData.MeshInfo.MeshOutputTopology);
346      break;
347    default:
348      break;
349    }
350  
351    IO.mapRequired("SigInputVectors", Info.SigInputVectors);
352    MutableArrayRef<uint8_t> Vec(Info.SigOutputVectors);
353    IO.mapRequired("SigOutputVectors", Vec);
354  
355    if (Version == 1)
356      return;
357  
358    IO.mapRequired("NumThreadsX", Info.NumThreadsX);
359    IO.mapRequired("NumThreadsY", Info.NumThreadsY);
360    IO.mapRequired("NumThreadsZ", Info.NumThreadsZ);
361  
362    if (Version == 2)
363      return;
364  
365    IO.mapRequired("EntryName", EntryName);
366  }
367  
368  } // namespace llvm
369