184 lines · cpp
1//===------ dxcontainer2yaml.cpp - obj2yaml conversion tool -----*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "obj2yaml.h"10#include "llvm/Object/DXContainer.h"11#include "llvm/ObjectYAML/DXContainerYAML.h"12#include "llvm/Support/Error.h"13 14#include <algorithm>15 16using namespace llvm;17using namespace llvm::object;18 19static 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});26 return YAML;27}28 29static Expected<DXContainerYAML::Object *>30dumpDXContainer(MemoryBufferRef Source) {31 assert(file_magic::dxcontainer_object == identify_magic(Source.getBuffer()));32 33 Expected<DXContainer> ExDXC = DXContainer::create(Source);34 if (!ExDXC)35 return ExDXC.takeError();36 DXContainer Container = *ExDXC;37 38 std::unique_ptr<DXContainerYAML::Object> Obj =39 std::make_unique<DXContainerYAML::Object>();40 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;47 48 Obj->Header.PartOffsets = std::vector<uint32_t>();49 for (const auto P : Container) {50 Obj->Header.PartOffsets->push_back(P.Offset);51 Obj->Parts.push_back(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());55 switch (PT) {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.getMajorVersion(),62 DXIL->first.getMinorVersion(),63 DXIL->first.ShaderKind,64 DXIL->first.Size,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)};71 break;72 }73 case dxbc::PartType::SFI0: {74 std::optional<uint64_t> Flags = Container.getShaderFeatureFlags();75 // Omit the flags in the YAML if they are missing or zero.76 if (Flags && *Flags > 0)77 NewPart.Flags = DXContainerYAML::ShaderFeatureFlags(*Flags);78 break;79 }80 case dxbc::PartType::HASH: {81 std::optional<dxbc::ShaderHash> Hash = Container.getShaderHash();82 if (Hash && Hash->isPopulated())83 NewPart.Hash = DXContainerYAML::ShaderHash(*Hash);84 break;85 }86 case dxbc::PartType::PSV0: {87 const auto &PSVInfo = Container.getPSVInfo();88 if (!PSVInfo)89 break;90 if (const auto *P =91 std::get_if<dxbc::PSV::v0::RuntimeInfo>(&PSVInfo->getInfo())) {92 if (!Container.getDXIL())93 break;94 NewPart.Info =95 DXContainerYAML::PSVInfo(P, Container.getDXIL()->first.ShaderKind);96 } else if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(97 &PSVInfo->getInfo()))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 else if (const auto *P =103 std::get_if<dxbc::PSV::v3::RuntimeInfo>(&PSVInfo->getInfo()))104 NewPart.Info = DXContainerYAML::PSVInfo(P, PSVInfo->getStringTable());105 NewPart.Info->ResourceStride = PSVInfo->getResourceStride();106 for (auto Res : PSVInfo->getResources())107 NewPart.Info->Resources.push_back(Res);108 109 for (auto El : PSVInfo->getSigInputElements())110 NewPart.Info->SigInputElements.push_back(111 DXContainerYAML::SignatureElement(112 El, PSVInfo->getStringTable(),113 PSVInfo->getSemanticIndexTable()));114 for (auto El : PSVInfo->getSigOutputElements())115 NewPart.Info->SigOutputElements.push_back(116 DXContainerYAML::SignatureElement(117 El, PSVInfo->getStringTable(),118 PSVInfo->getSemanticIndexTable()));119 for (auto El : PSVInfo->getSigPatchOrPrimElements())120 NewPart.Info->SigPatchOrPrimElements.push_back(121 DXContainerYAML::SignatureElement(122 El, PSVInfo->getStringTable(),123 PSVInfo->getSemanticIndexTable()));124 125 if (PSVInfo->usesViewID()) {126 for (int I = 0; I < 4; ++I)127 for (auto Mask : PSVInfo->getOutputVectorMasks(I))128 NewPart.Info->OutputVectorMasks[I].push_back(Mask);129 for (auto Mask : PSVInfo->getPatchOrPrimMasks())130 NewPart.Info->PatchOrPrimMasks.push_back(Mask);131 }132 133 for (int I = 0; I < 4; ++I)134 for (auto Mask : PSVInfo->getInputOutputMap(I))135 NewPart.Info->InputOutputMap[I].push_back(Mask);136 137 for (auto Mask : PSVInfo->getInputPatchMap())138 NewPart.Info->InputPatchMap.push_back(Mask);139 140 for (auto Mask : PSVInfo->getPatchOutputMap())141 NewPart.Info->PatchOutputMap.push_back(Mask);142 143 break;144 }145 case dxbc::PartType::ISG1:146 NewPart.Signature = dumpSignature(Container.getInputSignature());147 break;148 case dxbc::PartType::OSG1:149 NewPart.Signature = dumpSignature(Container.getOutputSignature());150 break;151 case dxbc::PartType::PSG1:152 NewPart.Signature = dumpSignature(Container.getPatchConstantSignature());153 break;154 case dxbc::PartType::Unknown:155 break;156 case dxbc::PartType::RTS0:157 std::optional<DirectX::RootSignature> RS = Container.getRootSignature();158 if (RS.has_value()) {159 auto RootSigDescOrErr =160 DXContainerYAML::RootSignatureYamlDesc::create(*RS);161 if (Error E = RootSigDescOrErr.takeError())162 return std::move(E);163 NewPart.RootSignature = RootSigDescOrErr.get();164 }165 break;166 }167 }168 169 return Obj.release();170}171 172llvm::Error dxcontainer2yaml(llvm::raw_ostream &Out,173 llvm::MemoryBufferRef Source) {174 Expected<DXContainerYAML::Object *> YAMLOrErr = dumpDXContainer(Source);175 if (!YAMLOrErr)176 return YAMLOrErr.takeError();177 178 std::unique_ptr<DXContainerYAML::Object> YAML(YAMLOrErr.get());179 yaml::Output Yout(Out);180 Yout << *YAML;181 182 return Error::success();183}184