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
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(os&: Stream, value: DummyValue, endian: llvm::endianness::little);
20 return Offset;
21}
22
23static 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 value: Stream.tell());
28 Stream.pwrite(Ptr: reinterpret_cast<const char *>(&Value), Size: sizeof(Value), Offset);
29}
30
31size_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(E: dxbc::RootParameterType::Constants32Bit):
40 Size += sizeof(dxbc::RTS0::v1::RootConstants);
41 break;
42 case llvm::to_underlying(E: dxbc::RootParameterType::CBV):
43 case llvm::to_underlying(E: dxbc::RootParameterType::SRV):
44 case llvm::to_underlying(E: 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(E: dxbc::RootParameterType::DescriptorTable):
52 const DescriptorTable &Table =
53 ParametersContainer.getDescriptorTable(Index: 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
68void RootSignatureDesc::write(raw_ostream &OS) const {
69 SmallString<256> Storage;
70 raw_svector_ostream BOS(Storage);
71 BOS.reserveExtraSpace(ExtraSize: getSize());
72
73 const uint32_t NumParameters = ParametersContainer.size();
74 const uint32_t NumSamplers = StaticSamplers.size();
75 support::endian::write(os&: BOS, value: Version, endian: llvm::endianness::little);
76 support::endian::write(os&: BOS, value: NumParameters, endian: llvm::endianness::little);
77 support::endian::write(os&: BOS, value: RootParameterOffset, endian: llvm::endianness::little);
78 support::endian::write(os&: BOS, value: NumSamplers, endian: llvm::endianness::little);
79 uint32_t SSO = StaticSamplersOffset;
80 if (NumSamplers > 0)
81 SSO = writePlaceholder(Stream&: BOS);
82 else
83 support::endian::write(os&: BOS, value: SSO, endian: llvm::endianness::little);
84 support::endian::write(os&: BOS, value: Flags, endian: llvm::endianness::little);
85
86 SmallVector<uint32_t> ParamsOffsets;
87 for (const RootParameterInfo &P : ParametersContainer) {
88 support::endian::write(os&: BOS, value: P.Header.ParameterType,
89 endian: llvm::endianness::little);
90 support::endian::write(os&: BOS, value: P.Header.ShaderVisibility,
91 endian: llvm::endianness::little);
92
93 ParamsOffsets.push_back(Elt: writePlaceholder(Stream&: BOS));
94 }
95
96 assert(NumParameters == ParamsOffsets.size());
97 for (size_t I = 0; I < NumParameters; ++I) {
98 rewriteOffsetToCurrentByte(Stream&: BOS, Offset: ParamsOffsets[I]);
99 const auto &[Type, Loc] = ParametersContainer.getTypeAndLocForParameter(Location: I);
100 switch (Type) {
101 case llvm::to_underlying(E: dxbc::RootParameterType::Constants32Bit): {
102 const dxbc::RTS0::v1::RootConstants &Constants =
103 ParametersContainer.getConstant(Index: Loc);
104 support::endian::write(os&: BOS, value: Constants.ShaderRegister,
105 endian: llvm::endianness::little);
106 support::endian::write(os&: BOS, value: Constants.RegisterSpace,
107 endian: llvm::endianness::little);
108 support::endian::write(os&: BOS, value: Constants.Num32BitValues,
109 endian: llvm::endianness::little);
110 break;
111 }
112 case llvm::to_underlying(E: dxbc::RootParameterType::CBV):
113 case llvm::to_underlying(E: dxbc::RootParameterType::SRV):
114 case llvm::to_underlying(E: dxbc::RootParameterType::UAV): {
115 const dxbc::RTS0::v2::RootDescriptor &Descriptor =
116 ParametersContainer.getRootDescriptor(Index: Loc);
117
118 support::endian::write(os&: BOS, value: Descriptor.ShaderRegister,
119 endian: llvm::endianness::little);
120 support::endian::write(os&: BOS, value: Descriptor.RegisterSpace,
121 endian: llvm::endianness::little);
122 if (Version > 1)
123 support::endian::write(os&: BOS, value: Descriptor.Flags, endian: llvm::endianness::little);
124 break;
125 }
126 case llvm::to_underlying(E: dxbc::RootParameterType::DescriptorTable): {
127 const DescriptorTable &Table =
128 ParametersContainer.getDescriptorTable(Index: Loc);
129 support::endian::write(os&: BOS, value: (uint32_t)Table.Ranges.size(),
130 endian: llvm::endianness::little);
131 rewriteOffsetToCurrentByte(Stream&: BOS, Offset: writePlaceholder(Stream&: BOS));
132 for (const auto &Range : Table) {
133 support::endian::write(os&: BOS, value: Range.RangeType, endian: llvm::endianness::little);
134 support::endian::write(os&: BOS, value: Range.NumDescriptors,
135 endian: llvm::endianness::little);
136 support::endian::write(os&: BOS, value: Range.BaseShaderRegister,
137 endian: llvm::endianness::little);
138 support::endian::write(os&: BOS, value: Range.RegisterSpace,
139 endian: llvm::endianness::little);
140 if (Version > 1)
141 support::endian::write(os&: BOS, value: Range.Flags, endian: llvm::endianness::little);
142 support::endian::write(os&: BOS, value: Range.OffsetInDescriptorsFromTableStart,
143 endian: llvm::endianness::little);
144 }
145 break;
146 }
147 }
148 }
149 if (NumSamplers > 0) {
150 rewriteOffsetToCurrentByte(Stream&: BOS, Offset: SSO);
151 for (const auto &S : StaticSamplers) {
152 support::endian::write(os&: BOS, value: S.Filter, endian: llvm::endianness::little);
153 support::endian::write(os&: BOS, value: S.AddressU, endian: llvm::endianness::little);
154 support::endian::write(os&: BOS, value: S.AddressV, endian: llvm::endianness::little);
155 support::endian::write(os&: BOS, value: S.AddressW, endian: llvm::endianness::little);
156 support::endian::write(os&: BOS, value: S.MipLODBias, endian: llvm::endianness::little);
157 support::endian::write(os&: BOS, value: S.MaxAnisotropy, endian: llvm::endianness::little);
158 support::endian::write(os&: BOS, value: S.ComparisonFunc, endian: llvm::endianness::little);
159 support::endian::write(os&: BOS, value: S.BorderColor, endian: llvm::endianness::little);
160 support::endian::write(os&: BOS, value: S.MinLOD, endian: llvm::endianness::little);
161 support::endian::write(os&: BOS, value: S.MaxLOD, endian: llvm::endianness::little);
162 support::endian::write(os&: BOS, value: S.ShaderRegister, endian: llvm::endianness::little);
163 support::endian::write(os&: BOS, value: S.RegisterSpace, endian: llvm::endianness::little);
164 support::endian::write(os&: BOS, value: S.ShaderVisibility, endian: llvm::endianness::little);
165 }
166 }
167 assert(Storage.size() == getSize());
168 OS.write(Ptr: Storage.data(), Size: Storage.size());
169}
170