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