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