This is a follow-up to #156140 and #160979, which deprecated one form of write and read, respectively. We have two forms of byte_swap: template <typename value_type> [[nodiscard]] inline value_type byte_swap(value_type value, endianness endian) template <typename value_type, endianness endian> [[nodiscard]] inline value_type byte_swap(value_type value) The difference is that endian is a function parameter in the former but a template parameter in the latter. This patch streamlines the code by migrating the use of the latter to the former while deprecating the latter because the latter is just forwarded to the former.
182 lines
7.5 KiB
C++
182 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>(
|
|
ByteOffset, llvm::endianness::little);
|
|
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());
|
|
}
|