1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ShaderInterfaceVariableInfoMap: Maps shader interface variable SPIR-V ids to their Vulkan
7 // mapping.
8 //
9
10 #include "libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.h"
11
12 namespace rx
13 {
14 namespace
15 {
HashSPIRVId(uint32_t id)16 uint32_t HashSPIRVId(uint32_t id)
17 {
18 ASSERT(id >= sh::vk::spirv::kIdShaderVariablesBegin);
19 return id - sh::vk::spirv::kIdShaderVariablesBegin;
20 }
21
LoadShaderInterfaceVariableXfbInfo(gl::BinaryInputStream * stream,ShaderInterfaceVariableXfbInfo * xfb)22 void LoadShaderInterfaceVariableXfbInfo(gl::BinaryInputStream *stream,
23 ShaderInterfaceVariableXfbInfo *xfb)
24 {
25 stream->readStruct(&xfb->pod);
26 xfb->arrayElements.resize(stream->readInt<size_t>());
27 for (ShaderInterfaceVariableXfbInfo &arrayElement : xfb->arrayElements)
28 {
29 LoadShaderInterfaceVariableXfbInfo(stream, &arrayElement);
30 }
31 }
32
SaveShaderInterfaceVariableXfbInfo(const ShaderInterfaceVariableXfbInfo & xfb,gl::BinaryOutputStream * stream)33 void SaveShaderInterfaceVariableXfbInfo(const ShaderInterfaceVariableXfbInfo &xfb,
34 gl::BinaryOutputStream *stream)
35 {
36 stream->writeStruct(xfb.pod);
37 stream->writeInt(xfb.arrayElements.size());
38 for (const ShaderInterfaceVariableXfbInfo &arrayElement : xfb.arrayElements)
39 {
40 SaveShaderInterfaceVariableXfbInfo(arrayElement, stream);
41 }
42 }
43 } // anonymous namespace
44
45 // ShaderInterfaceVariableInfoMap implementation.
46 ShaderInterfaceVariableInfoMap::ShaderInterfaceVariableInfoMap() = default;
47
48 ShaderInterfaceVariableInfoMap::~ShaderInterfaceVariableInfoMap() = default;
49
clear()50 void ShaderInterfaceVariableInfoMap::clear()
51 {
52 mData.clear();
53 mXFBData.clear();
54 memset(&mPod, 0, sizeof(mPod));
55 for (gl::ShaderType shaderType : gl::AllShaderTypes())
56 {
57 mIdToIndexMap[shaderType].clear();
58 }
59 }
60
save(gl::BinaryOutputStream * stream)61 void ShaderInterfaceVariableInfoMap::save(gl::BinaryOutputStream *stream)
62 {
63 ASSERT(mXFBData.size() <= mData.size());
64 stream->writeStruct(mPod);
65
66 for (const IdToIndexMap &idToIndexMap : mIdToIndexMap)
67 {
68 stream->writeInt(idToIndexMap.size());
69 if (idToIndexMap.size() > 0)
70 {
71 stream->writeBytes(reinterpret_cast<const uint8_t *>(idToIndexMap.data()),
72 idToIndexMap.size() * sizeof(*idToIndexMap.data()));
73 }
74 }
75
76 stream->writeVector(mData);
77 if (mPod.xfbInfoCount > 0)
78 {
79 uint32_t xfbInfoCount = 0;
80 for (size_t xfbIndex = 0; xfbIndex < mXFBData.size(); xfbIndex++)
81 {
82 if (!mXFBData[xfbIndex])
83 {
84 continue;
85 }
86 stream->writeInt(xfbIndex);
87 xfbInfoCount++;
88 XFBInterfaceVariableInfo &info = *mXFBData[xfbIndex];
89 SaveShaderInterfaceVariableXfbInfo(info.xfb, stream);
90 stream->writeInt(info.fieldXfb.size());
91 for (const ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
92 {
93 SaveShaderInterfaceVariableXfbInfo(xfb, stream);
94 }
95 }
96 ASSERT(xfbInfoCount == mPod.xfbInfoCount);
97 }
98 }
load(gl::BinaryInputStream * stream)99 void ShaderInterfaceVariableInfoMap::load(gl::BinaryInputStream *stream)
100 {
101 stream->readStruct(&mPod);
102
103 for (IdToIndexMap &idToIndexMap : mIdToIndexMap)
104 {
105 // ASSERT(idToIndexMap.empty());
106 size_t count = stream->readInt<size_t>();
107 if (count > 0)
108 {
109 idToIndexMap.resetWithRawData(count,
110 stream->getBytes(count * sizeof(*idToIndexMap.data())));
111 }
112 }
113
114 stream->readVector(&mData);
115 ASSERT(mXFBData.empty());
116 ASSERT(mPod.xfbInfoCount <= mData.size());
117 if (mPod.xfbInfoCount > 0)
118 {
119 mXFBData.resize(mData.size());
120 for (uint32_t i = 0; i < mPod.xfbInfoCount; ++i)
121 {
122 size_t xfbIndex = stream->readInt<size_t>();
123 mXFBData[xfbIndex] = std::make_unique<XFBInterfaceVariableInfo>();
124
125 XFBInterfaceVariableInfo &info = *mXFBData[xfbIndex];
126 LoadShaderInterfaceVariableXfbInfo(stream, &info.xfb);
127 info.fieldXfb.resize(stream->readInt<size_t>());
128 for (ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
129 {
130 LoadShaderInterfaceVariableXfbInfo(stream, &xfb);
131 }
132 }
133 }
134 }
135
setInputPerVertexActiveMembers(gl::ShaderType shaderType,gl::PerVertexMemberBitSet activeMembers)136 void ShaderInterfaceVariableInfoMap::setInputPerVertexActiveMembers(
137 gl::ShaderType shaderType,
138 gl::PerVertexMemberBitSet activeMembers)
139 {
140 // Input gl_PerVertex is only meaningful for tessellation and geometry stages
141 ASSERT(shaderType == gl::ShaderType::TessControl ||
142 shaderType == gl::ShaderType::TessEvaluation || shaderType == gl::ShaderType::Geometry ||
143 activeMembers.none());
144 mPod.inputPerVertexActiveMembers[shaderType] = activeMembers;
145 }
146
setOutputPerVertexActiveMembers(gl::ShaderType shaderType,gl::PerVertexMemberBitSet activeMembers)147 void ShaderInterfaceVariableInfoMap::setOutputPerVertexActiveMembers(
148 gl::ShaderType shaderType,
149 gl::PerVertexMemberBitSet activeMembers)
150 {
151 // Output gl_PerVertex is only meaningful for vertex, tessellation and geometry stages
152 ASSERT(shaderType == gl::ShaderType::Vertex || shaderType == gl::ShaderType::TessControl ||
153 shaderType == gl::ShaderType::TessEvaluation || shaderType == gl::ShaderType::Geometry ||
154 activeMembers.none());
155 mPod.outputPerVertexActiveMembers[shaderType] = activeMembers;
156 }
157
setVariableIndex(gl::ShaderType shaderType,uint32_t id,VariableIndex index)158 void ShaderInterfaceVariableInfoMap::setVariableIndex(gl::ShaderType shaderType,
159 uint32_t id,
160 VariableIndex index)
161 {
162 mIdToIndexMap[shaderType][HashSPIRVId(id)] = index;
163 }
164
getVariableIndex(gl::ShaderType shaderType,uint32_t id) const165 const VariableIndex &ShaderInterfaceVariableInfoMap::getVariableIndex(gl::ShaderType shaderType,
166 uint32_t id) const
167 {
168 return mIdToIndexMap[shaderType].at(HashSPIRVId(id));
169 }
170
getMutable(gl::ShaderType shaderType,uint32_t id)171 ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::getMutable(gl::ShaderType shaderType,
172 uint32_t id)
173 {
174 ASSERT(hasVariable(shaderType, id));
175 uint32_t index = getVariableIndex(shaderType, id).index;
176 return mData[index];
177 }
178
getXFBMutable(gl::ShaderType shaderType,uint32_t id)179 XFBInterfaceVariableInfo *ShaderInterfaceVariableInfoMap::getXFBMutable(gl::ShaderType shaderType,
180 uint32_t id)
181 {
182 ASSERT(hasVariable(shaderType, id));
183 uint32_t index = getVariableIndex(shaderType, id).index;
184 if (index >= mXFBData.size())
185 {
186 mXFBData.resize(index + 1);
187 }
188 if (!mXFBData[index])
189 {
190 mXFBData[index] = std::make_unique<XFBInterfaceVariableInfo>();
191 mData[index].hasTransformFeedback = true;
192 mPod.xfbInfoCount++;
193 }
194 return mXFBData[index].get();
195 }
196
add(gl::ShaderType shaderType,uint32_t id)197 ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::add(gl::ShaderType shaderType,
198 uint32_t id)
199 {
200 ASSERT(!hasVariable(shaderType, id));
201 uint32_t index = static_cast<uint32_t>(mData.size());
202 setVariableIndex(shaderType, id, {index});
203 mData.resize(index + 1);
204 return mData[index];
205 }
206
addResource(gl::ShaderBitSet shaderTypes,const gl::ShaderMap<uint32_t> & idInShaderTypes,uint32_t descriptorSet,uint32_t binding)207 void ShaderInterfaceVariableInfoMap::addResource(gl::ShaderBitSet shaderTypes,
208 const gl::ShaderMap<uint32_t> &idInShaderTypes,
209 uint32_t descriptorSet,
210 uint32_t binding)
211 {
212 uint32_t index = static_cast<uint32_t>(mData.size());
213 mData.resize(index + 1);
214 ShaderInterfaceVariableInfo *info = &mData[index];
215
216 info->descriptorSet = descriptorSet;
217 info->binding = binding;
218 info->activeStages = shaderTypes;
219
220 for (const gl::ShaderType shaderType : shaderTypes)
221 {
222 const uint32_t id = idInShaderTypes[shaderType];
223 ASSERT(!hasVariable(shaderType, id));
224 setVariableIndex(shaderType, id, {index});
225 }
226 }
227
addOrGet(gl::ShaderType shaderType,uint32_t id)228 ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::addOrGet(gl::ShaderType shaderType,
229 uint32_t id)
230 {
231 if (!hasVariable(shaderType, id))
232 {
233 return add(shaderType, id);
234 }
235 else
236 {
237 uint32_t index = getVariableIndex(shaderType, id).index;
238 return mData[index];
239 }
240 }
241
hasVariable(gl::ShaderType shaderType,uint32_t id) const242 bool ShaderInterfaceVariableInfoMap::hasVariable(gl::ShaderType shaderType, uint32_t id) const
243 {
244 const uint32_t hashedId = HashSPIRVId(id);
245 return hashedId < mIdToIndexMap[shaderType].size() &&
246 mIdToIndexMap[shaderType].at(hashedId).index != VariableIndex::kInvalid;
247 }
248
hasTransformFeedbackInfo(gl::ShaderType shaderType,uint32_t bufferIndex) const249 bool ShaderInterfaceVariableInfoMap::hasTransformFeedbackInfo(gl::ShaderType shaderType,
250 uint32_t bufferIndex) const
251 {
252 return hasVariable(shaderType, SpvGetXfbBufferBlockId(bufferIndex));
253 }
254 } // namespace rx
255