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) || gl::IsImageType(variable.type) ||
129 variable.isFragmentInOut)
130 {
131 visitor->visitOpaqueObject(elementVar);
132 }
133 else
134 {
135 visitor->visitVariable(elementVar, isRowMajorMatrix);
136 }
137 }
138
139 visitor->exitArrayElement(variable, arrayElement);
140 }
141
142 visitor->exitArray(variable);
143 }
144
CollapseNameStack(const std::vector<std::string> & nameStack)145 std::string CollapseNameStack(const std::vector<std::string> &nameStack)
146 {
147 std::stringstream strstr = sh::InitializeStream<std::stringstream>();
148 for (const std::string &part : nameStack)
149 {
150 strstr << part;
151 }
152 return strstr.str();
153 }
154
GetStd430BaseAlignment(GLenum variableType,bool isRowMajor)155 size_t GetStd430BaseAlignment(GLenum variableType, bool isRowMajor)
156 {
157 GLenum flippedType = isRowMajor ? variableType : gl::TransposeMatrixType(variableType);
158 size_t numComponents = static_cast<size_t>(gl::VariableColumnCount(flippedType));
159 return ComponentAlignment(numComponents);
160 }
161
162 class BaseAlignmentVisitor : public ShaderVariableVisitor
163 {
164 public:
165 BaseAlignmentVisitor() = default;
visitVariable(const ShaderVariable & variable,bool isRowMajor)166 void visitVariable(const ShaderVariable &variable, bool isRowMajor) override
167 {
168 size_t baseAlignment = GetStd430BaseAlignment(variable.type, isRowMajor);
169 mCurrentAlignment = std::max(mCurrentAlignment, baseAlignment);
170 }
171
172 // This is in components rather than bytes.
getBaseAlignment() const173 size_t getBaseAlignment() const { return mCurrentAlignment; }
174
175 private:
176 size_t mCurrentAlignment = 0;
177 };
178 } // anonymous namespace
179
180 // BlockLayoutEncoder implementation.
BlockLayoutEncoder()181 BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) {}
182
encodeType(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix)183 BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
184 const std::vector<unsigned int> &arraySizes,
185 bool isRowMajorMatrix)
186 {
187 int arrayStride;
188 int matrixStride;
189
190 getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride);
191
192 const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * kBytesPerComponent),
193 static_cast<int>(arrayStride * kBytesPerComponent),
194 static_cast<int>(matrixStride * kBytesPerComponent),
195 isRowMajorMatrix);
196
197 advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride);
198
199 return memberInfo;
200 }
201
encodeArrayOfPreEncodedStructs(size_t size,const std::vector<unsigned int> & arraySizes)202 BlockMemberInfo BlockLayoutEncoder::encodeArrayOfPreEncodedStructs(
203 size_t size,
204 const std::vector<unsigned int> &arraySizes)
205 {
206 const unsigned int innerArraySizeProduct = gl::InnerArraySizeProduct(arraySizes);
207 const unsigned int outermostArraySize = gl::OutermostArraySize(arraySizes);
208
209 // The size of struct is expected to be already aligned appropriately.
210 const size_t arrayStride = size * innerArraySizeProduct;
211
212 const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * kBytesPerComponent),
213 static_cast<int>(arrayStride), -1, false);
214
215 mCurrentOffset += arrayStride * outermostArraySize / kBytesPerComponent;
216
217 return memberInfo;
218 }
219
getShaderVariableSize(const ShaderVariable & structVar,bool isRowMajor)220 size_t BlockLayoutEncoder::getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor)
221 {
222 size_t currentOffset = mCurrentOffset;
223 mCurrentOffset = 0;
224 BlockEncoderVisitor visitor("", "", this);
225 enterAggregateType(structVar);
226 TraverseShaderVariables(structVar.fields, isRowMajor, &visitor);
227 exitAggregateType(structVar);
228 size_t structVarSize = getCurrentOffset();
229 mCurrentOffset = currentOffset;
230 return structVarSize;
231 }
232
233 // static
GetBlockRegister(const BlockMemberInfo & info)234 size_t BlockLayoutEncoder::GetBlockRegister(const BlockMemberInfo &info)
235 {
236 return (info.offset / kBytesPerComponent) / kComponentsPerRegister;
237 }
238
239 // static
GetBlockRegisterElement(const BlockMemberInfo & info)240 size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info)
241 {
242 return (info.offset / kBytesPerComponent) % kComponentsPerRegister;
243 }
244
align(size_t baseAlignment)245 void BlockLayoutEncoder::align(size_t baseAlignment)
246 {
247 mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, baseAlignment);
248 }
249
250 // StubBlockEncoder implementation.
getBlockLayoutInfo(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int * arrayStrideOut,int * matrixStrideOut)251 void StubBlockEncoder::getBlockLayoutInfo(GLenum type,
252 const std::vector<unsigned int> &arraySizes,
253 bool isRowMajorMatrix,
254 int *arrayStrideOut,
255 int *matrixStrideOut)
256 {
257 *arrayStrideOut = 0;
258 *matrixStrideOut = 0;
259 }
260
261 // Std140BlockEncoder implementation.
Std140BlockEncoder()262 Std140BlockEncoder::Std140BlockEncoder() {}
263
enterAggregateType(const ShaderVariable & structVar)264 void Std140BlockEncoder::enterAggregateType(const ShaderVariable &structVar)
265 {
266 align(getBaseAlignment(structVar));
267 }
268
exitAggregateType(const ShaderVariable & structVar)269 void Std140BlockEncoder::exitAggregateType(const ShaderVariable &structVar)
270 {
271 align(getBaseAlignment(structVar));
272 }
273
getBlockLayoutInfo(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int * arrayStrideOut,int * matrixStrideOut)274 void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
275 const std::vector<unsigned int> &arraySizes,
276 bool isRowMajorMatrix,
277 int *arrayStrideOut,
278 int *matrixStrideOut)
279 {
280 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
281 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == kBytesPerComponent);
282
283 size_t baseAlignment = 0;
284 int matrixStride = 0;
285 int arrayStride = 0;
286
287 if (gl::IsMatrixType(type))
288 {
289 baseAlignment = getTypeBaseAlignment(type, isRowMajorMatrix);
290 matrixStride = static_cast<int>(getTypeBaseAlignment(type, isRowMajorMatrix));
291
292 if (!arraySizes.empty())
293 {
294 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
295 arrayStride =
296 static_cast<int>(getTypeBaseAlignment(type, isRowMajorMatrix) * numRegisters);
297 }
298 }
299 else if (!arraySizes.empty())
300 {
301 baseAlignment = static_cast<int>(getTypeBaseAlignment(type, false));
302 arrayStride = static_cast<int>(getTypeBaseAlignment(type, false));
303 }
304 else
305 {
306 const size_t numComponents = static_cast<size_t>(gl::VariableComponentCount(type));
307 baseAlignment = ComponentAlignment(numComponents);
308 }
309
310 mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
311
312 *matrixStrideOut = matrixStride;
313 *arrayStrideOut = arrayStride;
314 }
315
advanceOffset(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int arrayStride,int matrixStride)316 void Std140BlockEncoder::advanceOffset(GLenum type,
317 const std::vector<unsigned int> &arraySizes,
318 bool isRowMajorMatrix,
319 int arrayStride,
320 int matrixStride)
321 {
322 if (!arraySizes.empty())
323 {
324 mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes);
325 }
326 else if (gl::IsMatrixType(type))
327 {
328 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
329 mCurrentOffset += matrixStride * numRegisters;
330 }
331 else
332 {
333 mCurrentOffset += gl::VariableComponentCount(type);
334 }
335 }
336
getBaseAlignment(const ShaderVariable & variable) const337 size_t Std140BlockEncoder::getBaseAlignment(const ShaderVariable &variable) const
338 {
339 return kComponentsPerRegister;
340 }
341
getTypeBaseAlignment(GLenum type,bool isRowMajorMatrix) const342 size_t Std140BlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const
343 {
344 return kComponentsPerRegister;
345 }
346
347 // Std430BlockEncoder implementation.
Std430BlockEncoder()348 Std430BlockEncoder::Std430BlockEncoder() {}
349
getBaseAlignment(const ShaderVariable & shaderVar) const350 size_t Std430BlockEncoder::getBaseAlignment(const ShaderVariable &shaderVar) const
351 {
352 if (shaderVar.isStruct())
353 {
354 BaseAlignmentVisitor visitor;
355 TraverseShaderVariables(shaderVar.fields, false, &visitor);
356 return visitor.getBaseAlignment();
357 }
358
359 return GetStd430BaseAlignment(shaderVar.type, shaderVar.isRowMajorLayout);
360 }
361
getTypeBaseAlignment(GLenum type,bool isRowMajorMatrix) const362 size_t Std430BlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const
363 {
364 return GetStd430BaseAlignment(type, isRowMajorMatrix);
365 }
366
GetInterfaceBlockInfo(const std::vector<ShaderVariable> & fields,const std::string & prefix,BlockLayoutEncoder * encoder,BlockLayoutMap * blockInfoOut)367 void GetInterfaceBlockInfo(const std::vector<ShaderVariable> &fields,
368 const std::string &prefix,
369 BlockLayoutEncoder *encoder,
370 BlockLayoutMap *blockInfoOut)
371 {
372 // Matrix packing is always recorded in individual fields, so they'll set the row major layout
373 // flag to true if needed.
374 // Iterates over all variables.
375 GetInterfaceBlockInfo(fields, prefix, encoder, false, false, blockInfoOut);
376 }
377
GetActiveUniformBlockInfo(const std::vector<ShaderVariable> & uniforms,const std::string & prefix,BlockLayoutEncoder * encoder,BlockLayoutMap * blockInfoOut)378 void GetActiveUniformBlockInfo(const std::vector<ShaderVariable> &uniforms,
379 const std::string &prefix,
380 BlockLayoutEncoder *encoder,
381 BlockLayoutMap *blockInfoOut)
382 {
383 // Matrix packing is always recorded in individual fields, so they'll set the row major layout
384 // flag to true if needed.
385 // Iterates only over the active variables.
386 GetInterfaceBlockInfo(uniforms, prefix, encoder, false, true, blockInfoOut);
387 }
388
389 // VariableNameVisitor implementation.
VariableNameVisitor(const std::string & namePrefix,const std::string & mappedNamePrefix)390 VariableNameVisitor::VariableNameVisitor(const std::string &namePrefix,
391 const std::string &mappedNamePrefix)
392 {
393 if (!namePrefix.empty())
394 {
395 mNameStack.push_back(namePrefix + ".");
396 }
397
398 if (!mappedNamePrefix.empty())
399 {
400 mMappedNameStack.push_back(mappedNamePrefix + ".");
401 }
402 }
403
404 VariableNameVisitor::~VariableNameVisitor() = default;
405
enterStruct(const ShaderVariable & structVar)406 void VariableNameVisitor::enterStruct(const ShaderVariable &structVar)
407 {
408 mNameStack.push_back(structVar.name);
409 mMappedNameStack.push_back(structVar.mappedName);
410 }
411
exitStruct(const ShaderVariable & structVar)412 void VariableNameVisitor::exitStruct(const ShaderVariable &structVar)
413 {
414 mNameStack.pop_back();
415 mMappedNameStack.pop_back();
416 }
417
enterStructAccess(const ShaderVariable & structVar,bool isRowMajor)418 void VariableNameVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor)
419 {
420 mNameStack.push_back(".");
421 mMappedNameStack.push_back(".");
422 }
423
exitStructAccess(const ShaderVariable & structVar,bool isRowMajor)424 void VariableNameVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor)
425 {
426 mNameStack.pop_back();
427 mMappedNameStack.pop_back();
428 }
429
enterArray(const ShaderVariable & arrayVar)430 void VariableNameVisitor::enterArray(const ShaderVariable &arrayVar)
431 {
432 if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct())
433 {
434 mNameStack.push_back(arrayVar.name);
435 mMappedNameStack.push_back(arrayVar.mappedName);
436 }
437 mArraySizeStack.push_back(arrayVar.getOutermostArraySize());
438 }
439
exitArray(const ShaderVariable & arrayVar)440 void VariableNameVisitor::exitArray(const ShaderVariable &arrayVar)
441 {
442 if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct())
443 {
444 mNameStack.pop_back();
445 mMappedNameStack.pop_back();
446 }
447 mArraySizeStack.pop_back();
448 }
449
enterArrayElement(const ShaderVariable & arrayVar,unsigned int arrayElement)450 void VariableNameVisitor::enterArrayElement(const ShaderVariable &arrayVar,
451 unsigned int arrayElement)
452 {
453 std::stringstream strstr = sh::InitializeStream<std::stringstream>();
454 strstr << "[" << arrayElement << "]";
455 std::string elementString = strstr.str();
456 mNameStack.push_back(elementString);
457 mMappedNameStack.push_back(elementString);
458 }
459
exitArrayElement(const ShaderVariable & arrayVar,unsigned int arrayElement)460 void VariableNameVisitor::exitArrayElement(const ShaderVariable &arrayVar,
461 unsigned int arrayElement)
462 {
463 mNameStack.pop_back();
464 mMappedNameStack.pop_back();
465 }
466
collapseNameStack() const467 std::string VariableNameVisitor::collapseNameStack() const
468 {
469 return CollapseNameStack(mNameStack);
470 }
471
collapseMappedNameStack() const472 std::string VariableNameVisitor::collapseMappedNameStack() const
473 {
474 return CollapseNameStack(mMappedNameStack);
475 }
476
visitOpaqueObject(const sh::ShaderVariable & variable)477 void VariableNameVisitor::visitOpaqueObject(const sh::ShaderVariable &variable)
478 {
479 if (!variable.hasParentArrayIndex())
480 {
481 mNameStack.push_back(variable.name);
482 mMappedNameStack.push_back(variable.mappedName);
483 }
484
485 std::string name = collapseNameStack();
486 std::string mappedName = collapseMappedNameStack();
487
488 if (!variable.hasParentArrayIndex())
489 {
490 mNameStack.pop_back();
491 mMappedNameStack.pop_back();
492 }
493
494 visitNamedOpaqueObject(variable, name, mappedName, mArraySizeStack);
495 }
496
visitVariable(const ShaderVariable & variable,bool isRowMajor)497 void VariableNameVisitor::visitVariable(const ShaderVariable &variable, bool isRowMajor)
498 {
499 if (!variable.hasParentArrayIndex())
500 {
501 mNameStack.push_back(variable.name);
502 mMappedNameStack.push_back(variable.mappedName);
503 }
504
505 std::string name = collapseNameStack();
506 std::string mappedName = collapseMappedNameStack();
507
508 if (!variable.hasParentArrayIndex())
509 {
510 mNameStack.pop_back();
511 mMappedNameStack.pop_back();
512 }
513
514 visitNamedVariable(variable, isRowMajor, name, mappedName, mArraySizeStack);
515 }
516
517 // BlockEncoderVisitor implementation.
BlockEncoderVisitor(const std::string & namePrefix,const std::string & mappedNamePrefix,BlockLayoutEncoder * encoder)518 BlockEncoderVisitor::BlockEncoderVisitor(const std::string &namePrefix,
519 const std::string &mappedNamePrefix,
520 BlockLayoutEncoder *encoder)
521 : VariableNameVisitor(namePrefix, mappedNamePrefix), mEncoder(encoder)
522 {}
523
524 BlockEncoderVisitor::~BlockEncoderVisitor() = default;
525
enterStructAccess(const ShaderVariable & structVar,bool isRowMajor)526 void BlockEncoderVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor)
527 {
528 mStructStackSize++;
529 if (!mIsTopLevelArrayStrideReady)
530 {
531 size_t structSize = mEncoder->getShaderVariableSize(structVar, isRowMajor);
532 mTopLevelArrayStride *= structSize;
533 mIsTopLevelArrayStrideReady = true;
534 }
535
536 VariableNameVisitor::enterStructAccess(structVar, isRowMajor);
537 mEncoder->enterAggregateType(structVar);
538 }
539
exitStructAccess(const ShaderVariable & structVar,bool isRowMajor)540 void BlockEncoderVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor)
541 {
542 mStructStackSize--;
543 mEncoder->exitAggregateType(structVar);
544 VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
545 }
546
enterArrayElement(const sh::ShaderVariable & arrayVar,unsigned int arrayElement)547 void BlockEncoderVisitor::enterArrayElement(const sh::ShaderVariable &arrayVar,
548 unsigned int arrayElement)
549 {
550 if (mStructStackSize == 0 && !arrayVar.hasParentArrayIndex())
551 {
552 // From the ES 3.1 spec "7.3.1.1 Naming Active Resources":
553 // For an active shader storage block member declared as an array of an aggregate type,
554 // an entry will be generated only for the first array element, regardless of its type.
555 // Such block members are referred to as top-level arrays. If the block member is an
556 // aggregate type, the enumeration rules are then applied recursively.
557 if (arrayElement == 0)
558 {
559 mTopLevelArraySize = arrayVar.getOutermostArraySize();
560 mTopLevelArrayStride = arrayVar.getInnerArraySizeProduct();
561 mIsTopLevelArrayStrideReady = false;
562 }
563 else
564 {
565 mSkipEnabled = true;
566 }
567 }
568 VariableNameVisitor::enterArrayElement(arrayVar, arrayElement);
569 }
570
exitArrayElement(const sh::ShaderVariable & arrayVar,unsigned int arrayElement)571 void BlockEncoderVisitor::exitArrayElement(const sh::ShaderVariable &arrayVar,
572 unsigned int arrayElement)
573 {
574 if (mStructStackSize == 0 && !arrayVar.hasParentArrayIndex())
575 {
576 mTopLevelArraySize = 1;
577 mTopLevelArrayStride = 0;
578 mIsTopLevelArrayStrideReady = true;
579 mSkipEnabled = false;
580 }
581 VariableNameVisitor::exitArrayElement(arrayVar, arrayElement);
582 }
583
visitNamedVariable(const ShaderVariable & variable,bool isRowMajor,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)584 void BlockEncoderVisitor::visitNamedVariable(const ShaderVariable &variable,
585 bool isRowMajor,
586 const std::string &name,
587 const std::string &mappedName,
588 const std::vector<unsigned int> &arraySizes)
589 {
590 std::vector<unsigned int> innermostArraySize;
591
592 if (variable.isArray())
593 {
594 innermostArraySize.push_back(variable.getNestedArraySize(0));
595 }
596 BlockMemberInfo variableInfo =
597 mEncoder->encodeType(variable.type, innermostArraySize, isRowMajor);
598 if (!mIsTopLevelArrayStrideReady)
599 {
600 ASSERT(mTopLevelArrayStride);
601 mTopLevelArrayStride *= variableInfo.arrayStride;
602 mIsTopLevelArrayStrideReady = true;
603 }
604 variableInfo.topLevelArrayStride = mTopLevelArrayStride;
605 encodeVariable(variable, variableInfo, name, mappedName);
606 }
607
TraverseShaderVariable(const ShaderVariable & variable,bool isRowMajorLayout,ShaderVariableVisitor * visitor)608 void TraverseShaderVariable(const ShaderVariable &variable,
609 bool isRowMajorLayout,
610 ShaderVariableVisitor *visitor)
611 {
612 bool rowMajorLayout = (isRowMajorLayout || variable.isRowMajorLayout);
613 bool isRowMajor = rowMajorLayout && gl::IsMatrixType(variable.type);
614
615 if (variable.isStruct())
616 {
617 visitor->enterStruct(variable);
618 if (variable.isArray())
619 {
620 TraverseStructArrayVariable(variable, rowMajorLayout, visitor);
621 }
622 else
623 {
624 TraverseStructVariable(variable, rowMajorLayout, visitor);
625 }
626 visitor->exitStruct(variable);
627 }
628 else if (variable.isArrayOfArrays())
629 {
630 TraverseArrayOfArraysVariable(variable, 0u, isRowMajor, visitor);
631 }
632 else if (gl::IsSamplerType(variable.type) || gl::IsImageType(variable.type) ||
633 variable.isFragmentInOut)
634 {
635 visitor->visitOpaqueObject(variable);
636 }
637 else
638 {
639 visitor->visitVariable(variable, isRowMajor);
640 }
641 }
642 } // namespace sh
643