llvm-project/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
Chris Bieneman 49dc58f551 [DX] [ObjectYAML] Support DX shader feature flags
DXContainers contain a feature flag part, which stores a bitfield used
to denote what underlying hardware features the shader requires. This
change adds feature flags to the DXContainer YAML tooling to enable
testing generating feature flags during HLSL code generation.

Depends on D133980

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D134315
2022-09-29 12:37:11 -05:00

90 lines
3.1 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: {
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: {
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::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();
}