This PR updates the YAML representation of DXContainer to support Root Signature 1.2, this also requires updating the write logic to support testing.
183 lines
7.5 KiB
C++
183 lines
7.5 KiB
C++
//===- llvm/MC/DXContainerRootSignature.cpp - RootSignature -*- 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 "llvm/MC/DXContainerRootSignature.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/Support/EndianStream.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::mcdxbc;
|
|
|
|
static uint32_t writePlaceholder(raw_svector_ostream &Stream) {
|
|
const uint32_t DummyValue = std::numeric_limits<uint32_t>::max();
|
|
uint32_t Offset = Stream.tell();
|
|
support::endian::write(Stream, DummyValue, llvm::endianness::little);
|
|
return Offset;
|
|
}
|
|
|
|
static uint32_t rewriteOffsetToCurrentByte(raw_svector_ostream &Stream,
|
|
uint32_t Offset) {
|
|
uint32_t ByteOffset = Stream.tell();
|
|
uint32_t Value =
|
|
support::endian::byte_swap<uint32_t, llvm::endianness::little>(
|
|
ByteOffset);
|
|
Stream.pwrite(reinterpret_cast<const char *>(&Value), sizeof(Value), Offset);
|
|
return ByteOffset;
|
|
}
|
|
|
|
size_t RootSignatureDesc::getSize() const {
|
|
uint32_t StaticSamplersOffset = computeStaticSamplersOffset();
|
|
size_t StaticSamplersSize = sizeof(dxbc::RTS0::v1::StaticSampler);
|
|
if (Version > 2)
|
|
StaticSamplersSize = sizeof(dxbc::RTS0::v3::StaticSampler);
|
|
|
|
return size_t(StaticSamplersOffset) +
|
|
(StaticSamplersSize * StaticSamplers.size());
|
|
}
|
|
|
|
uint32_t RootSignatureDesc::computeRootParametersOffset() const {
|
|
return sizeof(dxbc::RTS0::v1::RootSignatureHeader);
|
|
}
|
|
|
|
uint32_t RootSignatureDesc::computeStaticSamplersOffset() const {
|
|
uint32_t Offset = computeRootParametersOffset();
|
|
|
|
for (const RootParameterInfo &I : ParametersContainer) {
|
|
Offset += sizeof(dxbc::RTS0::v1::RootParameterHeader);
|
|
switch (I.Type) {
|
|
case dxbc::RootParameterType::Constants32Bit:
|
|
Offset += sizeof(dxbc::RTS0::v1::RootConstants);
|
|
break;
|
|
case dxbc::RootParameterType::CBV:
|
|
case dxbc::RootParameterType::SRV:
|
|
case dxbc::RootParameterType::UAV:
|
|
if (Version == 1)
|
|
Offset += sizeof(dxbc::RTS0::v1::RootDescriptor);
|
|
else
|
|
Offset += sizeof(dxbc::RTS0::v2::RootDescriptor);
|
|
|
|
break;
|
|
case dxbc::RootParameterType::DescriptorTable:
|
|
const DescriptorTable &Table =
|
|
ParametersContainer.getDescriptorTable(I.Location);
|
|
|
|
// 4 bytes for the number of ranges in table and
|
|
// 4 bytes for the ranges offset
|
|
Offset += 2 * sizeof(uint32_t);
|
|
if (Version == 1)
|
|
Offset += sizeof(dxbc::RTS0::v1::DescriptorRange) * Table.Ranges.size();
|
|
else
|
|
Offset += sizeof(dxbc::RTS0::v2::DescriptorRange) * Table.Ranges.size();
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Offset;
|
|
}
|
|
|
|
void RootSignatureDesc::write(raw_ostream &OS) const {
|
|
SmallString<256> Storage;
|
|
raw_svector_ostream BOS(Storage);
|
|
BOS.reserveExtraSpace(getSize());
|
|
|
|
const uint32_t NumParameters = ParametersContainer.size();
|
|
const uint32_t NumSamplers = StaticSamplers.size();
|
|
support::endian::write(BOS, Version, llvm::endianness::little);
|
|
support::endian::write(BOS, NumParameters, llvm::endianness::little);
|
|
support::endian::write(BOS, RootParameterOffset, llvm::endianness::little);
|
|
support::endian::write(BOS, NumSamplers, llvm::endianness::little);
|
|
uint32_t SSO = writePlaceholder(BOS);
|
|
support::endian::write(BOS, Flags, llvm::endianness::little);
|
|
|
|
SmallVector<uint32_t> ParamsOffsets;
|
|
for (const RootParameterInfo &I : ParametersContainer) {
|
|
support::endian::write(BOS, I.Type, llvm::endianness::little);
|
|
support::endian::write(BOS, I.Visibility, llvm::endianness::little);
|
|
|
|
ParamsOffsets.push_back(writePlaceholder(BOS));
|
|
}
|
|
|
|
assert(NumParameters == ParamsOffsets.size());
|
|
for (size_t I = 0; I < NumParameters; ++I) {
|
|
rewriteOffsetToCurrentByte(BOS, ParamsOffsets[I]);
|
|
const RootParameterInfo &Info = ParametersContainer.getInfo(I);
|
|
switch (Info.Type) {
|
|
case dxbc::RootParameterType::Constants32Bit: {
|
|
const mcdxbc::RootConstants &Constants =
|
|
ParametersContainer.getConstant(Info.Location);
|
|
support::endian::write(BOS, Constants.ShaderRegister,
|
|
llvm::endianness::little);
|
|
support::endian::write(BOS, Constants.RegisterSpace,
|
|
llvm::endianness::little);
|
|
support::endian::write(BOS, Constants.Num32BitValues,
|
|
llvm::endianness::little);
|
|
break;
|
|
}
|
|
case dxbc::RootParameterType::CBV:
|
|
case dxbc::RootParameterType::SRV:
|
|
case dxbc::RootParameterType::UAV: {
|
|
const mcdxbc::RootDescriptor &Descriptor =
|
|
ParametersContainer.getRootDescriptor(Info.Location);
|
|
|
|
support::endian::write(BOS, Descriptor.ShaderRegister,
|
|
llvm::endianness::little);
|
|
support::endian::write(BOS, Descriptor.RegisterSpace,
|
|
llvm::endianness::little);
|
|
if (Version > 1)
|
|
support::endian::write(BOS, Descriptor.Flags, llvm::endianness::little);
|
|
break;
|
|
}
|
|
case dxbc::RootParameterType::DescriptorTable: {
|
|
const DescriptorTable &Table =
|
|
ParametersContainer.getDescriptorTable(Info.Location);
|
|
support::endian::write(BOS, (uint32_t)Table.Ranges.size(),
|
|
llvm::endianness::little);
|
|
rewriteOffsetToCurrentByte(BOS, writePlaceholder(BOS));
|
|
for (const auto &Range : Table) {
|
|
support::endian::write(BOS, static_cast<uint32_t>(Range.RangeType),
|
|
llvm::endianness::little);
|
|
support::endian::write(BOS, Range.NumDescriptors,
|
|
llvm::endianness::little);
|
|
support::endian::write(BOS, Range.BaseShaderRegister,
|
|
llvm::endianness::little);
|
|
support::endian::write(BOS, Range.RegisterSpace,
|
|
llvm::endianness::little);
|
|
if (Version > 1)
|
|
support::endian::write(BOS, Range.Flags, llvm::endianness::little);
|
|
support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart,
|
|
llvm::endianness::little);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
[[maybe_unused]] uint32_t Offset = rewriteOffsetToCurrentByte(BOS, SSO);
|
|
assert(Offset == computeStaticSamplersOffset() &&
|
|
"Computed offset does not match written offset");
|
|
for (const auto &S : StaticSamplers) {
|
|
support::endian::write(BOS, S.Filter, llvm::endianness::little);
|
|
support::endian::write(BOS, S.AddressU, llvm::endianness::little);
|
|
support::endian::write(BOS, S.AddressV, llvm::endianness::little);
|
|
support::endian::write(BOS, S.AddressW, llvm::endianness::little);
|
|
support::endian::write(BOS, S.MipLODBias, llvm::endianness::little);
|
|
support::endian::write(BOS, S.MaxAnisotropy, llvm::endianness::little);
|
|
support::endian::write(BOS, S.ComparisonFunc, llvm::endianness::little);
|
|
support::endian::write(BOS, S.BorderColor, llvm::endianness::little);
|
|
support::endian::write(BOS, S.MinLOD, llvm::endianness::little);
|
|
support::endian::write(BOS, S.MaxLOD, llvm::endianness::little);
|
|
support::endian::write(BOS, S.ShaderRegister, llvm::endianness::little);
|
|
support::endian::write(BOS, S.RegisterSpace, llvm::endianness::little);
|
|
support::endian::write(BOS, S.ShaderVisibility, llvm::endianness::little);
|
|
|
|
if (Version > 2)
|
|
support::endian::write(BOS, S.Flags, llvm::endianness::little);
|
|
}
|
|
assert(Storage.size() == getSize());
|
|
OS.write(Storage.data(), Storage.size());
|
|
}
|