2 // Copyright (c) 2002-2010 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.
7 #include "compiler/translator/VariableInfo.h"
11 TString arrayBrackets(int index)
14 stream << "[" << index << "]";
18 // Returns the data type for an attribute, uniform, or varying.
19 ShDataType getVariableDataType(const TType& type)
21 switch (type.getBasicType()) {
23 if (type.isMatrix()) {
24 switch (type.getNominalSize()) {
25 case 2: return SH_FLOAT_MAT2;
26 case 3: return SH_FLOAT_MAT3;
27 case 4: return SH_FLOAT_MAT4;
28 default: UNREACHABLE();
30 } else if (type.isVector()) {
31 switch (type.getNominalSize()) {
32 case 2: return SH_FLOAT_VEC2;
33 case 3: return SH_FLOAT_VEC3;
34 case 4: return SH_FLOAT_VEC4;
35 default: UNREACHABLE();
41 if (type.isMatrix()) {
43 } else if (type.isVector()) {
44 switch (type.getNominalSize()) {
45 case 2: return SH_INT_VEC2;
46 case 3: return SH_INT_VEC3;
47 case 4: return SH_INT_VEC4;
48 default: UNREACHABLE();
54 if (type.isMatrix()) {
56 } else if (type.isVector()) {
57 switch (type.getNominalSize()) {
58 case 2: return SH_BOOL_VEC2;
59 case 3: return SH_BOOL_VEC3;
60 case 4: return SH_BOOL_VEC4;
61 default: UNREACHABLE();
66 case EbtSampler2D: return SH_SAMPLER_2D;
67 case EbtSamplerCube: return SH_SAMPLER_CUBE;
68 case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES;
69 case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB;
70 default: UNREACHABLE();
75 void getBuiltInVariableInfo(const TType& type,
77 const TString& mappedName,
78 TVariableInfoList& infoList);
79 void getUserDefinedVariableInfo(const TType& type,
81 const TString& mappedName,
82 TVariableInfoList& infoList,
83 ShHashFunction64 hashFunction);
85 // Returns info for an attribute, uniform, or varying.
86 void getVariableInfo(const TType& type,
88 const TString& mappedName,
89 TVariableInfoList& infoList,
90 ShHashFunction64 hashFunction)
92 if (type.getBasicType() == EbtStruct) {
94 for (int i = 0; i < type.getArraySize(); ++i) {
95 TString lname = name + arrayBrackets(i);
96 TString lmappedName = mappedName + arrayBrackets(i);
97 getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
100 getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
103 getBuiltInVariableInfo(type, name, mappedName, infoList);
107 void getBuiltInVariableInfo(const TType& type,
109 const TString& mappedName,
110 TVariableInfoList& infoList)
112 ASSERT(type.getBasicType() != EbtStruct);
114 TVariableInfo varInfo;
115 if (type.isArray()) {
116 varInfo.name = (name + "[0]").c_str();
117 varInfo.mappedName = (mappedName + "[0]").c_str();
118 varInfo.size = type.getArraySize();
119 varInfo.isArray = true;
121 varInfo.name = name.c_str();
122 varInfo.mappedName = mappedName.c_str();
124 varInfo.isArray = false;
126 varInfo.precision = type.getPrecision();
127 varInfo.type = getVariableDataType(type);
128 infoList.push_back(varInfo);
131 void getUserDefinedVariableInfo(const TType& type,
133 const TString& mappedName,
134 TVariableInfoList& infoList,
135 ShHashFunction64 hashFunction)
137 ASSERT(type.getBasicType() == EbtStruct);
139 const TFieldList& fields = type.getStruct()->fields();
140 for (size_t i = 0; i < fields.size(); ++i) {
141 const TType& fieldType = *(fields[i]->type());
142 const TString& fieldName = fields[i]->name();
143 getVariableInfo(fieldType,
144 name + "." + fieldName,
145 mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
151 TVariableInfo* findVariable(const TType& type,
153 TVariableInfoList& infoList)
155 // TODO(zmo): optimize this function.
156 TString myName = name;
159 for (size_t ii = 0; ii < infoList.size(); ++ii)
161 if (infoList[ii].name.c_str() == myName)
162 return &(infoList[ii]);
167 } // namespace anonymous
169 TVariableInfo::TVariableInfo()
173 precision(EbpUndefined),
178 TVariableInfo::TVariableInfo(ShDataType type, int size)
182 precision(EbpUndefined),
187 CollectVariables::CollectVariables(TVariableInfoList& attribs,
188 TVariableInfoList& uniforms,
189 TVariableInfoList& varyings,
190 ShHashFunction64 hashFunction)
194 mPointCoordAdded(false),
195 mFrontFacingAdded(false),
196 mFragCoordAdded(false),
197 mHashFunction(hashFunction)
201 // We want to check whether a uniform/varying is statically used
202 // because we only count the used ones in packing computing.
203 // Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
204 // toward varying counting if they are statically used in a fragment
206 void CollectVariables::visitSymbol(TIntermSymbol* symbol)
208 ASSERT(symbol != NULL);
209 TVariableInfo* var = NULL;
210 switch (symbol->getQualifier())
213 case EvqInvariantVaryingOut:
215 case EvqInvariantVaryingIn:
216 var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
219 var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
222 if (!mFragCoordAdded) {
224 info.name = "gl_FragCoord";
225 info.mappedName = "gl_FragCoord";
226 info.type = SH_FLOAT_VEC4;
228 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
229 info.staticUse = true;
230 mVaryings.push_back(info);
231 mFragCoordAdded = true;
235 if (!mFrontFacingAdded) {
237 info.name = "gl_FrontFacing";
238 info.mappedName = "gl_FrontFacing";
241 info.precision = EbpUndefined;
242 info.staticUse = true;
243 mVaryings.push_back(info);
244 mFrontFacingAdded = true;
248 if (!mPointCoordAdded) {
250 info.name = "gl_PointCoord";
251 info.mappedName = "gl_PointCoord";
252 info.type = SH_FLOAT_VEC2;
254 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
255 info.staticUse = true;
256 mVaryings.push_back(info);
257 mPointCoordAdded = true;
264 var->staticUse = true;
267 bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
269 bool visitChildren = true;
271 switch (node->getOp())
273 case EOpDeclaration: {
274 const TIntermSequence& sequence = node->getSequence();
275 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
276 if (qualifier == EvqAttribute || qualifier == EvqUniform ||
277 qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
278 qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
280 TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs :
281 (qualifier == EvqUniform ? mUniforms : mVaryings);
282 for (TIntermSequence::const_iterator i = sequence.begin();
283 i != sequence.end(); ++i)
285 const TIntermSymbol* variable = (*i)->getAsSymbolNode();
286 // The only case in which the sequence will not contain a
287 // TIntermSymbol node is initialization. It will contain a
288 // TInterBinary node in that case. Since attributes, uniforms,
289 // and varyings cannot be initialized in a shader, we must have
290 // only TIntermSymbol nodes in the sequence.
291 ASSERT(variable != NULL);
292 TString processedSymbol;
293 if (mHashFunction == NULL)
294 processedSymbol = variable->getSymbol();
296 processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
297 getVariableInfo(variable->getType(),
298 variable->getOriginalSymbol(),
302 visitChildren = false;
310 return visitChildren;