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 | |
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 | |
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 | |
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(dest: Digest.data(), src: &Data.Digest[0], n: 16); |
46 | } |
47 | |
48 | DXContainerYAML::PSVInfo::PSVInfo() : Version(0) { |
49 | memset(s: &Info, c: 0, n: sizeof(Info)); |
50 | } |
51 | |
52 | DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v0::RuntimeInfo *P, |
53 | uint16_t Stage) |
54 | : Version(0) { |
55 | memset(s: &Info, c: 0, n: sizeof(Info)); |
56 | memcpy(dest: &Info, src: P, n: 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 | |
65 | DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v1::RuntimeInfo *P) |
66 | : Version(1) { |
67 | memset(s: &Info, c: 0, n: sizeof(Info)); |
68 | memcpy(dest: &Info, src: P, n: sizeof(dxbc::PSV::v1::RuntimeInfo)); |
69 | } |
70 | |
71 | DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v2::RuntimeInfo *P) |
72 | : Version(2) { |
73 | memset(s: &Info, c: 0, n: sizeof(Info)); |
74 | memcpy(dest: &Info, src: P, n: sizeof(dxbc::PSV::v2::RuntimeInfo)); |
75 | } |
76 | |
77 | DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v3::RuntimeInfo *P, |
78 | StringRef StringTable) |
79 | : Version(3), |
80 | EntryName(StringTable.substr(Start: P->EntryNameOffset, |
81 | N: StringTable.find(C: '\0', From: P->EntryNameOffset) - |
82 | P->EntryNameOffset)) { |
83 | memset(s: &Info, c: 0, n: sizeof(Info)); |
84 | memcpy(dest: &Info, src: P, n: sizeof(dxbc::PSV::v3::RuntimeInfo)); |
85 | } |
86 | |
87 | namespace yaml { |
88 | |
89 | void MappingTraits<DXContainerYAML::VersionTuple>::mapping( |
90 | IO &IO, DXContainerYAML::VersionTuple &Version) { |
91 | IO.mapRequired(Key: "Major" , Val&: Version.Major); |
92 | IO.mapRequired(Key: "Minor" , Val&: Version.Minor); |
93 | } |
94 | |
95 | void MappingTraits<DXContainerYAML::FileHeader>::( |
96 | IO &IO, DXContainerYAML::FileHeader &) { |
97 | IO.mapRequired(Key: "Hash" , Val&: Header.Hash); |
98 | IO.mapRequired(Key: "Version" , Val&: Header.Version); |
99 | IO.mapOptional(Key: "FileSize" , Val&: Header.FileSize); |
100 | IO.mapRequired(Key: "PartCount" , Val&: Header.PartCount); |
101 | IO.mapOptional(Key: "PartOffsets" , Val&: Header.PartOffsets); |
102 | } |
103 | |
104 | void MappingTraits<DXContainerYAML::DXILProgram>::mapping( |
105 | IO &IO, DXContainerYAML::DXILProgram &Program) { |
106 | IO.mapRequired(Key: "MajorVersion" , Val&: Program.MajorVersion); |
107 | IO.mapRequired(Key: "MinorVersion" , Val&: Program.MinorVersion); |
108 | IO.mapRequired(Key: "ShaderKind" , Val&: Program.ShaderKind); |
109 | IO.mapOptional(Key: "Size" , Val&: Program.Size); |
110 | IO.mapRequired(Key: "DXILMajorVersion" , Val&: Program.DXILMajorVersion); |
111 | IO.mapRequired(Key: "DXILMinorVersion" , Val&: Program.DXILMinorVersion); |
112 | IO.mapOptional(Key: "DXILSize" , Val&: Program.DXILSize); |
113 | IO.mapOptional(Key: "DXIL" , Val&: Program.DXIL); |
114 | } |
115 | |
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 | |
123 | void MappingTraits<DXContainerYAML::ShaderHash>::mapping( |
124 | IO &IO, DXContainerYAML::ShaderHash &Hash) { |
125 | IO.mapRequired(Key: "IncludesSource" , Val&: Hash.IncludesSource); |
126 | IO.mapRequired(Key: "Digest" , Val&: Hash.Digest); |
127 | } |
128 | |
129 | void MappingTraits<DXContainerYAML::PSVInfo>::mapping( |
130 | IO &IO, DXContainerYAML::PSVInfo &PSV) { |
131 | IO.mapRequired(Key: "Version" , Val&: 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(F: [&]() { 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(Key: "ShaderStage" , Val&: PSV.Info.ShaderStage); |
144 | PSV.mapInfoForVersion(IO); |
145 | |
146 | IO.mapRequired(Key: "ResourceStride" , Val&: PSV.ResourceStride); |
147 | IO.mapRequired(Key: "Resources" , Val&: PSV.Resources); |
148 | if (PSV.Version == 0) |
149 | return; |
150 | IO.mapRequired(Key: "SigInputElements" , Val&: PSV.SigInputElements); |
151 | IO.mapRequired(Key: "SigOutputElements" , Val&: PSV.SigOutputElements); |
152 | IO.mapRequired(Key: "SigPatchOrPrimElements" , Val&: PSV.SigPatchOrPrimElements); |
153 | |
154 | Triple::EnvironmentType Stage = dxbc::getShaderStage(Kind: PSV.Info.ShaderStage); |
155 | if (PSV.Info.UsesViewID) { |
156 | MutableArrayRef<SmallVector<llvm::yaml::Hex32>> MutableOutMasks( |
157 | PSV.OutputVectorMasks); |
158 | IO.mapRequired(Key: "OutputVectorMasks" , Val&: MutableOutMasks); |
159 | if (Stage == Triple::EnvironmentType::Hull) |
160 | IO.mapRequired(Key: "PatchOrPrimMasks" , Val&: PSV.PatchOrPrimMasks); |
161 | } |
162 | MutableArrayRef<SmallVector<llvm::yaml::Hex32>> MutableIOMap( |
163 | PSV.InputOutputMap); |
164 | IO.mapRequired(Key: "InputOutputMap" , Val&: MutableIOMap); |
165 | |
166 | if (Stage == Triple::EnvironmentType::Hull) |
167 | IO.mapRequired(Key: "InputPatchMap" , Val&: PSV.InputPatchMap); |
168 | |
169 | if (Stage == Triple::EnvironmentType::Domain) |
170 | IO.mapRequired(Key: "PatchOutputMap" , Val&: PSV.PatchOutputMap); |
171 | } |
172 | |
173 | void MappingTraits<DXContainerYAML::SignatureParameter>::mapping( |
174 | IO &IO, DXContainerYAML::SignatureParameter &S) { |
175 | IO.mapRequired(Key: "Stream" , Val&: S.Stream); |
176 | IO.mapRequired(Key: "Name" , Val&: S.Name); |
177 | IO.mapRequired(Key: "Index" , Val&: S.Index); |
178 | IO.mapRequired(Key: "SystemValue" , Val&: S.SystemValue); |
179 | IO.mapRequired(Key: "CompType" , Val&: S.CompType); |
180 | IO.mapRequired(Key: "Register" , Val&: S.Register); |
181 | IO.mapRequired(Key: "Mask" , Val&: S.Mask); |
182 | IO.mapRequired(Key: "ExclusiveMask" , Val&: S.ExclusiveMask); |
183 | IO.mapRequired(Key: "MinPrecision" , Val&: S.MinPrecision); |
184 | } |
185 | |
186 | void MappingTraits<DXContainerYAML::Signature>::mapping( |
187 | IO &IO, DXContainerYAML::Signature &S) { |
188 | IO.mapRequired(Key: "Parameters" , Val&: S.Parameters); |
189 | } |
190 | |
191 | void MappingTraits<DXContainerYAML::Part>::mapping(IO &IO, |
192 | DXContainerYAML::Part &P) { |
193 | IO.mapRequired(Key: "Name" , Val&: P.Name); |
194 | IO.mapRequired(Key: "Size" , Val&: P.Size); |
195 | IO.mapOptional(Key: "Program" , Val&: P.Program); |
196 | IO.mapOptional(Key: "Flags" , Val&: P.Flags); |
197 | IO.mapOptional(Key: "Hash" , Val&: P.Hash); |
198 | IO.mapOptional(Key: "PSVInfo" , Val&: P.Info); |
199 | IO.mapOptional(Key: "Signature" , Val&: P.Signature); |
200 | } |
201 | |
202 | void MappingTraits<DXContainerYAML::Object>::mapping( |
203 | IO &IO, DXContainerYAML::Object &Obj) { |
204 | IO.mapTag(Tag: "!dxcontainer" , Default: true); |
205 | IO.mapRequired(Key: "Header" , Val&: Obj.Header); |
206 | IO.mapRequired(Key: "Parts" , Val&: Obj.Parts); |
207 | } |
208 | |
209 | void MappingTraits<DXContainerYAML::ResourceBindInfo>::mapping( |
210 | IO &IO, DXContainerYAML::ResourceBindInfo &Res) { |
211 | IO.mapRequired(Key: "Type" , Val&: Res.Type); |
212 | IO.mapRequired(Key: "Space" , Val&: Res.Space); |
213 | IO.mapRequired(Key: "LowerBound" , Val&: Res.LowerBound); |
214 | IO.mapRequired(Key: "UpperBound" , Val&: Res.UpperBound); |
215 | |
216 | const uint32_t *PSVVersion = static_cast<uint32_t *>(IO.getContext()); |
217 | if (*PSVVersion < 2) |
218 | return; |
219 | |
220 | IO.mapRequired(Key: "Kind" , Val&: Res.Kind); |
221 | IO.mapRequired(Key: "Flags" , Val&: Res.Flags); |
222 | } |
223 | |
224 | void MappingTraits<DXContainerYAML::SignatureElement>::mapping( |
225 | IO &IO, DXContainerYAML::SignatureElement &El) { |
226 | IO.mapRequired(Key: "Name" , Val&: El.Name); |
227 | IO.mapRequired(Key: "Indices" , Val&: El.Indices); |
228 | IO.mapRequired(Key: "StartRow" , Val&: El.StartRow); |
229 | IO.mapRequired(Key: "Cols" , Val&: El.Cols); |
230 | IO.mapRequired(Key: "StartCol" , Val&: El.StartCol); |
231 | IO.mapRequired(Key: "Allocated" , Val&: El.Allocated); |
232 | IO.mapRequired(Key: "Kind" , Val&: El.Kind); |
233 | IO.mapRequired(Key: "ComponentType" , Val&: El.Type); |
234 | IO.mapRequired(Key: "Interpolation" , Val&: El.Mode); |
235 | IO.mapRequired(Key: "DynamicMask" , Val&: El.DynamicMask); |
236 | IO.mapRequired(Key: "Stream" , Val&: El.Stream); |
237 | } |
238 | |
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(Val&: Value, Str: E.Name.str().c_str(), ConstVal: E.Value); |
243 | } |
244 | |
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(Val&: Value, Str: E.Name.str().c_str(), ConstVal: E.Value); |
249 | } |
250 | |
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(Val&: Value, Str: E.Name.str().c_str(), ConstVal: E.Value); |
255 | } |
256 | |
257 | void ScalarEnumerationTraits<dxbc::D3DSystemValue>::enumeration( |
258 | IO &IO, dxbc::D3DSystemValue &Value) { |
259 | for (const auto &E : dxbc::getD3DSystemValues()) |
260 | IO.enumCase(Val&: Value, Str: E.Name.str().c_str(), ConstVal: E.Value); |
261 | } |
262 | |
263 | void ScalarEnumerationTraits<dxbc::SigMinPrecision>::enumeration( |
264 | IO &IO, dxbc::SigMinPrecision &Value) { |
265 | for (const auto &E : dxbc::getSigMinPrecisions()) |
266 | IO.enumCase(Val&: Value, Str: E.Name.str().c_str(), ConstVal: E.Value); |
267 | } |
268 | |
269 | void ScalarEnumerationTraits<dxbc::SigComponentType>::enumeration( |
270 | IO &IO, dxbc::SigComponentType &Value) { |
271 | for (const auto &E : dxbc::getSigComponentTypes()) |
272 | IO.enumCase(Val&: Value, Str: E.Name.str().c_str(), ConstVal: E.Value); |
273 | } |
274 | |
275 | } // namespace yaml |
276 | |
277 | void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) { |
278 | dxbc::PipelinePSVInfo &StageInfo = Info.StageInfo; |
279 | Triple::EnvironmentType Stage = dxbc::getShaderStage(Kind: Info.ShaderStage); |
280 | |
281 | switch (Stage) { |
282 | case Triple::EnvironmentType::Pixel: |
283 | IO.mapRequired(Key: "DepthOutput" , Val&: StageInfo.PS.DepthOutput); |
284 | IO.mapRequired(Key: "SampleFrequency" , Val&: StageInfo.PS.SampleFrequency); |
285 | break; |
286 | case Triple::EnvironmentType::Vertex: |
287 | IO.mapRequired(Key: "OutputPositionPresent" , Val&: StageInfo.VS.OutputPositionPresent); |
288 | break; |
289 | case Triple::EnvironmentType::Geometry: |
290 | IO.mapRequired(Key: "InputPrimitive" , Val&: StageInfo.GS.InputPrimitive); |
291 | IO.mapRequired(Key: "OutputTopology" , Val&: StageInfo.GS.OutputTopology); |
292 | IO.mapRequired(Key: "OutputStreamMask" , Val&: StageInfo.GS.OutputStreamMask); |
293 | IO.mapRequired(Key: "OutputPositionPresent" , Val&: StageInfo.GS.OutputPositionPresent); |
294 | break; |
295 | case Triple::EnvironmentType::Hull: |
296 | IO.mapRequired(Key: "InputControlPointCount" , |
297 | Val&: StageInfo.HS.InputControlPointCount); |
298 | IO.mapRequired(Key: "OutputControlPointCount" , |
299 | Val&: StageInfo.HS.OutputControlPointCount); |
300 | IO.mapRequired(Key: "TessellatorDomain" , Val&: StageInfo.HS.TessellatorDomain); |
301 | IO.mapRequired(Key: "TessellatorOutputPrimitive" , |
302 | Val&: StageInfo.HS.TessellatorOutputPrimitive); |
303 | break; |
304 | case Triple::EnvironmentType::Domain: |
305 | IO.mapRequired(Key: "InputControlPointCount" , |
306 | Val&: StageInfo.DS.InputControlPointCount); |
307 | IO.mapRequired(Key: "OutputPositionPresent" , Val&: StageInfo.DS.OutputPositionPresent); |
308 | IO.mapRequired(Key: "TessellatorDomain" , Val&: StageInfo.DS.TessellatorDomain); |
309 | break; |
310 | case Triple::EnvironmentType::Mesh: |
311 | IO.mapRequired(Key: "GroupSharedBytesUsed" , Val&: StageInfo.MS.GroupSharedBytesUsed); |
312 | IO.mapRequired(Key: "GroupSharedBytesDependentOnViewID" , |
313 | Val&: StageInfo.MS.GroupSharedBytesDependentOnViewID); |
314 | IO.mapRequired(Key: "PayloadSizeInBytes" , Val&: StageInfo.MS.PayloadSizeInBytes); |
315 | IO.mapRequired(Key: "MaxOutputVertices" , Val&: StageInfo.MS.MaxOutputVertices); |
316 | IO.mapRequired(Key: "MaxOutputPrimitives" , Val&: StageInfo.MS.MaxOutputPrimitives); |
317 | break; |
318 | case Triple::EnvironmentType::Amplification: |
319 | IO.mapRequired(Key: "PayloadSizeInBytes" , Val&: StageInfo.AS.PayloadSizeInBytes); |
320 | break; |
321 | default: |
322 | break; |
323 | } |
324 | |
325 | IO.mapRequired(Key: "MinimumWaveLaneCount" , Val&: Info.MinimumWaveLaneCount); |
326 | IO.mapRequired(Key: "MaximumWaveLaneCount" , Val&: Info.MaximumWaveLaneCount); |
327 | |
328 | if (Version == 0) |
329 | return; |
330 | |
331 | IO.mapRequired(Key: "UsesViewID" , Val&: Info.UsesViewID); |
332 | |
333 | switch (Stage) { |
334 | case Triple::EnvironmentType::Geometry: |
335 | IO.mapRequired(Key: "MaxVertexCount" , Val&: Info.GeomData.MaxVertexCount); |
336 | break; |
337 | case Triple::EnvironmentType::Hull: |
338 | case Triple::EnvironmentType::Domain: |
339 | IO.mapRequired(Key: "SigPatchConstOrPrimVectors" , |
340 | Val&: Info.GeomData.SigPatchConstOrPrimVectors); |
341 | break; |
342 | case Triple::EnvironmentType::Mesh: |
343 | IO.mapRequired(Key: "SigPrimVectors" , Val&: Info.GeomData.MeshInfo.SigPrimVectors); |
344 | IO.mapRequired(Key: "MeshOutputTopology" , |
345 | Val&: Info.GeomData.MeshInfo.MeshOutputTopology); |
346 | break; |
347 | default: |
348 | break; |
349 | } |
350 | |
351 | IO.mapRequired(Key: "SigInputVectors" , Val&: Info.SigInputVectors); |
352 | MutableArrayRef<uint8_t> Vec(Info.SigOutputVectors); |
353 | IO.mapRequired(Key: "SigOutputVectors" , Val&: Vec); |
354 | |
355 | if (Version == 1) |
356 | return; |
357 | |
358 | IO.mapRequired(Key: "NumThreadsX" , Val&: Info.NumThreadsX); |
359 | IO.mapRequired(Key: "NumThreadsY" , Val&: Info.NumThreadsY); |
360 | IO.mapRequired(Key: "NumThreadsZ" , Val&: Info.NumThreadsZ); |
361 | |
362 | if (Version == 2) |
363 | return; |
364 | |
365 | IO.mapRequired(Key: "EntryName" , Val&: EntryName); |
366 | } |
367 | |
368 | } // namespace llvm |
369 | |