xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/ShaderInterfaceVariableInfoMap.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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