1 //===------ dxcontainer2yaml.cpp - obj2yaml conversion tool -----*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
10 #include "llvm/Object/DXContainer.h"
11 #include "llvm/ObjectYAML/DXContainerYAML.h"
12 #include "llvm/Support/Error.h"
17 using namespace llvm::object
;
19 static DXContainerYAML::Signature
dumpSignature(const DirectX::Signature
&Sig
) {
20 DXContainerYAML::Signature YAML
;
21 for (auto Param
: Sig
)
22 YAML
.Parameters
.push_back(DXContainerYAML::SignatureParameter
{
23 Param
.Stream
, Sig
.getName(Param
.NameOffset
).str(), Param
.Index
,
24 Param
.SystemValue
, Param
.CompType
, Param
.Register
, Param
.Mask
,
25 Param
.ExclusiveMask
, Param
.MinPrecision
});
29 static Expected
<DXContainerYAML::Object
*>
30 dumpDXContainer(MemoryBufferRef Source
) {
31 assert(file_magic::dxcontainer_object
== identify_magic(Source
.getBuffer()));
33 Expected
<DXContainer
> ExDXC
= DXContainer::create(Source
);
35 return ExDXC
.takeError();
36 DXContainer Container
= *ExDXC
;
38 std::unique_ptr
<DXContainerYAML::Object
> Obj
=
39 std::make_unique
<DXContainerYAML::Object
>();
41 for (uint8_t Byte
: Container
.getHeader().FileHash
.Digest
)
42 Obj
->Header
.Hash
.push_back(Byte
);
43 Obj
->Header
.Version
.Major
= Container
.getHeader().Version
.Major
;
44 Obj
->Header
.Version
.Minor
= Container
.getHeader().Version
.Minor
;
45 Obj
->Header
.FileSize
= Container
.getHeader().FileSize
;
46 Obj
->Header
.PartCount
= Container
.getHeader().PartCount
;
48 Obj
->Header
.PartOffsets
= std::vector
<uint32_t>();
49 for (const auto P
: Container
) {
50 Obj
->Header
.PartOffsets
->push_back(P
.Offset
);
52 DXContainerYAML::Part(P
.Part
.getName().str(), P
.Part
.Size
));
53 DXContainerYAML::Part
&NewPart
= Obj
->Parts
.back();
54 dxbc::PartType PT
= dxbc::parsePartType(P
.Part
.getName());
56 case dxbc::PartType::DXIL
: {
57 std::optional
<DXContainer::DXILData
> DXIL
= Container
.getDXIL();
58 assert(DXIL
&& "Since we are iterating and found a DXIL part, "
59 "this should never not have a value");
60 NewPart
.Program
= DXContainerYAML::DXILProgram
{
61 DXIL
->first
.MajorVersion
,
62 DXIL
->first
.MinorVersion
,
63 DXIL
->first
.ShaderKind
,
65 DXIL
->first
.Bitcode
.MajorVersion
,
66 DXIL
->first
.Bitcode
.MinorVersion
,
67 DXIL
->first
.Bitcode
.Offset
,
68 DXIL
->first
.Bitcode
.Size
,
69 std::vector
<llvm::yaml::Hex8
>(
70 DXIL
->second
, DXIL
->second
+ DXIL
->first
.Bitcode
.Size
)};
73 case dxbc::PartType::SFI0
: {
74 std::optional
<uint64_t> Flags
= Container
.getShaderFlags();
75 // Omit the flags in the YAML if they are missing or zero.
76 if (Flags
&& *Flags
> 0)
77 NewPart
.Flags
= DXContainerYAML::ShaderFlags(*Flags
);
80 case dxbc::PartType::HASH
: {
81 std::optional
<dxbc::ShaderHash
> Hash
= Container
.getShaderHash();
82 if (Hash
&& Hash
->isPopulated())
83 NewPart
.Hash
= DXContainerYAML::ShaderHash(*Hash
);
86 case dxbc::PartType::PSV0
: {
87 const auto &PSVInfo
= Container
.getPSVInfo();
91 std::get_if
<dxbc::PSV::v0::RuntimeInfo
>(&PSVInfo
->getInfo())) {
92 if (!Container
.getDXIL())
95 DXContainerYAML::PSVInfo(P
, Container
.getDXIL()->first
.ShaderKind
);
96 } else if (const auto *P
= std::get_if
<dxbc::PSV::v1::RuntimeInfo
>(
98 NewPart
.Info
= DXContainerYAML::PSVInfo(P
);
99 else if (const auto *P
=
100 std::get_if
<dxbc::PSV::v2::RuntimeInfo
>(&PSVInfo
->getInfo()))
101 NewPart
.Info
= DXContainerYAML::PSVInfo(P
);
102 NewPart
.Info
->ResourceStride
= PSVInfo
->getResourceStride();
103 for (auto Res
: PSVInfo
->getResources())
104 NewPart
.Info
->Resources
.push_back(Res
);
106 for (auto El
: PSVInfo
->getSigInputElements())
107 NewPart
.Info
->SigInputElements
.push_back(
108 DXContainerYAML::SignatureElement(
109 El
, PSVInfo
->getStringTable(),
110 PSVInfo
->getSemanticIndexTable()));
111 for (auto El
: PSVInfo
->getSigOutputElements())
112 NewPart
.Info
->SigOutputElements
.push_back(
113 DXContainerYAML::SignatureElement(
114 El
, PSVInfo
->getStringTable(),
115 PSVInfo
->getSemanticIndexTable()));
116 for (auto El
: PSVInfo
->getSigPatchOrPrimElements())
117 NewPart
.Info
->SigPatchOrPrimElements
.push_back(
118 DXContainerYAML::SignatureElement(
119 El
, PSVInfo
->getStringTable(),
120 PSVInfo
->getSemanticIndexTable()));
122 if (PSVInfo
->usesViewID()) {
123 for (int I
= 0; I
< 4; ++I
)
124 for (auto Mask
: PSVInfo
->getOutputVectorMasks(I
))
125 NewPart
.Info
->OutputVectorMasks
[I
].push_back(Mask
);
126 for (auto Mask
: PSVInfo
->getPatchOrPrimMasks())
127 NewPart
.Info
->PatchOrPrimMasks
.push_back(Mask
);
130 for (int I
= 0; I
< 4; ++I
)
131 for (auto Mask
: PSVInfo
->getInputOutputMap(I
))
132 NewPart
.Info
->InputOutputMap
[I
].push_back(Mask
);
134 for (auto Mask
: PSVInfo
->getInputPatchMap())
135 NewPart
.Info
->InputPatchMap
.push_back(Mask
);
137 for (auto Mask
: PSVInfo
->getPatchOutputMap())
138 NewPart
.Info
->PatchOutputMap
.push_back(Mask
);
142 case dxbc::PartType::ISG1
:
143 NewPart
.Signature
= dumpSignature(Container
.getInputSignature());
145 case dxbc::PartType::OSG1
:
146 NewPart
.Signature
= dumpSignature(Container
.getOutputSignature());
148 case dxbc::PartType::PSG1
:
149 NewPart
.Signature
= dumpSignature(Container
.getPatchConstantSignature());
151 case dxbc::PartType::Unknown
:
156 return Obj
.release();
159 llvm::Error
dxcontainer2yaml(llvm::raw_ostream
&Out
,
160 llvm::MemoryBufferRef Source
) {
161 Expected
<DXContainerYAML::Object
*> YAMLOrErr
= dumpDXContainer(Source
);
163 return YAMLOrErr
.takeError();
165 std::unique_ptr
<DXContainerYAML::Object
> YAML(YAMLOrErr
.get());
166 yaml::Output
Yout(Out
);
169 return Error::success();