182 lines · cpp
1//===- llvm/MC/DXContainerRootSignature.cpp - RootSignature -*- 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 "llvm/MC/DXContainerRootSignature.h"10#include "llvm/ADT/SmallString.h"11#include "llvm/Support/EndianStream.h"12 13using namespace llvm;14using namespace llvm::mcdxbc;15 16static uint32_t writePlaceholder(raw_svector_ostream &Stream) {17 const uint32_t DummyValue = std::numeric_limits<uint32_t>::max();18 uint32_t Offset = Stream.tell();19 support::endian::write(Stream, DummyValue, llvm::endianness::little);20 return Offset;21}22 23static uint32_t rewriteOffsetToCurrentByte(raw_svector_ostream &Stream,24 uint32_t Offset) {25 uint32_t ByteOffset = Stream.tell();26 uint32_t Value = support::endian::byte_swap<uint32_t>(27 ByteOffset, llvm::endianness::little);28 Stream.pwrite(reinterpret_cast<const char *>(&Value), sizeof(Value), Offset);29 return ByteOffset;30}31 32size_t RootSignatureDesc::getSize() const {33 uint32_t StaticSamplersOffset = computeStaticSamplersOffset();34 size_t StaticSamplersSize = sizeof(dxbc::RTS0::v1::StaticSampler);35 if (Version > 2)36 StaticSamplersSize = sizeof(dxbc::RTS0::v3::StaticSampler);37 38 return size_t(StaticSamplersOffset) +39 (StaticSamplersSize * StaticSamplers.size());40}41 42uint32_t RootSignatureDesc::computeRootParametersOffset() const {43 return sizeof(dxbc::RTS0::v1::RootSignatureHeader);44}45 46uint32_t RootSignatureDesc::computeStaticSamplersOffset() const {47 uint32_t Offset = computeRootParametersOffset();48 49 for (const RootParameterInfo &I : ParametersContainer) {50 Offset += sizeof(dxbc::RTS0::v1::RootParameterHeader);51 switch (I.Type) {52 case dxbc::RootParameterType::Constants32Bit:53 Offset += sizeof(dxbc::RTS0::v1::RootConstants);54 break;55 case dxbc::RootParameterType::CBV:56 case dxbc::RootParameterType::SRV:57 case dxbc::RootParameterType::UAV:58 if (Version == 1)59 Offset += sizeof(dxbc::RTS0::v1::RootDescriptor);60 else61 Offset += sizeof(dxbc::RTS0::v2::RootDescriptor);62 63 break;64 case dxbc::RootParameterType::DescriptorTable:65 const DescriptorTable &Table =66 ParametersContainer.getDescriptorTable(I.Location);67 68 // 4 bytes for the number of ranges in table and69 // 4 bytes for the ranges offset70 Offset += 2 * sizeof(uint32_t);71 if (Version == 1)72 Offset += sizeof(dxbc::RTS0::v1::DescriptorRange) * Table.Ranges.size();73 else74 Offset += sizeof(dxbc::RTS0::v2::DescriptorRange) * Table.Ranges.size();75 break;76 }77 }78 79 return Offset;80}81 82void RootSignatureDesc::write(raw_ostream &OS) const {83 SmallString<256> Storage;84 raw_svector_ostream BOS(Storage);85 BOS.reserveExtraSpace(getSize());86 87 const uint32_t NumParameters = ParametersContainer.size();88 const uint32_t NumSamplers = StaticSamplers.size();89 support::endian::write(BOS, Version, llvm::endianness::little);90 support::endian::write(BOS, NumParameters, llvm::endianness::little);91 support::endian::write(BOS, RootParameterOffset, llvm::endianness::little);92 support::endian::write(BOS, NumSamplers, llvm::endianness::little);93 uint32_t SSO = writePlaceholder(BOS);94 support::endian::write(BOS, Flags, llvm::endianness::little);95 96 SmallVector<uint32_t> ParamsOffsets;97 for (const RootParameterInfo &I : ParametersContainer) {98 support::endian::write(BOS, I.Type, llvm::endianness::little);99 support::endian::write(BOS, I.Visibility, llvm::endianness::little);100 101 ParamsOffsets.push_back(writePlaceholder(BOS));102 }103 104 assert(NumParameters == ParamsOffsets.size());105 for (size_t I = 0; I < NumParameters; ++I) {106 rewriteOffsetToCurrentByte(BOS, ParamsOffsets[I]);107 const RootParameterInfo &Info = ParametersContainer.getInfo(I);108 switch (Info.Type) {109 case dxbc::RootParameterType::Constants32Bit: {110 const mcdxbc::RootConstants &Constants =111 ParametersContainer.getConstant(Info.Location);112 support::endian::write(BOS, Constants.ShaderRegister,113 llvm::endianness::little);114 support::endian::write(BOS, Constants.RegisterSpace,115 llvm::endianness::little);116 support::endian::write(BOS, Constants.Num32BitValues,117 llvm::endianness::little);118 break;119 }120 case dxbc::RootParameterType::CBV:121 case dxbc::RootParameterType::SRV:122 case dxbc::RootParameterType::UAV: {123 const mcdxbc::RootDescriptor &Descriptor =124 ParametersContainer.getRootDescriptor(Info.Location);125 126 support::endian::write(BOS, Descriptor.ShaderRegister,127 llvm::endianness::little);128 support::endian::write(BOS, Descriptor.RegisterSpace,129 llvm::endianness::little);130 if (Version > 1)131 support::endian::write(BOS, Descriptor.Flags, llvm::endianness::little);132 break;133 }134 case dxbc::RootParameterType::DescriptorTable: {135 const DescriptorTable &Table =136 ParametersContainer.getDescriptorTable(Info.Location);137 support::endian::write(BOS, (uint32_t)Table.Ranges.size(),138 llvm::endianness::little);139 rewriteOffsetToCurrentByte(BOS, writePlaceholder(BOS));140 for (const auto &Range : Table) {141 support::endian::write(BOS, static_cast<uint32_t>(Range.RangeType),142 llvm::endianness::little);143 support::endian::write(BOS, Range.NumDescriptors,144 llvm::endianness::little);145 support::endian::write(BOS, Range.BaseShaderRegister,146 llvm::endianness::little);147 support::endian::write(BOS, Range.RegisterSpace,148 llvm::endianness::little);149 if (Version > 1)150 support::endian::write(BOS, Range.Flags, llvm::endianness::little);151 support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart,152 llvm::endianness::little);153 }154 break;155 }156 }157 }158 [[maybe_unused]] uint32_t Offset = rewriteOffsetToCurrentByte(BOS, SSO);159 assert(Offset == computeStaticSamplersOffset() &&160 "Computed offset does not match written offset");161 for (const auto &S : StaticSamplers) {162 support::endian::write(BOS, S.Filter, llvm::endianness::little);163 support::endian::write(BOS, S.AddressU, llvm::endianness::little);164 support::endian::write(BOS, S.AddressV, llvm::endianness::little);165 support::endian::write(BOS, S.AddressW, llvm::endianness::little);166 support::endian::write(BOS, S.MipLODBias, llvm::endianness::little);167 support::endian::write(BOS, S.MaxAnisotropy, llvm::endianness::little);168 support::endian::write(BOS, S.ComparisonFunc, llvm::endianness::little);169 support::endian::write(BOS, S.BorderColor, llvm::endianness::little);170 support::endian::write(BOS, S.MinLOD, llvm::endianness::little);171 support::endian::write(BOS, S.MaxLOD, llvm::endianness::little);172 support::endian::write(BOS, S.ShaderRegister, llvm::endianness::little);173 support::endian::write(BOS, S.RegisterSpace, llvm::endianness::little);174 support::endian::write(BOS, S.ShaderVisibility, llvm::endianness::little);175 176 if (Version > 2)177 support::endian::write(BOS, S.Flags, llvm::endianness::little);178 }179 assert(Storage.size() == getSize());180 OS.write(Storage.data(), Storage.size());181}182