• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
ShaderInterfaceVariableInfoMap()46 ShaderInterfaceVariableInfoMap::ShaderInterfaceVariableInfoMap()
47 {
48     // Reserve storage for most common use case
49     mData.reserve(64);
50 }
51 
52 ShaderInterfaceVariableInfoMap::~ShaderInterfaceVariableInfoMap() = default;
53 
clear()54 void ShaderInterfaceVariableInfoMap::clear()
55 {
56     mData.clear();
57     mXFBData.clear();
58     memset(&mPod, 0, sizeof(mPod));
59     for (gl::ShaderType shaderType : gl::AllShaderTypes())
60     {
61         mIdToIndexMap[shaderType].clear();
62     }
63 }
64 
save(gl::BinaryOutputStream * stream)65 void ShaderInterfaceVariableInfoMap::save(gl::BinaryOutputStream *stream)
66 {
67     ASSERT(mXFBData.size() <= mData.size());
68     stream->writeStruct(mPod);
69 
70     for (const IdToIndexMap &idToIndexMap : mIdToIndexMap)
71     {
72         stream->writeInt(idToIndexMap.size());
73         if (idToIndexMap.size() > 0)
74         {
75             stream->writeBytes(reinterpret_cast<const uint8_t *>(idToIndexMap.data()),
76                                idToIndexMap.size() * sizeof(*idToIndexMap.data()));
77         }
78     }
79 
80     stream->writeVector(mData);
81     if (mPod.xfbInfoCount > 0)
82     {
83         uint32_t xfbInfoCount = 0;
84         for (size_t xfbIndex = 0; xfbIndex < mXFBData.size(); xfbIndex++)
85         {
86             if (!mXFBData[xfbIndex])
87             {
88                 continue;
89             }
90             stream->writeInt(xfbIndex);
91             xfbInfoCount++;
92             XFBInterfaceVariableInfo &info = *mXFBData[xfbIndex];
93             SaveShaderInterfaceVariableXfbInfo(info.xfb, stream);
94             stream->writeInt(info.fieldXfb.size());
95             for (const ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
96             {
97                 SaveShaderInterfaceVariableXfbInfo(xfb, stream);
98             }
99         }
100         ASSERT(xfbInfoCount == mPod.xfbInfoCount);
101     }
102 }
load(gl::BinaryInputStream * stream)103 void ShaderInterfaceVariableInfoMap::load(gl::BinaryInputStream *stream)
104 {
105     stream->readStruct(&mPod);
106 
107     for (IdToIndexMap &idToIndexMap : mIdToIndexMap)
108     {
109         // ASSERT(idToIndexMap.empty());
110         size_t count = stream->readInt<size_t>();
111         if (count > 0)
112         {
113             idToIndexMap.resetWithRawData(count,
114                                           stream->getBytes(count * sizeof(*idToIndexMap.data())));
115         }
116     }
117 
118     stream->readVector(&mData);
119     ASSERT(mXFBData.empty());
120     ASSERT(mPod.xfbInfoCount <= mData.size());
121     if (mPod.xfbInfoCount > 0)
122     {
123         mXFBData.resize(mData.size());
124         for (uint32_t i = 0; i < mPod.xfbInfoCount; ++i)
125         {
126             size_t xfbIndex    = stream->readInt<size_t>();
127             mXFBData[xfbIndex] = std::make_unique<XFBInterfaceVariableInfo>();
128 
129             XFBInterfaceVariableInfo &info = *mXFBData[xfbIndex];
130             LoadShaderInterfaceVariableXfbInfo(stream, &info.xfb);
131             info.fieldXfb.resize(stream->readInt<size_t>());
132             for (ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
133             {
134                 LoadShaderInterfaceVariableXfbInfo(stream, &xfb);
135             }
136         }
137     }
138 }
139 
setInputPerVertexActiveMembers(gl::ShaderType shaderType,gl::PerVertexMemberBitSet activeMembers)140 void ShaderInterfaceVariableInfoMap::setInputPerVertexActiveMembers(
141     gl::ShaderType shaderType,
142     gl::PerVertexMemberBitSet activeMembers)
143 {
144     // Input gl_PerVertex is only meaningful for tessellation and geometry stages
145     ASSERT(shaderType == gl::ShaderType::TessControl ||
146            shaderType == gl::ShaderType::TessEvaluation || shaderType == gl::ShaderType::Geometry ||
147            activeMembers.none());
148     mPod.inputPerVertexActiveMembers[shaderType] = activeMembers;
149 }
150 
setOutputPerVertexActiveMembers(gl::ShaderType shaderType,gl::PerVertexMemberBitSet activeMembers)151 void ShaderInterfaceVariableInfoMap::setOutputPerVertexActiveMembers(
152     gl::ShaderType shaderType,
153     gl::PerVertexMemberBitSet activeMembers)
154 {
155     // Output gl_PerVertex is only meaningful for vertex, tessellation and geometry stages
156     ASSERT(shaderType == gl::ShaderType::Vertex || shaderType == gl::ShaderType::TessControl ||
157            shaderType == gl::ShaderType::TessEvaluation || shaderType == gl::ShaderType::Geometry ||
158            activeMembers.none());
159     mPod.outputPerVertexActiveMembers[shaderType] = activeMembers;
160 }
161 
setVariableIndex(gl::ShaderType shaderType,uint32_t id,VariableIndex index)162 void ShaderInterfaceVariableInfoMap::setVariableIndex(gl::ShaderType shaderType,
163                                                       uint32_t id,
164                                                       VariableIndex index)
165 {
166     mIdToIndexMap[shaderType][HashSPIRVId(id)] = index;
167 }
168 
getVariableIndex(gl::ShaderType shaderType,uint32_t id) const169 const VariableIndex &ShaderInterfaceVariableInfoMap::getVariableIndex(gl::ShaderType shaderType,
170                                                                       uint32_t id) const
171 {
172     return mIdToIndexMap[shaderType].at(HashSPIRVId(id));
173 }
174 
getMutable(gl::ShaderType shaderType,uint32_t id)175 ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::getMutable(gl::ShaderType shaderType,
176                                                                         uint32_t id)
177 {
178     ASSERT(hasVariable(shaderType, id));
179     uint32_t index = getVariableIndex(shaderType, id).index;
180     return mData[index];
181 }
182 
getXFBMutable(gl::ShaderType shaderType,uint32_t id)183 XFBInterfaceVariableInfo *ShaderInterfaceVariableInfoMap::getXFBMutable(gl::ShaderType shaderType,
184                                                                         uint32_t id)
185 {
186     ASSERT(hasVariable(shaderType, id));
187     uint32_t index = getVariableIndex(shaderType, id).index;
188     if (index >= mXFBData.size())
189     {
190         mXFBData.resize(index + 1);
191     }
192     if (!mXFBData[index])
193     {
194         mXFBData[index]                   = std::make_unique<XFBInterfaceVariableInfo>();
195         mData[index].hasTransformFeedback = true;
196         mPod.xfbInfoCount++;
197     }
198     return mXFBData[index].get();
199 }
200 
add(gl::ShaderType shaderType,uint32_t id)201 ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::add(gl::ShaderType shaderType,
202                                                                  uint32_t id)
203 {
204     ASSERT(!hasVariable(shaderType, id));
205     uint32_t index = static_cast<uint32_t>(mData.size());
206     setVariableIndex(shaderType, id, {index});
207     mData.resize(index + 1);
208     return mData[index];
209 }
210 
addResource(gl::ShaderBitSet shaderTypes,const gl::ShaderMap<uint32_t> & idInShaderTypes,uint32_t descriptorSet,uint32_t binding)211 void ShaderInterfaceVariableInfoMap::addResource(gl::ShaderBitSet shaderTypes,
212                                                  const gl::ShaderMap<uint32_t> &idInShaderTypes,
213                                                  uint32_t descriptorSet,
214                                                  uint32_t binding)
215 {
216     uint32_t index = static_cast<uint32_t>(mData.size());
217     mData.resize(index + 1);
218     ShaderInterfaceVariableInfo *info = &mData[index];
219 
220     info->descriptorSet = descriptorSet;
221     info->binding       = binding;
222     info->activeStages  = shaderTypes;
223 
224     for (const gl::ShaderType shaderType : shaderTypes)
225     {
226         const uint32_t id = idInShaderTypes[shaderType];
227         ASSERT(!hasVariable(shaderType, id));
228         setVariableIndex(shaderType, id, {index});
229     }
230 }
231 
addOrGet(gl::ShaderType shaderType,uint32_t id)232 ShaderInterfaceVariableInfo &ShaderInterfaceVariableInfoMap::addOrGet(gl::ShaderType shaderType,
233                                                                       uint32_t id)
234 {
235     if (!hasVariable(shaderType, id))
236     {
237         return add(shaderType, id);
238     }
239     else
240     {
241         uint32_t index = getVariableIndex(shaderType, id).index;
242         return mData[index];
243     }
244 }
245 
hasVariable(gl::ShaderType shaderType,uint32_t id) const246 bool ShaderInterfaceVariableInfoMap::hasVariable(gl::ShaderType shaderType, uint32_t id) const
247 {
248     const uint32_t hashedId = HashSPIRVId(id);
249     return hashedId < mIdToIndexMap[shaderType].size() &&
250            mIdToIndexMap[shaderType].at(hashedId).index != VariableIndex::kInvalid;
251 }
252 
hasTransformFeedbackInfo(gl::ShaderType shaderType,uint32_t bufferIndex) const253 bool ShaderInterfaceVariableInfoMap::hasTransformFeedbackInfo(gl::ShaderType shaderType,
254                                                               uint32_t bufferIndex) const
255 {
256     return hasVariable(shaderType, SpvGetXfbBufferBlockId(bufferIndex));
257 }
258 }  // namespace rx
259