Line data Source code
1 : //
2 : // Copyright (c) 2002-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 :
7 : #include "angle_gl.h"
8 : #include "compiler/translator/SymbolTable.h"
9 : #include "compiler/translator/VariableInfo.h"
10 : #include "compiler/translator/util.h"
11 : #include "common/utilities.h"
12 :
13 : namespace sh
14 : {
15 :
16 : namespace
17 : {
18 :
19 0 : BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
20 : {
21 0 : switch (blockStorage)
22 : {
23 0 : case EbsPacked: return BLOCKLAYOUT_PACKED;
24 0 : case EbsShared: return BLOCKLAYOUT_SHARED;
25 0 : case EbsStd140: return BLOCKLAYOUT_STANDARD;
26 0 : default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
27 : }
28 : }
29 :
30 0 : void ExpandUserDefinedVariable(const ShaderVariable &variable,
31 : const std::string &name,
32 : const std::string &mappedName,
33 : bool markStaticUse,
34 : std::vector<ShaderVariable> *expanded)
35 : {
36 0 : ASSERT(variable.isStruct());
37 :
38 0 : const std::vector<ShaderVariable> &fields = variable.fields;
39 :
40 0 : for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
41 : {
42 0 : const ShaderVariable &field = fields[fieldIndex];
43 0 : ExpandVariable(field,
44 0 : name + "." + field.name,
45 0 : mappedName + "." + field.mappedName,
46 : markStaticUse,
47 0 : expanded);
48 : }
49 0 : }
50 :
51 : template <class VarT>
52 0 : VarT *FindVariable(const TString &name,
53 : std::vector<VarT> *infoList)
54 : {
55 : // TODO(zmo): optimize this function.
56 0 : for (size_t ii = 0; ii < infoList->size(); ++ii)
57 : {
58 0 : if ((*infoList)[ii].name.c_str() == name)
59 0 : return &((*infoList)[ii]);
60 : }
61 :
62 0 : return NULL;
63 : }
64 :
65 : }
66 :
67 0 : CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
68 : std::vector<sh::OutputVariable> *outputVariables,
69 : std::vector<sh::Uniform> *uniforms,
70 : std::vector<sh::Varying> *varyings,
71 : std::vector<sh::InterfaceBlock> *interfaceBlocks,
72 : ShHashFunction64 hashFunction,
73 : const TSymbolTable &symbolTable,
74 0 : const TExtensionBehavior &extensionBehavior)
75 : : TIntermTraverser(true, false, false),
76 : mAttribs(attribs),
77 : mOutputVariables(outputVariables),
78 : mUniforms(uniforms),
79 : mVaryings(varyings),
80 : mInterfaceBlocks(interfaceBlocks),
81 : mDepthRangeAdded(false),
82 : mPointCoordAdded(false),
83 : mFrontFacingAdded(false),
84 : mFragCoordAdded(false),
85 : mInstanceIDAdded(false),
86 : mVertexIDAdded(false),
87 : mPositionAdded(false),
88 : mPointSizeAdded(false),
89 : mLastFragDataAdded(false),
90 : mFragColorAdded(false),
91 : mFragDataAdded(false),
92 : mFragDepthEXTAdded(false),
93 : mFragDepthAdded(false),
94 : mSecondaryFragColorEXTAdded(false),
95 : mSecondaryFragDataEXTAdded(false),
96 : mHashFunction(hashFunction),
97 : mSymbolTable(symbolTable),
98 0 : mExtensionBehavior(extensionBehavior)
99 : {
100 0 : }
101 :
102 : // We want to check whether a uniform/varying is statically used
103 : // because we only count the used ones in packing computing.
104 : // Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
105 : // toward varying counting if they are statically used in a fragment
106 : // shader.
107 0 : void CollectVariables::visitSymbol(TIntermSymbol *symbol)
108 : {
109 0 : ASSERT(symbol != NULL);
110 0 : ShaderVariable *var = NULL;
111 0 : const TString &symbolName = symbol->getSymbol();
112 :
113 0 : if (IsVarying(symbol->getQualifier()))
114 : {
115 0 : var = FindVariable(symbolName, mVaryings);
116 : }
117 0 : else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
118 : {
119 0 : UNREACHABLE();
120 : }
121 0 : else if (symbolName == "gl_DepthRange")
122 : {
123 0 : ASSERT(symbol->getQualifier() == EvqUniform);
124 :
125 0 : if (!mDepthRangeAdded)
126 : {
127 0 : Uniform info;
128 0 : const char kName[] = "gl_DepthRange";
129 0 : info.name = kName;
130 0 : info.mappedName = kName;
131 0 : info.type = GL_STRUCT_ANGLEX;
132 0 : info.arraySize = 0;
133 0 : info.precision = GL_NONE;
134 0 : info.staticUse = true;
135 :
136 0 : ShaderVariable nearInfo;
137 0 : const char kNearName[] = "near";
138 0 : nearInfo.name = kNearName;
139 0 : nearInfo.mappedName = kNearName;
140 0 : nearInfo.type = GL_FLOAT;
141 0 : nearInfo.arraySize = 0;
142 0 : nearInfo.precision = GL_HIGH_FLOAT;
143 0 : nearInfo.staticUse = true;
144 :
145 0 : ShaderVariable farInfo;
146 0 : const char kFarName[] = "far";
147 0 : farInfo.name = kFarName;
148 0 : farInfo.mappedName = kFarName;
149 0 : farInfo.type = GL_FLOAT;
150 0 : farInfo.arraySize = 0;
151 0 : farInfo.precision = GL_HIGH_FLOAT;
152 0 : farInfo.staticUse = true;
153 :
154 0 : ShaderVariable diffInfo;
155 0 : const char kDiffName[] = "diff";
156 0 : diffInfo.name = kDiffName;
157 0 : diffInfo.mappedName = kDiffName;
158 0 : diffInfo.type = GL_FLOAT;
159 0 : diffInfo.arraySize = 0;
160 0 : diffInfo.precision = GL_HIGH_FLOAT;
161 0 : diffInfo.staticUse = true;
162 :
163 0 : info.fields.push_back(nearInfo);
164 0 : info.fields.push_back(farInfo);
165 0 : info.fields.push_back(diffInfo);
166 :
167 0 : mUniforms->push_back(info);
168 0 : mDepthRangeAdded = true;
169 : }
170 : }
171 : else
172 : {
173 0 : switch (symbol->getQualifier())
174 : {
175 : case EvqAttribute:
176 : case EvqVertexIn:
177 0 : var = FindVariable(symbolName, mAttribs);
178 0 : break;
179 : case EvqFragmentOut:
180 0 : var = FindVariable(symbolName, mOutputVariables);
181 0 : break;
182 : case EvqUniform:
183 : {
184 0 : const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
185 0 : if (interfaceBlock)
186 : {
187 0 : InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
188 0 : ASSERT(namedBlock);
189 0 : var = FindVariable(symbolName, &namedBlock->fields);
190 :
191 : // Set static use on the parent interface block here
192 0 : namedBlock->staticUse = true;
193 : }
194 : else
195 : {
196 0 : var = FindVariable(symbolName, mUniforms);
197 : }
198 :
199 : // It's an internal error to reference an undefined user uniform
200 0 : ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
201 : }
202 0 : break;
203 : case EvqFragCoord:
204 0 : if (!mFragCoordAdded)
205 : {
206 0 : Varying info;
207 0 : const char kName[] = "gl_FragCoord";
208 0 : info.name = kName;
209 0 : info.mappedName = kName;
210 0 : info.type = GL_FLOAT_VEC4;
211 0 : info.arraySize = 0;
212 0 : info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
213 0 : info.staticUse = true;
214 0 : info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
215 0 : mVaryings->push_back(info);
216 0 : mFragCoordAdded = true;
217 : }
218 0 : return;
219 : case EvqFrontFacing:
220 0 : if (!mFrontFacingAdded)
221 : {
222 0 : Varying info;
223 0 : const char kName[] = "gl_FrontFacing";
224 0 : info.name = kName;
225 0 : info.mappedName = kName;
226 0 : info.type = GL_BOOL;
227 0 : info.arraySize = 0;
228 0 : info.precision = GL_NONE;
229 0 : info.staticUse = true;
230 0 : info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
231 0 : mVaryings->push_back(info);
232 0 : mFrontFacingAdded = true;
233 : }
234 0 : return;
235 : case EvqPointCoord:
236 0 : if (!mPointCoordAdded)
237 : {
238 0 : Varying info;
239 0 : const char kName[] = "gl_PointCoord";
240 0 : info.name = kName;
241 0 : info.mappedName = kName;
242 0 : info.type = GL_FLOAT_VEC2;
243 0 : info.arraySize = 0;
244 0 : info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
245 0 : info.staticUse = true;
246 0 : info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
247 0 : mVaryings->push_back(info);
248 0 : mPointCoordAdded = true;
249 : }
250 0 : return;
251 : case EvqInstanceID:
252 0 : if (!mInstanceIDAdded)
253 : {
254 0 : Attribute info;
255 0 : const char kName[] = "gl_InstanceID";
256 0 : info.name = kName;
257 0 : info.mappedName = kName;
258 0 : info.type = GL_INT;
259 0 : info.arraySize = 0;
260 0 : info.precision = GL_HIGH_INT; // Defined by spec.
261 0 : info.staticUse = true;
262 0 : info.location = -1;
263 0 : mAttribs->push_back(info);
264 0 : mInstanceIDAdded = true;
265 : }
266 0 : return;
267 : case EvqVertexID:
268 0 : if (!mVertexIDAdded)
269 : {
270 0 : Attribute info;
271 0 : const char kName[] = "gl_VertexID";
272 0 : info.name = kName;
273 0 : info.mappedName = kName;
274 0 : info.type = GL_INT;
275 0 : info.arraySize = 0;
276 0 : info.precision = GL_HIGH_INT; // Defined by spec.
277 0 : info.staticUse = true;
278 0 : info.location = -1;
279 0 : mAttribs->push_back(info);
280 0 : mVertexIDAdded = true;
281 : }
282 0 : return;
283 : case EvqPosition:
284 0 : if (!mPositionAdded)
285 : {
286 0 : Varying info;
287 0 : const char kName[] = "gl_Position";
288 0 : info.name = kName;
289 0 : info.mappedName = kName;
290 0 : info.type = GL_FLOAT_VEC4;
291 0 : info.arraySize = 0;
292 0 : info.precision = GL_HIGH_FLOAT; // Defined by spec.
293 0 : info.staticUse = true;
294 0 : info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
295 0 : mVaryings->push_back(info);
296 0 : mPositionAdded = true;
297 : }
298 0 : return;
299 : case EvqPointSize:
300 0 : if (!mPointSizeAdded)
301 : {
302 0 : Varying info;
303 0 : const char kName[] = "gl_PointSize";
304 0 : info.name = kName;
305 0 : info.mappedName = kName;
306 0 : info.type = GL_FLOAT;
307 0 : info.arraySize = 0;
308 0 : info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
309 0 : info.staticUse = true;
310 0 : info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
311 0 : mVaryings->push_back(info);
312 0 : mPointSizeAdded = true;
313 : }
314 0 : return;
315 : case EvqLastFragData:
316 0 : if (!mLastFragDataAdded)
317 : {
318 0 : Varying info;
319 0 : const char kName[] = "gl_LastFragData";
320 0 : info.name = kName;
321 0 : info.mappedName = kName;
322 0 : info.type = GL_FLOAT_VEC4;
323 0 : info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
324 0 : info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
325 0 : info.staticUse = true;
326 0 : info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
327 0 : mVaryings->push_back(info);
328 0 : mLastFragDataAdded = true;
329 : }
330 0 : return;
331 : case EvqFragColor:
332 0 : if (!mFragColorAdded)
333 : {
334 0 : OutputVariable info;
335 0 : const char kName[] = "gl_FragColor";
336 0 : info.name = kName;
337 0 : info.mappedName = kName;
338 0 : info.type = GL_FLOAT_VEC4;
339 0 : info.arraySize = 0;
340 0 : info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
341 0 : info.staticUse = true;
342 0 : mOutputVariables->push_back(info);
343 0 : mFragColorAdded = true;
344 : }
345 0 : return;
346 : case EvqFragData:
347 0 : if (!mFragDataAdded)
348 : {
349 0 : OutputVariable info;
350 0 : const char kName[] = "gl_FragData";
351 0 : info.name = kName;
352 0 : info.mappedName = kName;
353 0 : info.type = GL_FLOAT_VEC4;
354 0 : if (::IsExtensionEnabled(mExtensionBehavior, "GL_EXT_draw_buffers"))
355 : {
356 0 : info.arraySize = static_cast<const TVariable *>(
357 0 : mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
358 : ->getConstPointer()
359 0 : ->getIConst();
360 : }
361 : else
362 : {
363 0 : info.arraySize = 1;
364 : }
365 0 : info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
366 0 : info.staticUse = true;
367 0 : mOutputVariables->push_back(info);
368 0 : mFragDataAdded = true;
369 : }
370 0 : return;
371 : case EvqFragDepthEXT:
372 0 : if (!mFragDepthEXTAdded)
373 : {
374 0 : OutputVariable info;
375 0 : const char kName[] = "gl_FragDepthEXT";
376 0 : info.name = kName;
377 0 : info.mappedName = kName;
378 0 : info.type = GL_FLOAT;
379 0 : info.arraySize = 0;
380 0 : info.precision =
381 0 : GLVariablePrecision(static_cast<const TVariable *>(
382 0 : mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
383 : ->getType());
384 0 : info.staticUse = true;
385 0 : mOutputVariables->push_back(info);
386 0 : mFragDepthEXTAdded = true;
387 : }
388 0 : return;
389 : case EvqFragDepth:
390 0 : if (!mFragDepthAdded)
391 : {
392 0 : OutputVariable info;
393 0 : const char kName[] = "gl_FragDepth";
394 0 : info.name = kName;
395 0 : info.mappedName = kName;
396 0 : info.type = GL_FLOAT;
397 0 : info.arraySize = 0;
398 0 : info.precision = GL_HIGH_FLOAT;
399 0 : info.staticUse = true;
400 0 : mOutputVariables->push_back(info);
401 0 : mFragDepthAdded = true;
402 : }
403 0 : return;
404 : case EvqSecondaryFragColorEXT:
405 0 : if (!mSecondaryFragColorEXTAdded)
406 : {
407 0 : OutputVariable info;
408 0 : const char kName[] = "gl_SecondaryFragColorEXT";
409 0 : info.name = kName;
410 0 : info.mappedName = kName;
411 0 : info.type = GL_FLOAT_VEC4;
412 0 : info.arraySize = 0;
413 0 : info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
414 0 : info.staticUse = true;
415 0 : mOutputVariables->push_back(info);
416 0 : mSecondaryFragColorEXTAdded = true;
417 : }
418 0 : return;
419 : case EvqSecondaryFragDataEXT:
420 0 : if (!mSecondaryFragDataEXTAdded)
421 : {
422 0 : OutputVariable info;
423 0 : const char kName[] = "gl_SecondaryFragDataEXT";
424 0 : info.name = kName;
425 0 : info.mappedName = kName;
426 0 : info.type = GL_FLOAT_VEC4;
427 :
428 : const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
429 0 : mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
430 0 : info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
431 0 : info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
432 0 : info.staticUse = true;
433 0 : mOutputVariables->push_back(info);
434 0 : mSecondaryFragDataEXTAdded = true;
435 : }
436 0 : return;
437 : default:
438 0 : break;
439 : }
440 : }
441 0 : if (var)
442 : {
443 0 : var->staticUse = true;
444 : }
445 : }
446 :
447 0 : class NameHashingTraverser : public GetVariableTraverser
448 : {
449 : public:
450 0 : NameHashingTraverser(ShHashFunction64 hashFunction,
451 : const TSymbolTable &symbolTable)
452 0 : : GetVariableTraverser(symbolTable),
453 0 : mHashFunction(hashFunction)
454 0 : {}
455 :
456 : private:
457 0 : void visitVariable(ShaderVariable *variable) override
458 : {
459 0 : TString stringName = TString(variable->name.c_str());
460 0 : variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
461 0 : }
462 :
463 : ShHashFunction64 mHashFunction;
464 : };
465 :
466 : // Attributes, which cannot have struct fields, are a special case
467 : template <>
468 0 : void CollectVariables::visitVariable(const TIntermSymbol *variable,
469 : std::vector<Attribute> *infoList) const
470 : {
471 0 : ASSERT(variable);
472 0 : const TType &type = variable->getType();
473 0 : ASSERT(!type.getStruct());
474 :
475 0 : Attribute attribute;
476 :
477 0 : attribute.type = GLVariableType(type);
478 0 : attribute.precision = GLVariablePrecision(type);
479 0 : attribute.name = variable->getSymbol().c_str();
480 0 : attribute.arraySize = type.getArraySize();
481 0 : attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
482 0 : attribute.location = variable->getType().getLayoutQualifier().location;
483 :
484 0 : infoList->push_back(attribute);
485 0 : }
486 :
487 : template <>
488 0 : void CollectVariables::visitVariable(const TIntermSymbol *variable,
489 : std::vector<OutputVariable> *infoList) const
490 : {
491 0 : ASSERT(variable);
492 0 : const TType &type = variable->getType();
493 0 : ASSERT(!type.getStruct());
494 :
495 0 : OutputVariable attribute;
496 :
497 0 : attribute.type = GLVariableType(type);
498 0 : attribute.precision = GLVariablePrecision(type);
499 0 : attribute.name = variable->getSymbol().c_str();
500 0 : attribute.arraySize = type.getArraySize();
501 0 : attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
502 0 : attribute.location = variable->getType().getLayoutQualifier().location;
503 :
504 0 : infoList->push_back(attribute);
505 0 : }
506 :
507 : template <>
508 0 : void CollectVariables::visitVariable(const TIntermSymbol *variable,
509 : std::vector<InterfaceBlock> *infoList) const
510 : {
511 0 : InterfaceBlock interfaceBlock;
512 0 : const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
513 0 : ASSERT(blockType);
514 :
515 0 : interfaceBlock.name = blockType->name().c_str();
516 : interfaceBlock.mappedName =
517 0 : TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
518 0 : interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
519 0 : interfaceBlock.arraySize = variable->getArraySize();
520 0 : interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
521 0 : interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
522 :
523 : // Gather field information
524 0 : for (const TField *field : blockType->fields())
525 : {
526 0 : const TType &fieldType = *field->type();
527 :
528 0 : NameHashingTraverser traverser(mHashFunction, mSymbolTable);
529 0 : traverser.traverse(fieldType, field->name(), &interfaceBlock.fields);
530 :
531 0 : interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
532 : }
533 :
534 0 : infoList->push_back(interfaceBlock);
535 0 : }
536 :
537 : template <typename VarT>
538 0 : void CollectVariables::visitVariable(const TIntermSymbol *variable,
539 : std::vector<VarT> *infoList) const
540 : {
541 0 : NameHashingTraverser traverser(mHashFunction, mSymbolTable);
542 0 : traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
543 0 : }
544 :
545 : template <typename VarT>
546 0 : void CollectVariables::visitInfoList(const TIntermSequence &sequence,
547 : std::vector<VarT> *infoList) const
548 : {
549 0 : for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
550 : {
551 0 : const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
552 : // The only case in which the sequence will not contain a
553 : // TIntermSymbol node is initialization. It will contain a
554 : // TInterBinary node in that case. Since attributes, uniforms,
555 : // and varyings cannot be initialized in a shader, we must have
556 : // only TIntermSymbol nodes in the sequence.
557 0 : ASSERT(variable != NULL);
558 0 : visitVariable(variable, infoList);
559 : }
560 0 : }
561 :
562 0 : bool CollectVariables::visitDeclaration(Visit, TIntermDeclaration *node)
563 : {
564 0 : const TIntermSequence &sequence = *(node->getSequence());
565 0 : ASSERT(!sequence.empty());
566 :
567 0 : const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
568 0 : TQualifier qualifier = typedNode.getQualifier();
569 :
570 0 : if (typedNode.getBasicType() == EbtInterfaceBlock)
571 : {
572 0 : visitInfoList(sequence, mInterfaceBlocks);
573 0 : return false;
574 : }
575 0 : else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqFragmentOut ||
576 0 : qualifier == EvqUniform || IsVarying(qualifier))
577 : {
578 0 : switch (qualifier)
579 : {
580 : case EvqAttribute:
581 : case EvqVertexIn:
582 0 : visitInfoList(sequence, mAttribs);
583 0 : break;
584 : case EvqFragmentOut:
585 0 : visitInfoList(sequence, mOutputVariables);
586 0 : break;
587 : case EvqUniform:
588 0 : visitInfoList(sequence, mUniforms);
589 0 : break;
590 : default:
591 0 : visitInfoList(sequence, mVaryings);
592 0 : break;
593 : }
594 :
595 0 : return false;
596 : }
597 :
598 0 : return true;
599 : }
600 :
601 0 : bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
602 : {
603 0 : if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
604 : {
605 : // NOTE: we do not determine static use for individual blocks of an array
606 0 : TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
607 0 : ASSERT(blockNode);
608 :
609 0 : TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
610 0 : ASSERT(constantUnion);
611 :
612 0 : const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
613 0 : InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
614 0 : ASSERT(namedBlock);
615 0 : namedBlock->staticUse = true;
616 :
617 0 : unsigned int fieldIndex = constantUnion->getUConst(0);
618 0 : ASSERT(fieldIndex < namedBlock->fields.size());
619 0 : namedBlock->fields[fieldIndex].staticUse = true;
620 0 : return false;
621 : }
622 :
623 0 : return true;
624 : }
625 :
626 0 : void ExpandVariable(const ShaderVariable &variable,
627 : const std::string &name,
628 : const std::string &mappedName,
629 : bool markStaticUse,
630 : std::vector<ShaderVariable> *expanded)
631 : {
632 0 : if (variable.isStruct())
633 : {
634 0 : if (variable.isArray())
635 : {
636 0 : for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
637 : elementIndex++)
638 : {
639 0 : std::string lname = name + ::ArrayString(elementIndex);
640 0 : std::string lmappedName = mappedName + ::ArrayString(elementIndex);
641 0 : ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
642 : }
643 : }
644 : else
645 : {
646 0 : ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
647 : }
648 : }
649 : else
650 : {
651 0 : ShaderVariable expandedVar = variable;
652 :
653 0 : expandedVar.name = name;
654 0 : expandedVar.mappedName = mappedName;
655 :
656 : // Mark all expanded fields as used if the parent is used
657 0 : if (markStaticUse)
658 : {
659 0 : expandedVar.staticUse = true;
660 : }
661 :
662 0 : if (expandedVar.isArray())
663 : {
664 0 : expandedVar.name += "[0]";
665 0 : expandedVar.mappedName += "[0]";
666 : }
667 :
668 0 : expanded->push_back(expandedVar);
669 : }
670 0 : }
671 :
672 0 : void ExpandUniforms(const std::vector<Uniform> &compact,
673 : std::vector<ShaderVariable> *expanded)
674 : {
675 0 : for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
676 : {
677 0 : const ShaderVariable &variable = compact[variableIndex];
678 0 : ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
679 : }
680 0 : }
681 :
682 : }
|