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