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