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