xref: /aosp_15_r20/external/angle/src/compiler/translator/blocklayout.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2013 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 // blocklayout.cpp:
7*8975f5c5SAndroid Build Coastguard Worker //   Implementation for block layout classes and methods.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/blocklayout.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/Common.h"
15*8975f5c5SAndroid Build Coastguard Worker 
16*8975f5c5SAndroid Build Coastguard Worker namespace sh
17*8975f5c5SAndroid Build Coastguard Worker {
18*8975f5c5SAndroid Build Coastguard Worker 
operator ==(const BlockMemberInfo & lhs,const BlockMemberInfo & rhs)19*8975f5c5SAndroid Build Coastguard Worker bool operator==(const BlockMemberInfo &lhs, const BlockMemberInfo &rhs)
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker     return lhs.type == rhs.type && lhs.offset == rhs.offset && lhs.arrayStride == rhs.arrayStride &&
22*8975f5c5SAndroid Build Coastguard Worker            lhs.matrixStride == rhs.matrixStride && lhs.arraySize == rhs.arraySize &&
23*8975f5c5SAndroid Build Coastguard Worker            lhs.isRowMajorMatrix == rhs.isRowMajorMatrix &&
24*8975f5c5SAndroid Build Coastguard Worker            lhs.topLevelArrayStride == rhs.topLevelArrayStride;
25*8975f5c5SAndroid Build Coastguard Worker }
26*8975f5c5SAndroid Build Coastguard Worker 
27*8975f5c5SAndroid Build Coastguard Worker namespace
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker class BlockLayoutMapVisitor : public BlockEncoderVisitor
30*8975f5c5SAndroid Build Coastguard Worker {
31*8975f5c5SAndroid Build Coastguard Worker   public:
BlockLayoutMapVisitor(BlockLayoutMap * blockInfoOut,const std::string & instanceName,BlockLayoutEncoder * encoder)32*8975f5c5SAndroid Build Coastguard Worker     BlockLayoutMapVisitor(BlockLayoutMap *blockInfoOut,
33*8975f5c5SAndroid Build Coastguard Worker                           const std::string &instanceName,
34*8975f5c5SAndroid Build Coastguard Worker                           BlockLayoutEncoder *encoder)
35*8975f5c5SAndroid Build Coastguard Worker         : BlockEncoderVisitor(instanceName, instanceName, encoder), mInfoOut(blockInfoOut)
36*8975f5c5SAndroid Build Coastguard Worker     {}
37*8975f5c5SAndroid Build Coastguard Worker 
encodeVariable(const ShaderVariable & variable,const BlockMemberInfo & variableInfo,const std::string & name,const std::string & mappedName)38*8975f5c5SAndroid Build Coastguard Worker     void encodeVariable(const ShaderVariable &variable,
39*8975f5c5SAndroid Build Coastguard Worker                         const BlockMemberInfo &variableInfo,
40*8975f5c5SAndroid Build Coastguard Worker                         const std::string &name,
41*8975f5c5SAndroid Build Coastguard Worker                         const std::string &mappedName) override
42*8975f5c5SAndroid Build Coastguard Worker     {
43*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!gl::IsSamplerType(variable.type));
44*8975f5c5SAndroid Build Coastguard Worker         if (!gl::IsOpaqueType(variable.type))
45*8975f5c5SAndroid Build Coastguard Worker         {
46*8975f5c5SAndroid Build Coastguard Worker             (*mInfoOut)[name] = variableInfo;
47*8975f5c5SAndroid Build Coastguard Worker         }
48*8975f5c5SAndroid Build Coastguard Worker     }
49*8975f5c5SAndroid Build Coastguard Worker 
50*8975f5c5SAndroid Build Coastguard Worker   private:
51*8975f5c5SAndroid Build Coastguard Worker     BlockLayoutMap *mInfoOut;
52*8975f5c5SAndroid Build Coastguard Worker };
53*8975f5c5SAndroid Build Coastguard Worker 
54*8975f5c5SAndroid Build Coastguard Worker template <typename VarT>
GetInterfaceBlockInfo(const std::vector<VarT> & fields,const std::string & prefix,BlockLayoutEncoder * encoder,bool inRowMajorLayout,bool onlyActiveVariables,BlockLayoutMap * blockInfoOut)55*8975f5c5SAndroid Build Coastguard Worker void GetInterfaceBlockInfo(const std::vector<VarT> &fields,
56*8975f5c5SAndroid Build Coastguard Worker                            const std::string &prefix,
57*8975f5c5SAndroid Build Coastguard Worker                            BlockLayoutEncoder *encoder,
58*8975f5c5SAndroid Build Coastguard Worker                            bool inRowMajorLayout,
59*8975f5c5SAndroid Build Coastguard Worker                            bool onlyActiveVariables,
60*8975f5c5SAndroid Build Coastguard Worker                            BlockLayoutMap *blockInfoOut)
61*8975f5c5SAndroid Build Coastguard Worker {
62*8975f5c5SAndroid Build Coastguard Worker     BlockLayoutMapVisitor visitor(blockInfoOut, prefix, encoder);
63*8975f5c5SAndroid Build Coastguard Worker     if (onlyActiveVariables)
64*8975f5c5SAndroid Build Coastguard Worker     {
65*8975f5c5SAndroid Build Coastguard Worker         TraverseActiveShaderVariables(fields, inRowMajorLayout, &visitor);
66*8975f5c5SAndroid Build Coastguard Worker     }
67*8975f5c5SAndroid Build Coastguard Worker     else
68*8975f5c5SAndroid Build Coastguard Worker     {
69*8975f5c5SAndroid Build Coastguard Worker         TraverseShaderVariables(fields, inRowMajorLayout, &visitor);
70*8975f5c5SAndroid Build Coastguard Worker     }
71*8975f5c5SAndroid Build Coastguard Worker }
72*8975f5c5SAndroid Build Coastguard Worker 
TraverseStructVariable(const ShaderVariable & variable,bool isRowMajorLayout,ShaderVariableVisitor * visitor)73*8975f5c5SAndroid Build Coastguard Worker void TraverseStructVariable(const ShaderVariable &variable,
74*8975f5c5SAndroid Build Coastguard Worker                             bool isRowMajorLayout,
75*8975f5c5SAndroid Build Coastguard Worker                             ShaderVariableVisitor *visitor)
76*8975f5c5SAndroid Build Coastguard Worker {
77*8975f5c5SAndroid Build Coastguard Worker     const std::vector<ShaderVariable> &fields = variable.fields;
78*8975f5c5SAndroid Build Coastguard Worker 
79*8975f5c5SAndroid Build Coastguard Worker     visitor->enterStructAccess(variable, isRowMajorLayout);
80*8975f5c5SAndroid Build Coastguard Worker     TraverseShaderVariables(fields, isRowMajorLayout, visitor);
81*8975f5c5SAndroid Build Coastguard Worker     visitor->exitStructAccess(variable, isRowMajorLayout);
82*8975f5c5SAndroid Build Coastguard Worker }
83*8975f5c5SAndroid Build Coastguard Worker 
TraverseStructArrayVariable(const ShaderVariable & variable,bool inRowMajorLayout,ShaderVariableVisitor * visitor)84*8975f5c5SAndroid Build Coastguard Worker void TraverseStructArrayVariable(const ShaderVariable &variable,
85*8975f5c5SAndroid Build Coastguard Worker                                  bool inRowMajorLayout,
86*8975f5c5SAndroid Build Coastguard Worker                                  ShaderVariableVisitor *visitor)
87*8975f5c5SAndroid Build Coastguard Worker {
88*8975f5c5SAndroid Build Coastguard Worker     visitor->enterArray(variable);
89*8975f5c5SAndroid Build Coastguard Worker 
90*8975f5c5SAndroid Build Coastguard Worker     // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
91*8975f5c5SAndroid Build Coastguard Worker     // innermost. We make a special case for unsized arrays.
92*8975f5c5SAndroid Build Coastguard Worker     const unsigned int currentArraySize = variable.getNestedArraySize(0);
93*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
94*8975f5c5SAndroid Build Coastguard Worker     {
95*8975f5c5SAndroid Build Coastguard Worker         visitor->enterArrayElement(variable, arrayElement);
96*8975f5c5SAndroid Build Coastguard Worker         ShaderVariable elementVar = variable;
97*8975f5c5SAndroid Build Coastguard Worker         elementVar.indexIntoArray(arrayElement);
98*8975f5c5SAndroid Build Coastguard Worker 
99*8975f5c5SAndroid Build Coastguard Worker         if (variable.arraySizes.size() > 1u)
100*8975f5c5SAndroid Build Coastguard Worker         {
101*8975f5c5SAndroid Build Coastguard Worker             TraverseStructArrayVariable(elementVar, inRowMajorLayout, visitor);
102*8975f5c5SAndroid Build Coastguard Worker         }
103*8975f5c5SAndroid Build Coastguard Worker         else
104*8975f5c5SAndroid Build Coastguard Worker         {
105*8975f5c5SAndroid Build Coastguard Worker             TraverseStructVariable(elementVar, inRowMajorLayout, visitor);
106*8975f5c5SAndroid Build Coastguard Worker         }
107*8975f5c5SAndroid Build Coastguard Worker 
108*8975f5c5SAndroid Build Coastguard Worker         visitor->exitArrayElement(variable, arrayElement);
109*8975f5c5SAndroid Build Coastguard Worker     }
110*8975f5c5SAndroid Build Coastguard Worker 
111*8975f5c5SAndroid Build Coastguard Worker     visitor->exitArray(variable);
112*8975f5c5SAndroid Build Coastguard Worker }
113*8975f5c5SAndroid Build Coastguard Worker 
TraverseArrayOfArraysVariable(const ShaderVariable & variable,unsigned int arrayNestingIndex,bool isRowMajorMatrix,ShaderVariableVisitor * visitor)114*8975f5c5SAndroid Build Coastguard Worker void TraverseArrayOfArraysVariable(const ShaderVariable &variable,
115*8975f5c5SAndroid Build Coastguard Worker                                    unsigned int arrayNestingIndex,
116*8975f5c5SAndroid Build Coastguard Worker                                    bool isRowMajorMatrix,
117*8975f5c5SAndroid Build Coastguard Worker                                    ShaderVariableVisitor *visitor)
118*8975f5c5SAndroid Build Coastguard Worker {
119*8975f5c5SAndroid Build Coastguard Worker     visitor->enterArray(variable);
120*8975f5c5SAndroid Build Coastguard Worker 
121*8975f5c5SAndroid Build Coastguard Worker     const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex);
122*8975f5c5SAndroid Build Coastguard Worker     unsigned int count                  = std::max(currentArraySize, 1u);
123*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int arrayElement = 0u; arrayElement < count; ++arrayElement)
124*8975f5c5SAndroid Build Coastguard Worker     {
125*8975f5c5SAndroid Build Coastguard Worker         visitor->enterArrayElement(variable, arrayElement);
126*8975f5c5SAndroid Build Coastguard Worker 
127*8975f5c5SAndroid Build Coastguard Worker         ShaderVariable elementVar = variable;
128*8975f5c5SAndroid Build Coastguard Worker         elementVar.indexIntoArray(arrayElement);
129*8975f5c5SAndroid Build Coastguard Worker 
130*8975f5c5SAndroid Build Coastguard Worker         if (arrayNestingIndex + 2u < variable.arraySizes.size())
131*8975f5c5SAndroid Build Coastguard Worker         {
132*8975f5c5SAndroid Build Coastguard Worker             TraverseArrayOfArraysVariable(elementVar, arrayNestingIndex, isRowMajorMatrix, visitor);
133*8975f5c5SAndroid Build Coastguard Worker         }
134*8975f5c5SAndroid Build Coastguard Worker         else
135*8975f5c5SAndroid Build Coastguard Worker         {
136*8975f5c5SAndroid Build Coastguard Worker             if (gl::IsSamplerType(variable.type) || gl::IsImageType(variable.type) ||
137*8975f5c5SAndroid Build Coastguard Worker                 variable.isFragmentInOut)
138*8975f5c5SAndroid Build Coastguard Worker             {
139*8975f5c5SAndroid Build Coastguard Worker                 visitor->visitOpaqueObject(elementVar);
140*8975f5c5SAndroid Build Coastguard Worker             }
141*8975f5c5SAndroid Build Coastguard Worker             else
142*8975f5c5SAndroid Build Coastguard Worker             {
143*8975f5c5SAndroid Build Coastguard Worker                 visitor->visitVariable(elementVar, isRowMajorMatrix);
144*8975f5c5SAndroid Build Coastguard Worker             }
145*8975f5c5SAndroid Build Coastguard Worker         }
146*8975f5c5SAndroid Build Coastguard Worker 
147*8975f5c5SAndroid Build Coastguard Worker         visitor->exitArrayElement(variable, arrayElement);
148*8975f5c5SAndroid Build Coastguard Worker     }
149*8975f5c5SAndroid Build Coastguard Worker 
150*8975f5c5SAndroid Build Coastguard Worker     visitor->exitArray(variable);
151*8975f5c5SAndroid Build Coastguard Worker }
152*8975f5c5SAndroid Build Coastguard Worker 
CollapseNameStack(const std::vector<std::string> & nameStack)153*8975f5c5SAndroid Build Coastguard Worker std::string CollapseNameStack(const std::vector<std::string> &nameStack)
154*8975f5c5SAndroid Build Coastguard Worker {
155*8975f5c5SAndroid Build Coastguard Worker     std::stringstream strstr = sh::InitializeStream<std::stringstream>();
156*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &part : nameStack)
157*8975f5c5SAndroid Build Coastguard Worker     {
158*8975f5c5SAndroid Build Coastguard Worker         strstr << part;
159*8975f5c5SAndroid Build Coastguard Worker     }
160*8975f5c5SAndroid Build Coastguard Worker     return strstr.str();
161*8975f5c5SAndroid Build Coastguard Worker }
162*8975f5c5SAndroid Build Coastguard Worker 
GetStd430BaseAlignment(GLenum variableType,bool isRowMajor)163*8975f5c5SAndroid Build Coastguard Worker size_t GetStd430BaseAlignment(GLenum variableType, bool isRowMajor)
164*8975f5c5SAndroid Build Coastguard Worker {
165*8975f5c5SAndroid Build Coastguard Worker     GLenum flippedType   = isRowMajor ? variableType : gl::TransposeMatrixType(variableType);
166*8975f5c5SAndroid Build Coastguard Worker     size_t numComponents = static_cast<size_t>(gl::VariableColumnCount(flippedType));
167*8975f5c5SAndroid Build Coastguard Worker     return ComponentAlignment(numComponents);
168*8975f5c5SAndroid Build Coastguard Worker }
169*8975f5c5SAndroid Build Coastguard Worker 
170*8975f5c5SAndroid Build Coastguard Worker class BaseAlignmentVisitor : public ShaderVariableVisitor
171*8975f5c5SAndroid Build Coastguard Worker {
172*8975f5c5SAndroid Build Coastguard Worker   public:
173*8975f5c5SAndroid Build Coastguard Worker     BaseAlignmentVisitor() = default;
visitVariable(const ShaderVariable & variable,bool isRowMajor)174*8975f5c5SAndroid Build Coastguard Worker     void visitVariable(const ShaderVariable &variable, bool isRowMajor) override
175*8975f5c5SAndroid Build Coastguard Worker     {
176*8975f5c5SAndroid Build Coastguard Worker         size_t baseAlignment = GetStd430BaseAlignment(variable.type, isRowMajor);
177*8975f5c5SAndroid Build Coastguard Worker         mCurrentAlignment    = std::max(mCurrentAlignment, baseAlignment);
178*8975f5c5SAndroid Build Coastguard Worker     }
179*8975f5c5SAndroid Build Coastguard Worker 
180*8975f5c5SAndroid Build Coastguard Worker     // This is in components rather than bytes.
getBaseAlignment() const181*8975f5c5SAndroid Build Coastguard Worker     size_t getBaseAlignment() const { return mCurrentAlignment; }
182*8975f5c5SAndroid Build Coastguard Worker 
183*8975f5c5SAndroid Build Coastguard Worker   private:
184*8975f5c5SAndroid Build Coastguard Worker     size_t mCurrentAlignment = 0;
185*8975f5c5SAndroid Build Coastguard Worker };
186*8975f5c5SAndroid Build Coastguard Worker 
187*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
188*8975f5c5SAndroid Build Coastguard Worker 
189*8975f5c5SAndroid Build Coastguard Worker // BlockLayoutEncoder implementation.
BlockLayoutEncoder()190*8975f5c5SAndroid Build Coastguard Worker BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) {}
191*8975f5c5SAndroid Build Coastguard Worker 
encodeType(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix)192*8975f5c5SAndroid Build Coastguard Worker BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
193*8975f5c5SAndroid Build Coastguard Worker                                                const std::vector<unsigned int> &arraySizes,
194*8975f5c5SAndroid Build Coastguard Worker                                                bool isRowMajorMatrix)
195*8975f5c5SAndroid Build Coastguard Worker {
196*8975f5c5SAndroid Build Coastguard Worker     int arrayStride;
197*8975f5c5SAndroid Build Coastguard Worker     int matrixStride;
198*8975f5c5SAndroid Build Coastguard Worker 
199*8975f5c5SAndroid Build Coastguard Worker     getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride);
200*8975f5c5SAndroid Build Coastguard Worker 
201*8975f5c5SAndroid Build Coastguard Worker     const BlockMemberInfo memberInfo(type, static_cast<int>(mCurrentOffset * kBytesPerComponent),
202*8975f5c5SAndroid Build Coastguard Worker                                      static_cast<int>(arrayStride * kBytesPerComponent),
203*8975f5c5SAndroid Build Coastguard Worker                                      static_cast<int>(matrixStride * kBytesPerComponent),
204*8975f5c5SAndroid Build Coastguard Worker                                      gl::ArraySizeProduct(arraySizes), isRowMajorMatrix);
205*8975f5c5SAndroid Build Coastguard Worker 
206*8975f5c5SAndroid Build Coastguard Worker     advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride);
207*8975f5c5SAndroid Build Coastguard Worker 
208*8975f5c5SAndroid Build Coastguard Worker     return memberInfo;
209*8975f5c5SAndroid Build Coastguard Worker }
210*8975f5c5SAndroid Build Coastguard Worker 
encodeArrayOfPreEncodedStructs(size_t size,const std::vector<unsigned int> & arraySizes)211*8975f5c5SAndroid Build Coastguard Worker BlockMemberInfo BlockLayoutEncoder::encodeArrayOfPreEncodedStructs(
212*8975f5c5SAndroid Build Coastguard Worker     size_t size,
213*8975f5c5SAndroid Build Coastguard Worker     const std::vector<unsigned int> &arraySizes)
214*8975f5c5SAndroid Build Coastguard Worker {
215*8975f5c5SAndroid Build Coastguard Worker     const unsigned int innerArraySizeProduct = gl::InnerArraySizeProduct(arraySizes);
216*8975f5c5SAndroid Build Coastguard Worker     const unsigned int outermostArraySize    = gl::OutermostArraySize(arraySizes);
217*8975f5c5SAndroid Build Coastguard Worker 
218*8975f5c5SAndroid Build Coastguard Worker     // The size of struct is expected to be already aligned appropriately.
219*8975f5c5SAndroid Build Coastguard Worker     const size_t arrayStride = size * innerArraySizeProduct;
220*8975f5c5SAndroid Build Coastguard Worker     GLenum type              = GL_INVALID_ENUM;
221*8975f5c5SAndroid Build Coastguard Worker     const BlockMemberInfo memberInfo(type, static_cast<int>(mCurrentOffset * kBytesPerComponent),
222*8975f5c5SAndroid Build Coastguard Worker                                      static_cast<int>(arrayStride), -1,
223*8975f5c5SAndroid Build Coastguard Worker                                      gl::ArraySizeProduct(arraySizes), false);
224*8975f5c5SAndroid Build Coastguard Worker 
225*8975f5c5SAndroid Build Coastguard Worker     angle::base::CheckedNumeric<size_t> checkedOffset(arrayStride);
226*8975f5c5SAndroid Build Coastguard Worker     checkedOffset *= outermostArraySize;
227*8975f5c5SAndroid Build Coastguard Worker     checkedOffset /= kBytesPerComponent;
228*8975f5c5SAndroid Build Coastguard Worker     checkedOffset += mCurrentOffset;
229*8975f5c5SAndroid Build Coastguard Worker     mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
230*8975f5c5SAndroid Build Coastguard Worker 
231*8975f5c5SAndroid Build Coastguard Worker     return memberInfo;
232*8975f5c5SAndroid Build Coastguard Worker }
233*8975f5c5SAndroid Build Coastguard Worker 
getCurrentOffset() const234*8975f5c5SAndroid Build Coastguard Worker size_t BlockLayoutEncoder::getCurrentOffset() const
235*8975f5c5SAndroid Build Coastguard Worker {
236*8975f5c5SAndroid Build Coastguard Worker     angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
237*8975f5c5SAndroid Build Coastguard Worker     checkedOffset *= kBytesPerComponent;
238*8975f5c5SAndroid Build Coastguard Worker     return checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
239*8975f5c5SAndroid Build Coastguard Worker }
240*8975f5c5SAndroid Build Coastguard Worker 
getShaderVariableSize(const ShaderVariable & structVar,bool isRowMajor)241*8975f5c5SAndroid Build Coastguard Worker size_t BlockLayoutEncoder::getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor)
242*8975f5c5SAndroid Build Coastguard Worker {
243*8975f5c5SAndroid Build Coastguard Worker     size_t currentOffset = mCurrentOffset;
244*8975f5c5SAndroid Build Coastguard Worker     mCurrentOffset       = 0;
245*8975f5c5SAndroid Build Coastguard Worker     BlockEncoderVisitor visitor("", "", this);
246*8975f5c5SAndroid Build Coastguard Worker     enterAggregateType(structVar);
247*8975f5c5SAndroid Build Coastguard Worker     TraverseShaderVariables(structVar.fields, isRowMajor, &visitor);
248*8975f5c5SAndroid Build Coastguard Worker     exitAggregateType(structVar);
249*8975f5c5SAndroid Build Coastguard Worker     size_t structVarSize = getCurrentOffset();
250*8975f5c5SAndroid Build Coastguard Worker     mCurrentOffset       = currentOffset;
251*8975f5c5SAndroid Build Coastguard Worker     return structVarSize;
252*8975f5c5SAndroid Build Coastguard Worker }
253*8975f5c5SAndroid Build Coastguard Worker 
254*8975f5c5SAndroid Build Coastguard Worker // static
GetBlockRegister(const BlockMemberInfo & info)255*8975f5c5SAndroid Build Coastguard Worker size_t BlockLayoutEncoder::GetBlockRegister(const BlockMemberInfo &info)
256*8975f5c5SAndroid Build Coastguard Worker {
257*8975f5c5SAndroid Build Coastguard Worker     return (info.offset / kBytesPerComponent) / kComponentsPerRegister;
258*8975f5c5SAndroid Build Coastguard Worker }
259*8975f5c5SAndroid Build Coastguard Worker 
260*8975f5c5SAndroid Build Coastguard Worker // static
GetBlockRegisterElement(const BlockMemberInfo & info)261*8975f5c5SAndroid Build Coastguard Worker size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info)
262*8975f5c5SAndroid Build Coastguard Worker {
263*8975f5c5SAndroid Build Coastguard Worker     return (info.offset / kBytesPerComponent) % kComponentsPerRegister;
264*8975f5c5SAndroid Build Coastguard Worker }
265*8975f5c5SAndroid Build Coastguard Worker 
align(size_t baseAlignment)266*8975f5c5SAndroid Build Coastguard Worker void BlockLayoutEncoder::align(size_t baseAlignment)
267*8975f5c5SAndroid Build Coastguard Worker {
268*8975f5c5SAndroid Build Coastguard Worker     if (baseAlignment == 0)
269*8975f5c5SAndroid Build Coastguard Worker     {
270*8975f5c5SAndroid Build Coastguard Worker         return;
271*8975f5c5SAndroid Build Coastguard Worker     }
272*8975f5c5SAndroid Build Coastguard Worker     angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
273*8975f5c5SAndroid Build Coastguard Worker     checkedOffset += baseAlignment;
274*8975f5c5SAndroid Build Coastguard Worker     checkedOffset -= 1;
275*8975f5c5SAndroid Build Coastguard Worker     angle::base::CheckedNumeric<size_t> checkedAlignmentOffset = checkedOffset;
276*8975f5c5SAndroid Build Coastguard Worker     checkedAlignmentOffset %= baseAlignment;
277*8975f5c5SAndroid Build Coastguard Worker     checkedOffset -= checkedAlignmentOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
278*8975f5c5SAndroid Build Coastguard Worker     mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
279*8975f5c5SAndroid Build Coastguard Worker     assert(mCurrentOffset >= 0);
280*8975f5c5SAndroid Build Coastguard Worker }
281*8975f5c5SAndroid Build Coastguard Worker 
282*8975f5c5SAndroid Build Coastguard Worker // StubBlockEncoder implementation.
getBlockLayoutInfo(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int * arrayStrideOut,int * matrixStrideOut)283*8975f5c5SAndroid Build Coastguard Worker void StubBlockEncoder::getBlockLayoutInfo(GLenum type,
284*8975f5c5SAndroid Build Coastguard Worker                                           const std::vector<unsigned int> &arraySizes,
285*8975f5c5SAndroid Build Coastguard Worker                                           bool isRowMajorMatrix,
286*8975f5c5SAndroid Build Coastguard Worker                                           int *arrayStrideOut,
287*8975f5c5SAndroid Build Coastguard Worker                                           int *matrixStrideOut)
288*8975f5c5SAndroid Build Coastguard Worker {
289*8975f5c5SAndroid Build Coastguard Worker     *arrayStrideOut  = 0;
290*8975f5c5SAndroid Build Coastguard Worker     *matrixStrideOut = 0;
291*8975f5c5SAndroid Build Coastguard Worker }
292*8975f5c5SAndroid Build Coastguard Worker 
293*8975f5c5SAndroid Build Coastguard Worker // Std140BlockEncoder implementation.
Std140BlockEncoder()294*8975f5c5SAndroid Build Coastguard Worker Std140BlockEncoder::Std140BlockEncoder() {}
295*8975f5c5SAndroid Build Coastguard Worker 
enterAggregateType(const ShaderVariable & structVar)296*8975f5c5SAndroid Build Coastguard Worker void Std140BlockEncoder::enterAggregateType(const ShaderVariable &structVar)
297*8975f5c5SAndroid Build Coastguard Worker {
298*8975f5c5SAndroid Build Coastguard Worker     align(getBaseAlignment(structVar));
299*8975f5c5SAndroid Build Coastguard Worker }
300*8975f5c5SAndroid Build Coastguard Worker 
exitAggregateType(const ShaderVariable & structVar)301*8975f5c5SAndroid Build Coastguard Worker void Std140BlockEncoder::exitAggregateType(const ShaderVariable &structVar)
302*8975f5c5SAndroid Build Coastguard Worker {
303*8975f5c5SAndroid Build Coastguard Worker     align(getBaseAlignment(structVar));
304*8975f5c5SAndroid Build Coastguard Worker }
305*8975f5c5SAndroid Build Coastguard Worker 
getBlockLayoutInfo(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int * arrayStrideOut,int * matrixStrideOut)306*8975f5c5SAndroid Build Coastguard Worker void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
307*8975f5c5SAndroid Build Coastguard Worker                                             const std::vector<unsigned int> &arraySizes,
308*8975f5c5SAndroid Build Coastguard Worker                                             bool isRowMajorMatrix,
309*8975f5c5SAndroid Build Coastguard Worker                                             int *arrayStrideOut,
310*8975f5c5SAndroid Build Coastguard Worker                                             int *matrixStrideOut)
311*8975f5c5SAndroid Build Coastguard Worker {
312*8975f5c5SAndroid Build Coastguard Worker     // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
313*8975f5c5SAndroid Build Coastguard Worker     ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == kBytesPerComponent);
314*8975f5c5SAndroid Build Coastguard Worker 
315*8975f5c5SAndroid Build Coastguard Worker     size_t baseAlignment = 0;
316*8975f5c5SAndroid Build Coastguard Worker     int matrixStride     = 0;
317*8975f5c5SAndroid Build Coastguard Worker     int arrayStride      = 0;
318*8975f5c5SAndroid Build Coastguard Worker 
319*8975f5c5SAndroid Build Coastguard Worker     if (gl::IsMatrixType(type))
320*8975f5c5SAndroid Build Coastguard Worker     {
321*8975f5c5SAndroid Build Coastguard Worker         baseAlignment = getTypeBaseAlignment(type, isRowMajorMatrix);
322*8975f5c5SAndroid Build Coastguard Worker         matrixStride  = static_cast<int>(getTypeBaseAlignment(type, isRowMajorMatrix));
323*8975f5c5SAndroid Build Coastguard Worker 
324*8975f5c5SAndroid Build Coastguard Worker         if (!arraySizes.empty())
325*8975f5c5SAndroid Build Coastguard Worker         {
326*8975f5c5SAndroid Build Coastguard Worker             const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
327*8975f5c5SAndroid Build Coastguard Worker             arrayStride =
328*8975f5c5SAndroid Build Coastguard Worker                 static_cast<int>(getTypeBaseAlignment(type, isRowMajorMatrix) * numRegisters);
329*8975f5c5SAndroid Build Coastguard Worker         }
330*8975f5c5SAndroid Build Coastguard Worker     }
331*8975f5c5SAndroid Build Coastguard Worker     else if (!arraySizes.empty())
332*8975f5c5SAndroid Build Coastguard Worker     {
333*8975f5c5SAndroid Build Coastguard Worker         baseAlignment = static_cast<int>(getTypeBaseAlignment(type, false));
334*8975f5c5SAndroid Build Coastguard Worker         arrayStride   = static_cast<int>(getTypeBaseAlignment(type, false));
335*8975f5c5SAndroid Build Coastguard Worker     }
336*8975f5c5SAndroid Build Coastguard Worker     else
337*8975f5c5SAndroid Build Coastguard Worker     {
338*8975f5c5SAndroid Build Coastguard Worker         const size_t numComponents = static_cast<size_t>(gl::VariableComponentCount(type));
339*8975f5c5SAndroid Build Coastguard Worker         baseAlignment              = ComponentAlignment(numComponents);
340*8975f5c5SAndroid Build Coastguard Worker     }
341*8975f5c5SAndroid Build Coastguard Worker 
342*8975f5c5SAndroid Build Coastguard Worker     align(baseAlignment);
343*8975f5c5SAndroid Build Coastguard Worker 
344*8975f5c5SAndroid Build Coastguard Worker     *matrixStrideOut = matrixStride;
345*8975f5c5SAndroid Build Coastguard Worker     *arrayStrideOut  = arrayStride;
346*8975f5c5SAndroid Build Coastguard Worker }
347*8975f5c5SAndroid Build Coastguard Worker 
advanceOffset(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int arrayStride,int matrixStride)348*8975f5c5SAndroid Build Coastguard Worker void Std140BlockEncoder::advanceOffset(GLenum type,
349*8975f5c5SAndroid Build Coastguard Worker                                        const std::vector<unsigned int> &arraySizes,
350*8975f5c5SAndroid Build Coastguard Worker                                        bool isRowMajorMatrix,
351*8975f5c5SAndroid Build Coastguard Worker                                        int arrayStride,
352*8975f5c5SAndroid Build Coastguard Worker                                        int matrixStride)
353*8975f5c5SAndroid Build Coastguard Worker {
354*8975f5c5SAndroid Build Coastguard Worker     if (!arraySizes.empty())
355*8975f5c5SAndroid Build Coastguard Worker     {
356*8975f5c5SAndroid Build Coastguard Worker         angle::base::CheckedNumeric<size_t> checkedOffset(arrayStride);
357*8975f5c5SAndroid Build Coastguard Worker         checkedOffset *= gl::ArraySizeProduct(arraySizes);
358*8975f5c5SAndroid Build Coastguard Worker         checkedOffset += mCurrentOffset;
359*8975f5c5SAndroid Build Coastguard Worker         mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
360*8975f5c5SAndroid Build Coastguard Worker     }
361*8975f5c5SAndroid Build Coastguard Worker     else if (gl::IsMatrixType(type))
362*8975f5c5SAndroid Build Coastguard Worker     {
363*8975f5c5SAndroid Build Coastguard Worker         angle::base::CheckedNumeric<size_t> checkedOffset(matrixStride);
364*8975f5c5SAndroid Build Coastguard Worker         checkedOffset *= gl::MatrixRegisterCount(type, isRowMajorMatrix);
365*8975f5c5SAndroid Build Coastguard Worker         checkedOffset += mCurrentOffset;
366*8975f5c5SAndroid Build Coastguard Worker         mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
367*8975f5c5SAndroid Build Coastguard Worker     }
368*8975f5c5SAndroid Build Coastguard Worker     else
369*8975f5c5SAndroid Build Coastguard Worker     {
370*8975f5c5SAndroid Build Coastguard Worker         angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
371*8975f5c5SAndroid Build Coastguard Worker         checkedOffset += gl::VariableComponentCount(type);
372*8975f5c5SAndroid Build Coastguard Worker         mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
373*8975f5c5SAndroid Build Coastguard Worker     }
374*8975f5c5SAndroid Build Coastguard Worker }
375*8975f5c5SAndroid Build Coastguard Worker 
getBaseAlignment(const ShaderVariable & variable) const376*8975f5c5SAndroid Build Coastguard Worker size_t Std140BlockEncoder::getBaseAlignment(const ShaderVariable &variable) const
377*8975f5c5SAndroid Build Coastguard Worker {
378*8975f5c5SAndroid Build Coastguard Worker     return kComponentsPerRegister;
379*8975f5c5SAndroid Build Coastguard Worker }
380*8975f5c5SAndroid Build Coastguard Worker 
getTypeBaseAlignment(GLenum type,bool isRowMajorMatrix) const381*8975f5c5SAndroid Build Coastguard Worker size_t Std140BlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const
382*8975f5c5SAndroid Build Coastguard Worker {
383*8975f5c5SAndroid Build Coastguard Worker     return kComponentsPerRegister;
384*8975f5c5SAndroid Build Coastguard Worker }
385*8975f5c5SAndroid Build Coastguard Worker 
386*8975f5c5SAndroid Build Coastguard Worker // Std430BlockEncoder implementation.
Std430BlockEncoder()387*8975f5c5SAndroid Build Coastguard Worker Std430BlockEncoder::Std430BlockEncoder() {}
388*8975f5c5SAndroid Build Coastguard Worker 
getBaseAlignment(const ShaderVariable & shaderVar) const389*8975f5c5SAndroid Build Coastguard Worker size_t Std430BlockEncoder::getBaseAlignment(const ShaderVariable &shaderVar) const
390*8975f5c5SAndroid Build Coastguard Worker {
391*8975f5c5SAndroid Build Coastguard Worker     if (shaderVar.isStruct())
392*8975f5c5SAndroid Build Coastguard Worker     {
393*8975f5c5SAndroid Build Coastguard Worker         BaseAlignmentVisitor visitor;
394*8975f5c5SAndroid Build Coastguard Worker         TraverseShaderVariables(shaderVar.fields, false, &visitor);
395*8975f5c5SAndroid Build Coastguard Worker         return visitor.getBaseAlignment();
396*8975f5c5SAndroid Build Coastguard Worker     }
397*8975f5c5SAndroid Build Coastguard Worker 
398*8975f5c5SAndroid Build Coastguard Worker     return GetStd430BaseAlignment(shaderVar.type, shaderVar.isRowMajorLayout);
399*8975f5c5SAndroid Build Coastguard Worker }
400*8975f5c5SAndroid Build Coastguard Worker 
getTypeBaseAlignment(GLenum type,bool isRowMajorMatrix) const401*8975f5c5SAndroid Build Coastguard Worker size_t Std430BlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const
402*8975f5c5SAndroid Build Coastguard Worker {
403*8975f5c5SAndroid Build Coastguard Worker     return GetStd430BaseAlignment(type, isRowMajorMatrix);
404*8975f5c5SAndroid Build Coastguard Worker }
405*8975f5c5SAndroid Build Coastguard Worker 
GetInterfaceBlockInfo(const std::vector<ShaderVariable> & fields,const std::string & prefix,BlockLayoutEncoder * encoder,BlockLayoutMap * blockInfoOut)406*8975f5c5SAndroid Build Coastguard Worker void GetInterfaceBlockInfo(const std::vector<ShaderVariable> &fields,
407*8975f5c5SAndroid Build Coastguard Worker                            const std::string &prefix,
408*8975f5c5SAndroid Build Coastguard Worker                            BlockLayoutEncoder *encoder,
409*8975f5c5SAndroid Build Coastguard Worker                            BlockLayoutMap *blockInfoOut)
410*8975f5c5SAndroid Build Coastguard Worker {
411*8975f5c5SAndroid Build Coastguard Worker     // Matrix packing is always recorded in individual fields, so they'll set the row major layout
412*8975f5c5SAndroid Build Coastguard Worker     // flag to true if needed.
413*8975f5c5SAndroid Build Coastguard Worker     // Iterates over all variables.
414*8975f5c5SAndroid Build Coastguard Worker     GetInterfaceBlockInfo(fields, prefix, encoder, false, false, blockInfoOut);
415*8975f5c5SAndroid Build Coastguard Worker }
416*8975f5c5SAndroid Build Coastguard Worker 
GetActiveUniformBlockInfo(const std::vector<ShaderVariable> & uniforms,const std::string & prefix,BlockLayoutEncoder * encoder,BlockLayoutMap * blockInfoOut)417*8975f5c5SAndroid Build Coastguard Worker void GetActiveUniformBlockInfo(const std::vector<ShaderVariable> &uniforms,
418*8975f5c5SAndroid Build Coastguard Worker                                const std::string &prefix,
419*8975f5c5SAndroid Build Coastguard Worker                                BlockLayoutEncoder *encoder,
420*8975f5c5SAndroid Build Coastguard Worker                                BlockLayoutMap *blockInfoOut)
421*8975f5c5SAndroid Build Coastguard Worker {
422*8975f5c5SAndroid Build Coastguard Worker     // Matrix packing is always recorded in individual fields, so they'll set the row major layout
423*8975f5c5SAndroid Build Coastguard Worker     // flag to true if needed.
424*8975f5c5SAndroid Build Coastguard Worker     // Iterates only over the active variables.
425*8975f5c5SAndroid Build Coastguard Worker     GetInterfaceBlockInfo(uniforms, prefix, encoder, false, true, blockInfoOut);
426*8975f5c5SAndroid Build Coastguard Worker }
427*8975f5c5SAndroid Build Coastguard Worker 
428*8975f5c5SAndroid Build Coastguard Worker // VariableNameVisitor implementation.
VariableNameVisitor(const std::string & namePrefix,const std::string & mappedNamePrefix)429*8975f5c5SAndroid Build Coastguard Worker VariableNameVisitor::VariableNameVisitor(const std::string &namePrefix,
430*8975f5c5SAndroid Build Coastguard Worker                                          const std::string &mappedNamePrefix)
431*8975f5c5SAndroid Build Coastguard Worker {
432*8975f5c5SAndroid Build Coastguard Worker     if (!namePrefix.empty())
433*8975f5c5SAndroid Build Coastguard Worker     {
434*8975f5c5SAndroid Build Coastguard Worker         mNameStack.push_back(namePrefix + ".");
435*8975f5c5SAndroid Build Coastguard Worker     }
436*8975f5c5SAndroid Build Coastguard Worker 
437*8975f5c5SAndroid Build Coastguard Worker     if (!mappedNamePrefix.empty())
438*8975f5c5SAndroid Build Coastguard Worker     {
439*8975f5c5SAndroid Build Coastguard Worker         mMappedNameStack.push_back(mappedNamePrefix + ".");
440*8975f5c5SAndroid Build Coastguard Worker     }
441*8975f5c5SAndroid Build Coastguard Worker }
442*8975f5c5SAndroid Build Coastguard Worker 
443*8975f5c5SAndroid Build Coastguard Worker VariableNameVisitor::~VariableNameVisitor() = default;
444*8975f5c5SAndroid Build Coastguard Worker 
enterStruct(const ShaderVariable & structVar)445*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::enterStruct(const ShaderVariable &structVar)
446*8975f5c5SAndroid Build Coastguard Worker {
447*8975f5c5SAndroid Build Coastguard Worker     mNameStack.push_back(structVar.name);
448*8975f5c5SAndroid Build Coastguard Worker     mMappedNameStack.push_back(structVar.mappedName);
449*8975f5c5SAndroid Build Coastguard Worker }
450*8975f5c5SAndroid Build Coastguard Worker 
exitStruct(const ShaderVariable & structVar)451*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::exitStruct(const ShaderVariable &structVar)
452*8975f5c5SAndroid Build Coastguard Worker {
453*8975f5c5SAndroid Build Coastguard Worker     mNameStack.pop_back();
454*8975f5c5SAndroid Build Coastguard Worker     mMappedNameStack.pop_back();
455*8975f5c5SAndroid Build Coastguard Worker }
456*8975f5c5SAndroid Build Coastguard Worker 
enterStructAccess(const ShaderVariable & structVar,bool isRowMajor)457*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor)
458*8975f5c5SAndroid Build Coastguard Worker {
459*8975f5c5SAndroid Build Coastguard Worker     mNameStack.push_back(".");
460*8975f5c5SAndroid Build Coastguard Worker     mMappedNameStack.push_back(".");
461*8975f5c5SAndroid Build Coastguard Worker }
462*8975f5c5SAndroid Build Coastguard Worker 
exitStructAccess(const ShaderVariable & structVar,bool isRowMajor)463*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor)
464*8975f5c5SAndroid Build Coastguard Worker {
465*8975f5c5SAndroid Build Coastguard Worker     mNameStack.pop_back();
466*8975f5c5SAndroid Build Coastguard Worker     mMappedNameStack.pop_back();
467*8975f5c5SAndroid Build Coastguard Worker }
468*8975f5c5SAndroid Build Coastguard Worker 
enterArray(const ShaderVariable & arrayVar)469*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::enterArray(const ShaderVariable &arrayVar)
470*8975f5c5SAndroid Build Coastguard Worker {
471*8975f5c5SAndroid Build Coastguard Worker     if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct())
472*8975f5c5SAndroid Build Coastguard Worker     {
473*8975f5c5SAndroid Build Coastguard Worker         mNameStack.push_back(arrayVar.name);
474*8975f5c5SAndroid Build Coastguard Worker         mMappedNameStack.push_back(arrayVar.mappedName);
475*8975f5c5SAndroid Build Coastguard Worker     }
476*8975f5c5SAndroid Build Coastguard Worker     mArraySizeStack.push_back(arrayVar.getOutermostArraySize());
477*8975f5c5SAndroid Build Coastguard Worker }
478*8975f5c5SAndroid Build Coastguard Worker 
exitArray(const ShaderVariable & arrayVar)479*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::exitArray(const ShaderVariable &arrayVar)
480*8975f5c5SAndroid Build Coastguard Worker {
481*8975f5c5SAndroid Build Coastguard Worker     if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct())
482*8975f5c5SAndroid Build Coastguard Worker     {
483*8975f5c5SAndroid Build Coastguard Worker         mNameStack.pop_back();
484*8975f5c5SAndroid Build Coastguard Worker         mMappedNameStack.pop_back();
485*8975f5c5SAndroid Build Coastguard Worker     }
486*8975f5c5SAndroid Build Coastguard Worker     mArraySizeStack.pop_back();
487*8975f5c5SAndroid Build Coastguard Worker }
488*8975f5c5SAndroid Build Coastguard Worker 
enterArrayElement(const ShaderVariable & arrayVar,unsigned int arrayElement)489*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::enterArrayElement(const ShaderVariable &arrayVar,
490*8975f5c5SAndroid Build Coastguard Worker                                             unsigned int arrayElement)
491*8975f5c5SAndroid Build Coastguard Worker {
492*8975f5c5SAndroid Build Coastguard Worker     std::stringstream strstr = sh::InitializeStream<std::stringstream>();
493*8975f5c5SAndroid Build Coastguard Worker     strstr << "[" << arrayElement << "]";
494*8975f5c5SAndroid Build Coastguard Worker     std::string elementString = strstr.str();
495*8975f5c5SAndroid Build Coastguard Worker     mNameStack.push_back(elementString);
496*8975f5c5SAndroid Build Coastguard Worker     mMappedNameStack.push_back(elementString);
497*8975f5c5SAndroid Build Coastguard Worker }
498*8975f5c5SAndroid Build Coastguard Worker 
exitArrayElement(const ShaderVariable & arrayVar,unsigned int arrayElement)499*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::exitArrayElement(const ShaderVariable &arrayVar,
500*8975f5c5SAndroid Build Coastguard Worker                                            unsigned int arrayElement)
501*8975f5c5SAndroid Build Coastguard Worker {
502*8975f5c5SAndroid Build Coastguard Worker     mNameStack.pop_back();
503*8975f5c5SAndroid Build Coastguard Worker     mMappedNameStack.pop_back();
504*8975f5c5SAndroid Build Coastguard Worker }
505*8975f5c5SAndroid Build Coastguard Worker 
collapseNameStack() const506*8975f5c5SAndroid Build Coastguard Worker std::string VariableNameVisitor::collapseNameStack() const
507*8975f5c5SAndroid Build Coastguard Worker {
508*8975f5c5SAndroid Build Coastguard Worker     return CollapseNameStack(mNameStack);
509*8975f5c5SAndroid Build Coastguard Worker }
510*8975f5c5SAndroid Build Coastguard Worker 
collapseMappedNameStack() const511*8975f5c5SAndroid Build Coastguard Worker std::string VariableNameVisitor::collapseMappedNameStack() const
512*8975f5c5SAndroid Build Coastguard Worker {
513*8975f5c5SAndroid Build Coastguard Worker     return CollapseNameStack(mMappedNameStack);
514*8975f5c5SAndroid Build Coastguard Worker }
515*8975f5c5SAndroid Build Coastguard Worker 
visitOpaqueObject(const sh::ShaderVariable & variable)516*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::visitOpaqueObject(const sh::ShaderVariable &variable)
517*8975f5c5SAndroid Build Coastguard Worker {
518*8975f5c5SAndroid Build Coastguard Worker     if (!variable.hasParentArrayIndex())
519*8975f5c5SAndroid Build Coastguard Worker     {
520*8975f5c5SAndroid Build Coastguard Worker         mNameStack.push_back(variable.name);
521*8975f5c5SAndroid Build Coastguard Worker         mMappedNameStack.push_back(variable.mappedName);
522*8975f5c5SAndroid Build Coastguard Worker     }
523*8975f5c5SAndroid Build Coastguard Worker 
524*8975f5c5SAndroid Build Coastguard Worker     std::string name       = collapseNameStack();
525*8975f5c5SAndroid Build Coastguard Worker     std::string mappedName = collapseMappedNameStack();
526*8975f5c5SAndroid Build Coastguard Worker 
527*8975f5c5SAndroid Build Coastguard Worker     if (!variable.hasParentArrayIndex())
528*8975f5c5SAndroid Build Coastguard Worker     {
529*8975f5c5SAndroid Build Coastguard Worker         mNameStack.pop_back();
530*8975f5c5SAndroid Build Coastguard Worker         mMappedNameStack.pop_back();
531*8975f5c5SAndroid Build Coastguard Worker     }
532*8975f5c5SAndroid Build Coastguard Worker 
533*8975f5c5SAndroid Build Coastguard Worker     visitNamedOpaqueObject(variable, name, mappedName, mArraySizeStack);
534*8975f5c5SAndroid Build Coastguard Worker }
535*8975f5c5SAndroid Build Coastguard Worker 
visitVariable(const ShaderVariable & variable,bool isRowMajor)536*8975f5c5SAndroid Build Coastguard Worker void VariableNameVisitor::visitVariable(const ShaderVariable &variable, bool isRowMajor)
537*8975f5c5SAndroid Build Coastguard Worker {
538*8975f5c5SAndroid Build Coastguard Worker     if (!variable.hasParentArrayIndex())
539*8975f5c5SAndroid Build Coastguard Worker     {
540*8975f5c5SAndroid Build Coastguard Worker         mNameStack.push_back(variable.name);
541*8975f5c5SAndroid Build Coastguard Worker         mMappedNameStack.push_back(variable.mappedName);
542*8975f5c5SAndroid Build Coastguard Worker     }
543*8975f5c5SAndroid Build Coastguard Worker 
544*8975f5c5SAndroid Build Coastguard Worker     std::string name       = collapseNameStack();
545*8975f5c5SAndroid Build Coastguard Worker     std::string mappedName = collapseMappedNameStack();
546*8975f5c5SAndroid Build Coastguard Worker 
547*8975f5c5SAndroid Build Coastguard Worker     if (!variable.hasParentArrayIndex())
548*8975f5c5SAndroid Build Coastguard Worker     {
549*8975f5c5SAndroid Build Coastguard Worker         mNameStack.pop_back();
550*8975f5c5SAndroid Build Coastguard Worker         mMappedNameStack.pop_back();
551*8975f5c5SAndroid Build Coastguard Worker     }
552*8975f5c5SAndroid Build Coastguard Worker 
553*8975f5c5SAndroid Build Coastguard Worker     visitNamedVariable(variable, isRowMajor, name, mappedName, mArraySizeStack);
554*8975f5c5SAndroid Build Coastguard Worker }
555*8975f5c5SAndroid Build Coastguard Worker 
556*8975f5c5SAndroid Build Coastguard Worker // BlockEncoderVisitor implementation.
BlockEncoderVisitor(const std::string & namePrefix,const std::string & mappedNamePrefix,BlockLayoutEncoder * encoder)557*8975f5c5SAndroid Build Coastguard Worker BlockEncoderVisitor::BlockEncoderVisitor(const std::string &namePrefix,
558*8975f5c5SAndroid Build Coastguard Worker                                          const std::string &mappedNamePrefix,
559*8975f5c5SAndroid Build Coastguard Worker                                          BlockLayoutEncoder *encoder)
560*8975f5c5SAndroid Build Coastguard Worker     : VariableNameVisitor(namePrefix, mappedNamePrefix), mEncoder(encoder)
561*8975f5c5SAndroid Build Coastguard Worker {}
562*8975f5c5SAndroid Build Coastguard Worker 
563*8975f5c5SAndroid Build Coastguard Worker BlockEncoderVisitor::~BlockEncoderVisitor() = default;
564*8975f5c5SAndroid Build Coastguard Worker 
enterStructAccess(const ShaderVariable & structVar,bool isRowMajor)565*8975f5c5SAndroid Build Coastguard Worker void BlockEncoderVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor)
566*8975f5c5SAndroid Build Coastguard Worker {
567*8975f5c5SAndroid Build Coastguard Worker     mStructStackSize++;
568*8975f5c5SAndroid Build Coastguard Worker     if (!mIsTopLevelArrayStrideReady)
569*8975f5c5SAndroid Build Coastguard Worker     {
570*8975f5c5SAndroid Build Coastguard Worker         size_t structSize = mEncoder->getShaderVariableSize(structVar, isRowMajor);
571*8975f5c5SAndroid Build Coastguard Worker         mTopLevelArrayStride *= structSize;
572*8975f5c5SAndroid Build Coastguard Worker         mIsTopLevelArrayStrideReady = true;
573*8975f5c5SAndroid Build Coastguard Worker     }
574*8975f5c5SAndroid Build Coastguard Worker 
575*8975f5c5SAndroid Build Coastguard Worker     VariableNameVisitor::enterStructAccess(structVar, isRowMajor);
576*8975f5c5SAndroid Build Coastguard Worker     mEncoder->enterAggregateType(structVar);
577*8975f5c5SAndroid Build Coastguard Worker }
578*8975f5c5SAndroid Build Coastguard Worker 
exitStructAccess(const ShaderVariable & structVar,bool isRowMajor)579*8975f5c5SAndroid Build Coastguard Worker void BlockEncoderVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor)
580*8975f5c5SAndroid Build Coastguard Worker {
581*8975f5c5SAndroid Build Coastguard Worker     mStructStackSize--;
582*8975f5c5SAndroid Build Coastguard Worker     mEncoder->exitAggregateType(structVar);
583*8975f5c5SAndroid Build Coastguard Worker     VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
584*8975f5c5SAndroid Build Coastguard Worker }
585*8975f5c5SAndroid Build Coastguard Worker 
enterArrayElement(const sh::ShaderVariable & arrayVar,unsigned int arrayElement)586*8975f5c5SAndroid Build Coastguard Worker void BlockEncoderVisitor::enterArrayElement(const sh::ShaderVariable &arrayVar,
587*8975f5c5SAndroid Build Coastguard Worker                                             unsigned int arrayElement)
588*8975f5c5SAndroid Build Coastguard Worker {
589*8975f5c5SAndroid Build Coastguard Worker     if (mStructStackSize == 0 && !arrayVar.hasParentArrayIndex())
590*8975f5c5SAndroid Build Coastguard Worker     {
591*8975f5c5SAndroid Build Coastguard Worker         // From the ES 3.1 spec "7.3.1.1 Naming Active Resources":
592*8975f5c5SAndroid Build Coastguard Worker         // For an active shader storage block member declared as an array of an aggregate type,
593*8975f5c5SAndroid Build Coastguard Worker         // an entry will be generated only for the first array element, regardless of its type.
594*8975f5c5SAndroid Build Coastguard Worker         // Such block members are referred to as top-level arrays. If the block member is an
595*8975f5c5SAndroid Build Coastguard Worker         // aggregate type, the enumeration rules are then applied recursively.
596*8975f5c5SAndroid Build Coastguard Worker         if (arrayElement == 0)
597*8975f5c5SAndroid Build Coastguard Worker         {
598*8975f5c5SAndroid Build Coastguard Worker             mTopLevelArraySize          = arrayVar.getOutermostArraySize();
599*8975f5c5SAndroid Build Coastguard Worker             mTopLevelArrayStride        = arrayVar.getInnerArraySizeProduct();
600*8975f5c5SAndroid Build Coastguard Worker             mIsTopLevelArrayStrideReady = false;
601*8975f5c5SAndroid Build Coastguard Worker         }
602*8975f5c5SAndroid Build Coastguard Worker         else
603*8975f5c5SAndroid Build Coastguard Worker         {
604*8975f5c5SAndroid Build Coastguard Worker             mSkipEnabled = true;
605*8975f5c5SAndroid Build Coastguard Worker         }
606*8975f5c5SAndroid Build Coastguard Worker     }
607*8975f5c5SAndroid Build Coastguard Worker     VariableNameVisitor::enterArrayElement(arrayVar, arrayElement);
608*8975f5c5SAndroid Build Coastguard Worker }
609*8975f5c5SAndroid Build Coastguard Worker 
exitArrayElement(const sh::ShaderVariable & arrayVar,unsigned int arrayElement)610*8975f5c5SAndroid Build Coastguard Worker void BlockEncoderVisitor::exitArrayElement(const sh::ShaderVariable &arrayVar,
611*8975f5c5SAndroid Build Coastguard Worker                                            unsigned int arrayElement)
612*8975f5c5SAndroid Build Coastguard Worker {
613*8975f5c5SAndroid Build Coastguard Worker     if (mStructStackSize == 0 && !arrayVar.hasParentArrayIndex())
614*8975f5c5SAndroid Build Coastguard Worker     {
615*8975f5c5SAndroid Build Coastguard Worker         mTopLevelArraySize          = 1;
616*8975f5c5SAndroid Build Coastguard Worker         mTopLevelArrayStride        = 0;
617*8975f5c5SAndroid Build Coastguard Worker         mIsTopLevelArrayStrideReady = true;
618*8975f5c5SAndroid Build Coastguard Worker         mSkipEnabled                = false;
619*8975f5c5SAndroid Build Coastguard Worker     }
620*8975f5c5SAndroid Build Coastguard Worker     VariableNameVisitor::exitArrayElement(arrayVar, arrayElement);
621*8975f5c5SAndroid Build Coastguard Worker }
622*8975f5c5SAndroid Build Coastguard Worker 
visitNamedVariable(const ShaderVariable & variable,bool isRowMajor,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)623*8975f5c5SAndroid Build Coastguard Worker void BlockEncoderVisitor::visitNamedVariable(const ShaderVariable &variable,
624*8975f5c5SAndroid Build Coastguard Worker                                              bool isRowMajor,
625*8975f5c5SAndroid Build Coastguard Worker                                              const std::string &name,
626*8975f5c5SAndroid Build Coastguard Worker                                              const std::string &mappedName,
627*8975f5c5SAndroid Build Coastguard Worker                                              const std::vector<unsigned int> &arraySizes)
628*8975f5c5SAndroid Build Coastguard Worker {
629*8975f5c5SAndroid Build Coastguard Worker     std::vector<unsigned int> innermostArraySize;
630*8975f5c5SAndroid Build Coastguard Worker 
631*8975f5c5SAndroid Build Coastguard Worker     if (variable.isArray())
632*8975f5c5SAndroid Build Coastguard Worker     {
633*8975f5c5SAndroid Build Coastguard Worker         innermostArraySize.push_back(variable.getNestedArraySize(0));
634*8975f5c5SAndroid Build Coastguard Worker     }
635*8975f5c5SAndroid Build Coastguard Worker     BlockMemberInfo variableInfo =
636*8975f5c5SAndroid Build Coastguard Worker         mEncoder->encodeType(variable.type, innermostArraySize, isRowMajor);
637*8975f5c5SAndroid Build Coastguard Worker     if (!mIsTopLevelArrayStrideReady)
638*8975f5c5SAndroid Build Coastguard Worker     {
639*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mTopLevelArrayStride);
640*8975f5c5SAndroid Build Coastguard Worker         mTopLevelArrayStride *= variableInfo.arrayStride;
641*8975f5c5SAndroid Build Coastguard Worker         mIsTopLevelArrayStrideReady = true;
642*8975f5c5SAndroid Build Coastguard Worker     }
643*8975f5c5SAndroid Build Coastguard Worker     variableInfo.topLevelArrayStride = mTopLevelArrayStride;
644*8975f5c5SAndroid Build Coastguard Worker     encodeVariable(variable, variableInfo, name, mappedName);
645*8975f5c5SAndroid Build Coastguard Worker }
646*8975f5c5SAndroid Build Coastguard Worker 
TraverseShaderVariable(const ShaderVariable & variable,bool isRowMajorLayout,ShaderVariableVisitor * visitor)647*8975f5c5SAndroid Build Coastguard Worker void TraverseShaderVariable(const ShaderVariable &variable,
648*8975f5c5SAndroid Build Coastguard Worker                             bool isRowMajorLayout,
649*8975f5c5SAndroid Build Coastguard Worker                             ShaderVariableVisitor *visitor)
650*8975f5c5SAndroid Build Coastguard Worker {
651*8975f5c5SAndroid Build Coastguard Worker     bool rowMajorLayout = (isRowMajorLayout || variable.isRowMajorLayout);
652*8975f5c5SAndroid Build Coastguard Worker     bool isRowMajor     = rowMajorLayout && gl::IsMatrixType(variable.type);
653*8975f5c5SAndroid Build Coastguard Worker 
654*8975f5c5SAndroid Build Coastguard Worker     if (variable.isStruct())
655*8975f5c5SAndroid Build Coastguard Worker     {
656*8975f5c5SAndroid Build Coastguard Worker         visitor->enterStruct(variable);
657*8975f5c5SAndroid Build Coastguard Worker         if (variable.isArray())
658*8975f5c5SAndroid Build Coastguard Worker         {
659*8975f5c5SAndroid Build Coastguard Worker             TraverseStructArrayVariable(variable, rowMajorLayout, visitor);
660*8975f5c5SAndroid Build Coastguard Worker         }
661*8975f5c5SAndroid Build Coastguard Worker         else
662*8975f5c5SAndroid Build Coastguard Worker         {
663*8975f5c5SAndroid Build Coastguard Worker             TraverseStructVariable(variable, rowMajorLayout, visitor);
664*8975f5c5SAndroid Build Coastguard Worker         }
665*8975f5c5SAndroid Build Coastguard Worker         visitor->exitStruct(variable);
666*8975f5c5SAndroid Build Coastguard Worker     }
667*8975f5c5SAndroid Build Coastguard Worker     else if (variable.isArrayOfArrays())
668*8975f5c5SAndroid Build Coastguard Worker     {
669*8975f5c5SAndroid Build Coastguard Worker         TraverseArrayOfArraysVariable(variable, 0u, isRowMajor, visitor);
670*8975f5c5SAndroid Build Coastguard Worker     }
671*8975f5c5SAndroid Build Coastguard Worker     else if (gl::IsSamplerType(variable.type) || gl::IsImageType(variable.type) ||
672*8975f5c5SAndroid Build Coastguard Worker              variable.isFragmentInOut)
673*8975f5c5SAndroid Build Coastguard Worker     {
674*8975f5c5SAndroid Build Coastguard Worker         visitor->visitOpaqueObject(variable);
675*8975f5c5SAndroid Build Coastguard Worker     }
676*8975f5c5SAndroid Build Coastguard Worker     else
677*8975f5c5SAndroid Build Coastguard Worker     {
678*8975f5c5SAndroid Build Coastguard Worker         visitor->visitVariable(variable, isRowMajor);
679*8975f5c5SAndroid Build Coastguard Worker     }
680*8975f5c5SAndroid Build Coastguard Worker }
681*8975f5c5SAndroid Build Coastguard Worker 
682*8975f5c5SAndroid Build Coastguard Worker }  // namespace sh
683