Files
clang-p2996/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
Chris B b799e9dafa [DX] Support pipeline state masks (#66425)
The DXContainer pipeline state information encodes a bunch of mask
vectors that are used to track things about the inputs and outputs from
each shader.

This adds support for reading and writing them throught he YAML test
interfaces. The writing logic in MC is extremely primitive and we'll
want to revisit the API for that, but since I'm not sure how we'll want
to generate the mask bits from DXIL during code generation I didn't want
to spend too much time on the API.

Fixes #59479
2023-09-15 10:02:54 -05:00

152 lines
5.6 KiB
C++

//===------ dxcontainer2yaml.cpp - obj2yaml conversion tool -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "obj2yaml.h"
#include "llvm/Object/DXContainer.h"
#include "llvm/ObjectYAML/DXContainerYAML.h"
#include "llvm/Support/Error.h"
#include <algorithm>
using namespace llvm;
using namespace llvm::object;
static Expected<DXContainerYAML::Object *>
dumpDXContainer(MemoryBufferRef Source) {
assert(file_magic::dxcontainer_object == identify_magic(Source.getBuffer()));
Expected<DXContainer> ExDXC = DXContainer::create(Source);
if (!ExDXC)
return ExDXC.takeError();
DXContainer Container = *ExDXC;
std::unique_ptr<DXContainerYAML::Object> Obj =
std::make_unique<DXContainerYAML::Object>();
for (uint8_t Byte : Container.getHeader().FileHash.Digest)
Obj->Header.Hash.push_back(Byte);
Obj->Header.Version.Major = Container.getHeader().Version.Major;
Obj->Header.Version.Minor = Container.getHeader().Version.Minor;
Obj->Header.FileSize = Container.getHeader().FileSize;
Obj->Header.PartCount = Container.getHeader().PartCount;
Obj->Header.PartOffsets = std::vector<uint32_t>();
for (const auto P : Container) {
Obj->Header.PartOffsets->push_back(P.Offset);
Obj->Parts.push_back(
DXContainerYAML::Part(P.Part.getName().str(), P.Part.Size));
DXContainerYAML::Part &NewPart = Obj->Parts.back();
dxbc::PartType PT = dxbc::parsePartType(P.Part.getName());
switch (PT) {
case dxbc::PartType::DXIL: {
std::optional<DXContainer::DXILData> DXIL = Container.getDXIL();
assert(DXIL && "Since we are iterating and found a DXIL part, "
"this should never not have a value");
NewPart.Program = DXContainerYAML::DXILProgram{
DXIL->first.MajorVersion,
DXIL->first.MinorVersion,
DXIL->first.ShaderKind,
DXIL->first.Size,
DXIL->first.Bitcode.MajorVersion,
DXIL->first.Bitcode.MinorVersion,
DXIL->first.Bitcode.Offset,
DXIL->first.Bitcode.Size,
std::vector<llvm::yaml::Hex8>(
DXIL->second, DXIL->second + DXIL->first.Bitcode.Size)};
break;
}
case dxbc::PartType::SFI0: {
std::optional<uint64_t> Flags = Container.getShaderFlags();
// Omit the flags in the YAML if they are missing or zero.
if (Flags && *Flags > 0)
NewPart.Flags = DXContainerYAML::ShaderFlags(*Flags);
break;
}
case dxbc::PartType::HASH: {
std::optional<dxbc::ShaderHash> Hash = Container.getShaderHash();
if (Hash && Hash->isPopulated())
NewPart.Hash = DXContainerYAML::ShaderHash(*Hash);
break;
}
case dxbc::PartType::PSV0: {
const auto &PSVInfo = Container.getPSVInfo();
if (!PSVInfo)
break;
if (const auto *P =
std::get_if<dxbc::PSV::v0::RuntimeInfo>(&PSVInfo->getInfo())) {
if (!Container.getDXIL())
break;
NewPart.Info =
DXContainerYAML::PSVInfo(P, Container.getDXIL()->first.ShaderKind);
} else if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(
&PSVInfo->getInfo()))
NewPart.Info = DXContainerYAML::PSVInfo(P);
else if (const auto *P =
std::get_if<dxbc::PSV::v2::RuntimeInfo>(&PSVInfo->getInfo()))
NewPart.Info = DXContainerYAML::PSVInfo(P);
NewPart.Info->ResourceStride = PSVInfo->getResourceStride();
for (auto Res : PSVInfo->getResources())
NewPart.Info->Resources.push_back(Res);
for (auto El : PSVInfo->getSigInputElements())
NewPart.Info->SigInputElements.push_back(
DXContainerYAML::SignatureElement(
El, PSVInfo->getStringTable(),
PSVInfo->getSemanticIndexTable()));
for (auto El : PSVInfo->getSigOutputElements())
NewPart.Info->SigOutputElements.push_back(
DXContainerYAML::SignatureElement(
El, PSVInfo->getStringTable(),
PSVInfo->getSemanticIndexTable()));
for (auto El : PSVInfo->getSigPatchOrPrimElements())
NewPart.Info->SigPatchOrPrimElements.push_back(
DXContainerYAML::SignatureElement(
El, PSVInfo->getStringTable(),
PSVInfo->getSemanticIndexTable()));
if (PSVInfo->usesViewID()) {
for (int I = 0; I < 4; ++I)
for (auto Mask : PSVInfo->getOutputVectorMasks(I))
NewPart.Info->OutputVectorMasks[I].push_back(Mask);
for (auto Mask : PSVInfo->getPatchOrPrimMasks())
NewPart.Info->PatchOrPrimMasks.push_back(Mask);
}
for (int I = 0; I < 4; ++I)
for (auto Mask : PSVInfo->getInputOutputMap(I))
NewPart.Info->InputOutputMap[I].push_back(Mask);
for (auto Mask : PSVInfo->getInputPatchMap())
NewPart.Info->InputPatchMap.push_back(Mask);
for (auto Mask : PSVInfo->getPatchOutputMap())
NewPart.Info->PatchOutputMap.push_back(Mask);
break;
}
case dxbc::PartType::Unknown:
break;
}
}
return Obj.release();
}
llvm::Error dxcontainer2yaml(llvm::raw_ostream &Out,
llvm::MemoryBufferRef Source) {
Expected<DXContainerYAML::Object *> YAMLOrErr = dumpDXContainer(Source);
if (!YAMLOrErr)
return YAMLOrErr.takeError();
std::unique_ptr<DXContainerYAML::Object> YAML(YAMLOrErr.get());
yaml::Output Yout(Out);
Yout << *YAML;
return Error::success();
}