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