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.
8 #include "compiler/translator/VariableInfo.h"
9 #include "compiler/translator/util.h"
10 #include "common/utilities.h"
18 TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
20 if (interfaceBlock.hasInstanceName())
22 return interfaceBlock.name() + "." + field.name();
30 BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
34 case EbsPacked: return BLOCKLAYOUT_PACKED;
35 case EbsShared: return BLOCKLAYOUT_SHARED;
36 case EbsStd140: return BLOCKLAYOUT_STANDARD;
37 default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
41 void ExpandUserDefinedVariable(const ShaderVariable &variable,
42 const std::string &name,
43 const std::string &mappedName,
45 std::vector<ShaderVariable> *expanded);
47 void ExpandVariable(const ShaderVariable &variable,
48 const std::string &name,
49 const std::string &mappedName,
51 std::vector<ShaderVariable> *expanded)
53 if (variable.isStruct())
55 if (variable.isArray())
57 for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++)
59 std::string lname = name + ::ArrayString(elementIndex);
60 std::string lmappedName = mappedName + ::ArrayString(elementIndex);
61 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
66 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
71 ShaderVariable expandedVar = variable;
73 expandedVar.name = name;
74 expandedVar.mappedName = mappedName;
76 // Mark all expanded fields as used if the parent is used
79 expandedVar.staticUse = true;
82 if (expandedVar.isArray())
84 expandedVar.name += "[0]";
85 expandedVar.mappedName += "[0]";
88 expanded->push_back(expandedVar);
92 void ExpandUserDefinedVariable(const ShaderVariable &variable,
93 const std::string &name,
94 const std::string &mappedName,
96 std::vector<ShaderVariable> *expanded)
98 ASSERT(variable.isStruct());
100 const std::vector<ShaderVariable> &fields = variable.fields;
102 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
104 const ShaderVariable &field = fields[fieldIndex];
105 ExpandVariable(field,
106 name + "." + field.name,
107 mappedName + "." + field.mappedName,
113 template <class VarT>
114 VarT *FindVariable(const TString &name,
115 std::vector<VarT> *infoList)
117 // TODO(zmo): optimize this function.
118 for (size_t ii = 0; ii < infoList->size(); ++ii)
120 if ((*infoList)[ii].name.c_str() == name)
121 return &((*infoList)[ii]);
129 CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
130 std::vector<sh::Attribute> *outputVariables,
131 std::vector<sh::Uniform> *uniforms,
132 std::vector<sh::Varying> *varyings,
133 std::vector<sh::InterfaceBlock> *interfaceBlocks,
134 ShHashFunction64 hashFunction)
136 mOutputVariables(outputVariables),
139 mInterfaceBlocks(interfaceBlocks),
140 mPointCoordAdded(false),
141 mFrontFacingAdded(false),
142 mFragCoordAdded(false),
143 mHashFunction(hashFunction)
147 // We want to check whether a uniform/varying is statically used
148 // because we only count the used ones in packing computing.
149 // Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
150 // toward varying counting if they are statically used in a fragment
152 void CollectVariables::visitSymbol(TIntermSymbol *symbol)
154 ASSERT(symbol != NULL);
155 ShaderVariable *var = NULL;
156 const TString &symbolName = symbol->getSymbol();
158 if (IsVarying(symbol->getQualifier()))
160 var = FindVariable(symbolName, mVaryings);
162 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
168 switch (symbol->getQualifier())
172 var = FindVariable(symbolName, mAttribs);
175 var = FindVariable(symbolName, mOutputVariables);
179 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
182 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
184 var = FindVariable(symbolName, &namedBlock->fields);
186 // Set static use on the parent interface block here
187 namedBlock->staticUse = true;
192 var = FindVariable(symbolName, mUniforms);
195 // It's an internal error to reference an undefined user uniform
196 ASSERT(symbolName.compare(0, 3, "gl_") == 0 || var);
200 if (!mFragCoordAdded)
203 info.name = "gl_FragCoord";
204 info.mappedName = "gl_FragCoord";
205 info.type = GL_FLOAT_VEC4;
207 info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
208 info.staticUse = true;
209 mVaryings->push_back(info);
210 mFragCoordAdded = true;
214 if (!mFrontFacingAdded)
217 info.name = "gl_FrontFacing";
218 info.mappedName = "gl_FrontFacing";
221 info.precision = GL_NONE;
222 info.staticUse = true;
223 mVaryings->push_back(info);
224 mFrontFacingAdded = true;
228 if (!mPointCoordAdded)
231 info.name = "gl_PointCoord";
232 info.mappedName = "gl_PointCoord";
233 info.type = GL_FLOAT_VEC2;
235 info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
236 info.staticUse = true;
237 mVaryings->push_back(info);
238 mPointCoordAdded = true;
247 var->staticUse = true;
251 class NameHashingTraverser : public GetVariableTraverser
254 NameHashingTraverser(ShHashFunction64 hashFunction)
255 : mHashFunction(hashFunction)
259 DISALLOW_COPY_AND_ASSIGN(NameHashingTraverser);
261 virtual void visitVariable(ShaderVariable *variable)
263 TString stringName = TString(variable->name.c_str());
264 variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
267 ShHashFunction64 mHashFunction;
270 // Attributes, which cannot have struct fields, are a special case
272 void CollectVariables::visitVariable(const TIntermSymbol *variable,
273 std::vector<Attribute> *infoList) const
276 const TType &type = variable->getType();
277 ASSERT(!type.getStruct());
281 attribute.type = GLVariableType(type);
282 attribute.precision = GLVariablePrecision(type);
283 attribute.name = variable->getSymbol().c_str();
284 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
285 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
286 attribute.location = variable->getType().getLayoutQualifier().location;
288 infoList->push_back(attribute);
292 void CollectVariables::visitVariable(const TIntermSymbol *variable,
293 std::vector<InterfaceBlock> *infoList) const
295 InterfaceBlock interfaceBlock;
296 const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
299 interfaceBlock.name = blockType->name().c_str();
300 interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
301 interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
302 interfaceBlock.arraySize = variable->getArraySize();
303 interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
304 interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
306 // Gather field information
307 const TFieldList &fieldList = blockType->fields();
309 for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
311 const TField &field = *fieldList[fieldIndex];
312 const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
313 const TType &fieldType = *field.type();
315 GetVariableTraverser traverser;
316 traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
318 interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
321 infoList->push_back(interfaceBlock);
324 template <typename VarT>
325 void CollectVariables::visitVariable(const TIntermSymbol *variable,
326 std::vector<VarT> *infoList) const
328 NameHashingTraverser traverser(mHashFunction);
329 traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
332 template <typename VarT>
333 void CollectVariables::visitInfoList(const TIntermSequence &sequence,
334 std::vector<VarT> *infoList) const
336 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
338 const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
339 // The only case in which the sequence will not contain a
340 // TIntermSymbol node is initialization. It will contain a
341 // TInterBinary node in that case. Since attributes, uniforms,
342 // and varyings cannot be initialized in a shader, we must have
343 // only TIntermSymbol nodes in the sequence.
344 ASSERT(variable != NULL);
345 visitVariable(variable, infoList);
349 bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
351 bool visitChildren = true;
353 switch (node->getOp())
357 const TIntermSequence &sequence = *(node->getSequence());
358 ASSERT(!sequence.empty());
360 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
361 TQualifier qualifier = typedNode.getQualifier();
363 if (typedNode.getBasicType() == EbtInterfaceBlock)
365 visitInfoList(sequence, mInterfaceBlocks);
366 visitChildren = false;
368 else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
369 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
370 IsVarying(qualifier))
376 visitInfoList(sequence, mAttribs);
379 visitInfoList(sequence, mOutputVariables);
382 visitInfoList(sequence, mUniforms);
385 visitInfoList(sequence, mVaryings);
389 visitChildren = false;
396 return visitChildren;
399 bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
401 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
403 // NOTE: we do not determine static use for individual blocks of an array
404 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
407 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
408 ASSERT(constantUnion);
410 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
411 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
413 namedBlock->staticUse = true;
415 unsigned int fieldIndex = constantUnion->getUConst(0);
416 ASSERT(fieldIndex < namedBlock->fields.size());
417 namedBlock->fields[fieldIndex].staticUse = true;
424 template <typename VarT>
425 void ExpandVariables(const std::vector<VarT> &compact,
426 std::vector<ShaderVariable> *expanded)
428 for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
430 const ShaderVariable &variable = compact[variableIndex];
431 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
435 template void ExpandVariables(const std::vector<Uniform> &, std::vector<ShaderVariable> *);
436 template void ExpandVariables(const std::vector<Varying> &, std::vector<ShaderVariable> *);