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