1 //===- DXContainerYAML.cpp - DXContainer YAMLIO implementation ------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines classes for handling the YAML representation of
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ObjectYAML/DXContainerYAML.h"
15 #include "llvm/ADT/ScopeExit.h"
16 #include "llvm/BinaryFormat/DXContainer.h"
17 #include "llvm/Support/ScopedPrinter.h"
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.");
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"
32 uint64_t DXContainerYAML::ShaderFeatureFlags::getEncodedFlags() {
34 #define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str) \
36 Flag |= (uint64_t)dxbc::FeatureFlags::Val;
37 #include "llvm/BinaryFormat/DXContainerConstants.def"
41 DXContainerYAML::ShaderHash::ShaderHash(const dxbc::ShaderHash
&Data
)
42 : IncludesSource((Data
.Flags
& static_cast<uint32_t>(
43 dxbc::HashFlags::IncludesSource
)) != 0),
45 memcpy(Digest
.data(), &Data
.Digest
[0], 16);
48 DXContainerYAML::PSVInfo::PSVInfo() : Version(0) {
49 memset(&Info
, 0, sizeof(Info
));
52 DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v0::RuntimeInfo
*P
,
55 memset(&Info
, 0, sizeof(Info
));
56 memcpy(&Info
, P
, sizeof(dxbc::PSV::v0::RuntimeInfo
));
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
62 Info
.ShaderStage
= static_cast<uint8_t>(Stage
);
65 DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v1::RuntimeInfo
*P
)
67 memset(&Info
, 0, sizeof(Info
));
68 memcpy(&Info
, P
, sizeof(dxbc::PSV::v1::RuntimeInfo
));
71 DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v2::RuntimeInfo
*P
)
73 memset(&Info
, 0, sizeof(Info
));
74 memcpy(&Info
, P
, sizeof(dxbc::PSV::v2::RuntimeInfo
));
77 DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v3::RuntimeInfo
*P
,
78 StringRef StringTable
)
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
));
89 void MappingTraits
<DXContainerYAML::VersionTuple
>::mapping(
90 IO
&IO
, DXContainerYAML::VersionTuple
&Version
) {
91 IO
.mapRequired("Major", Version
.Major
);
92 IO
.mapRequired("Minor", Version
.Minor
);
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
);
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
);
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"
123 void MappingTraits
<DXContainerYAML::ShaderHash
>::mapping(
124 IO
&IO
, DXContainerYAML::ShaderHash
&Hash
) {
125 IO
.mapRequired("IncludesSource", Hash
.IncludesSource
);
126 IO
.mapRequired("Digest", Hash
.Digest
);
129 void MappingTraits
<DXContainerYAML::PSVInfo
>::mapping(
130 IO
&IO
, DXContainerYAML::PSVInfo
&PSV
) {
131 IO
.mapRequired("Version", PSV
.Version
);
133 // Store the PSV version in the YAML context.
134 void *OldContext
= IO
.getContext();
135 uint32_t Version
= PSV
.Version
;
136 IO
.setContext(&Version
);
138 // Restore the YAML context on function exit.
139 auto RestoreContext
= make_scope_exit([&]() { IO
.setContext(OldContext
); });
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
);
146 IO
.mapRequired("ResourceStride", PSV
.ResourceStride
);
147 IO
.mapRequired("Resources", PSV
.Resources
);
148 if (PSV
.Version
== 0)
150 IO
.mapRequired("SigInputElements", PSV
.SigInputElements
);
151 IO
.mapRequired("SigOutputElements", PSV
.SigOutputElements
);
152 IO
.mapRequired("SigPatchOrPrimElements", PSV
.SigPatchOrPrimElements
);
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
);
162 MutableArrayRef
<SmallVector
<llvm::yaml::Hex32
>> MutableIOMap(
164 IO
.mapRequired("InputOutputMap", MutableIOMap
);
166 if (Stage
== Triple::EnvironmentType::Hull
)
167 IO
.mapRequired("InputPatchMap", PSV
.InputPatchMap
);
169 if (Stage
== Triple::EnvironmentType::Domain
)
170 IO
.mapRequired("PatchOutputMap", PSV
.PatchOutputMap
);
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
);
186 void MappingTraits
<DXContainerYAML::Signature
>::mapping(
187 IO
&IO
, DXContainerYAML::Signature
&S
) {
188 IO
.mapRequired("Parameters", S
.Parameters
);
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
);
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
);
209 void MappingTraits
<DXContainerYAML::ResourceFlags
>::mapping(
210 IO
&IO
, DXContainerYAML::ResourceFlags
&Flags
) {
211 #define RESOURCE_FLAG(FlagIndex, Enum) IO.mapRequired(#Enum, Flags.Bits.Enum);
212 #include "llvm/BinaryFormat/DXContainerConstants.def"
215 void MappingTraits
<DXContainerYAML::ResourceBindInfo
>::mapping(
216 IO
&IO
, DXContainerYAML::ResourceBindInfo
&Res
) {
217 IO
.mapRequired("Type", Res
.Type
);
218 IO
.mapRequired("Space", Res
.Space
);
219 IO
.mapRequired("LowerBound", Res
.LowerBound
);
220 IO
.mapRequired("UpperBound", Res
.UpperBound
);
222 const uint32_t *PSVVersion
= static_cast<uint32_t *>(IO
.getContext());
226 IO
.mapRequired("Kind", Res
.Kind
);
227 IO
.mapRequired("Flags", Res
.Flags
);
230 void MappingTraits
<DXContainerYAML::SignatureElement
>::mapping(
231 IO
&IO
, DXContainerYAML::SignatureElement
&El
) {
232 IO
.mapRequired("Name", El
.Name
);
233 IO
.mapRequired("Indices", El
.Indices
);
234 IO
.mapRequired("StartRow", El
.StartRow
);
235 IO
.mapRequired("Cols", El
.Cols
);
236 IO
.mapRequired("StartCol", El
.StartCol
);
237 IO
.mapRequired("Allocated", El
.Allocated
);
238 IO
.mapRequired("Kind", El
.Kind
);
239 IO
.mapRequired("ComponentType", El
.Type
);
240 IO
.mapRequired("Interpolation", El
.Mode
);
241 IO
.mapRequired("DynamicMask", El
.DynamicMask
);
242 IO
.mapRequired("Stream", El
.Stream
);
245 void ScalarEnumerationTraits
<dxbc::PSV::SemanticKind
>::enumeration(
246 IO
&IO
, dxbc::PSV::SemanticKind
&Value
) {
247 for (const auto &E
: dxbc::PSV::getSemanticKinds())
248 IO
.enumCase(Value
, E
.Name
.str().c_str(), E
.Value
);
251 void ScalarEnumerationTraits
<dxbc::PSV::ComponentType
>::enumeration(
252 IO
&IO
, dxbc::PSV::ComponentType
&Value
) {
253 for (const auto &E
: dxbc::PSV::getComponentTypes())
254 IO
.enumCase(Value
, E
.Name
.str().c_str(), E
.Value
);
257 void ScalarEnumerationTraits
<dxbc::PSV::InterpolationMode
>::enumeration(
258 IO
&IO
, dxbc::PSV::InterpolationMode
&Value
) {
259 for (const auto &E
: dxbc::PSV::getInterpolationModes())
260 IO
.enumCase(Value
, E
.Name
.str().c_str(), E
.Value
);
263 void ScalarEnumerationTraits
<dxbc::PSV::ResourceType
>::enumeration(
264 IO
&IO
, dxbc::PSV::ResourceType
&Value
) {
265 for (const auto &E
: dxbc::PSV::getResourceTypes())
266 IO
.enumCase(Value
, E
.Name
.str().c_str(), E
.Value
);
269 void ScalarEnumerationTraits
<dxbc::PSV::ResourceKind
>::enumeration(
270 IO
&IO
, dxbc::PSV::ResourceKind
&Value
) {
271 for (const auto &E
: dxbc::PSV::getResourceKinds())
272 IO
.enumCase(Value
, E
.Name
.str().c_str(), E
.Value
);
275 void ScalarEnumerationTraits
<dxbc::D3DSystemValue
>::enumeration(
276 IO
&IO
, dxbc::D3DSystemValue
&Value
) {
277 for (const auto &E
: dxbc::getD3DSystemValues())
278 IO
.enumCase(Value
, E
.Name
.str().c_str(), E
.Value
);
281 void ScalarEnumerationTraits
<dxbc::SigMinPrecision
>::enumeration(
282 IO
&IO
, dxbc::SigMinPrecision
&Value
) {
283 for (const auto &E
: dxbc::getSigMinPrecisions())
284 IO
.enumCase(Value
, E
.Name
.str().c_str(), E
.Value
);
287 void ScalarEnumerationTraits
<dxbc::SigComponentType
>::enumeration(
288 IO
&IO
, dxbc::SigComponentType
&Value
) {
289 for (const auto &E
: dxbc::getSigComponentTypes())
290 IO
.enumCase(Value
, E
.Name
.str().c_str(), E
.Value
);
295 void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO
&IO
) {
296 dxbc::PipelinePSVInfo
&StageInfo
= Info
.StageInfo
;
297 Triple::EnvironmentType Stage
= dxbc::getShaderStage(Info
.ShaderStage
);
300 case Triple::EnvironmentType::Pixel
:
301 IO
.mapRequired("DepthOutput", StageInfo
.PS
.DepthOutput
);
302 IO
.mapRequired("SampleFrequency", StageInfo
.PS
.SampleFrequency
);
304 case Triple::EnvironmentType::Vertex
:
305 IO
.mapRequired("OutputPositionPresent", StageInfo
.VS
.OutputPositionPresent
);
307 case Triple::EnvironmentType::Geometry
:
308 IO
.mapRequired("InputPrimitive", StageInfo
.GS
.InputPrimitive
);
309 IO
.mapRequired("OutputTopology", StageInfo
.GS
.OutputTopology
);
310 IO
.mapRequired("OutputStreamMask", StageInfo
.GS
.OutputStreamMask
);
311 IO
.mapRequired("OutputPositionPresent", StageInfo
.GS
.OutputPositionPresent
);
313 case Triple::EnvironmentType::Hull
:
314 IO
.mapRequired("InputControlPointCount",
315 StageInfo
.HS
.InputControlPointCount
);
316 IO
.mapRequired("OutputControlPointCount",
317 StageInfo
.HS
.OutputControlPointCount
);
318 IO
.mapRequired("TessellatorDomain", StageInfo
.HS
.TessellatorDomain
);
319 IO
.mapRequired("TessellatorOutputPrimitive",
320 StageInfo
.HS
.TessellatorOutputPrimitive
);
322 case Triple::EnvironmentType::Domain
:
323 IO
.mapRequired("InputControlPointCount",
324 StageInfo
.DS
.InputControlPointCount
);
325 IO
.mapRequired("OutputPositionPresent", StageInfo
.DS
.OutputPositionPresent
);
326 IO
.mapRequired("TessellatorDomain", StageInfo
.DS
.TessellatorDomain
);
328 case Triple::EnvironmentType::Mesh
:
329 IO
.mapRequired("GroupSharedBytesUsed", StageInfo
.MS
.GroupSharedBytesUsed
);
330 IO
.mapRequired("GroupSharedBytesDependentOnViewID",
331 StageInfo
.MS
.GroupSharedBytesDependentOnViewID
);
332 IO
.mapRequired("PayloadSizeInBytes", StageInfo
.MS
.PayloadSizeInBytes
);
333 IO
.mapRequired("MaxOutputVertices", StageInfo
.MS
.MaxOutputVertices
);
334 IO
.mapRequired("MaxOutputPrimitives", StageInfo
.MS
.MaxOutputPrimitives
);
336 case Triple::EnvironmentType::Amplification
:
337 IO
.mapRequired("PayloadSizeInBytes", StageInfo
.AS
.PayloadSizeInBytes
);
343 IO
.mapRequired("MinimumWaveLaneCount", Info
.MinimumWaveLaneCount
);
344 IO
.mapRequired("MaximumWaveLaneCount", Info
.MaximumWaveLaneCount
);
349 IO
.mapRequired("UsesViewID", Info
.UsesViewID
);
352 case Triple::EnvironmentType::Geometry
:
353 IO
.mapRequired("MaxVertexCount", Info
.GeomData
.MaxVertexCount
);
355 case Triple::EnvironmentType::Hull
:
356 case Triple::EnvironmentType::Domain
:
357 IO
.mapRequired("SigPatchConstOrPrimVectors",
358 Info
.GeomData
.SigPatchConstOrPrimVectors
);
360 case Triple::EnvironmentType::Mesh
:
361 IO
.mapRequired("SigPrimVectors", Info
.GeomData
.MeshInfo
.SigPrimVectors
);
362 IO
.mapRequired("MeshOutputTopology",
363 Info
.GeomData
.MeshInfo
.MeshOutputTopology
);
369 IO
.mapRequired("SigInputVectors", Info
.SigInputVectors
);
370 MutableArrayRef
<uint8_t> Vec(Info
.SigOutputVectors
);
371 IO
.mapRequired("SigOutputVectors", Vec
);
376 IO
.mapRequired("NumThreadsX", Info
.NumThreadsX
);
377 IO
.mapRequired("NumThreadsY", Info
.NumThreadsY
);
378 IO
.mapRequired("NumThreadsZ", Info
.NumThreadsZ
);
383 IO
.mapRequired("EntryName", EntryName
);