xref: /freebsd/contrib/llvm-project/llvm/lib/MC/DXContainerRootSignature.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
writePlaceholder(raw_svector_ostream & Stream)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 
rewriteOffsetToCurrentByte(raw_svector_ostream & Stream,uint32_t Offset)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 
getSize() const31 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 
write(raw_ostream & OS) const68 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