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();
120 varInfo.name = name.c_str();
121 varInfo.mappedName = mappedName.c_str();
124 varInfo.precision = type.getPrecision();
125 varInfo.type = getVariableDataType(type);
126 infoList.push_back(varInfo);
129 void getUserDefinedVariableInfo(const TType& type,
131 const TString& mappedName,
132 TVariableInfoList& infoList,
133 ShHashFunction64 hashFunction)
135 ASSERT(type.getBasicType() == EbtStruct);
137 const TFieldList& fields = type.getStruct()->fields();
138 for (size_t i = 0; i < fields.size(); ++i) {
139 const TType& fieldType = *(fields[i]->type());
140 const TString& fieldName = fields[i]->name();
141 getVariableInfo(fieldType,
142 name + "." + fieldName,
143 mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
149 TVariableInfo* findVariable(const TType& type,
151 TVariableInfoList& infoList)
153 // TODO(zmo): optimize this function.
154 TString myName = name;
157 for (size_t ii = 0; ii < infoList.size(); ++ii)
159 if (infoList[ii].name.c_str() == myName)
160 return &(infoList[ii]);
165 } // namespace anonymous
167 TVariableInfo::TVariableInfo()
170 precision(EbpUndefined),
175 TVariableInfo::TVariableInfo(ShDataType type, int size)
178 precision(EbpUndefined),
183 CollectVariables::CollectVariables(TVariableInfoList& attribs,
184 TVariableInfoList& uniforms,
185 TVariableInfoList& varyings,
186 ShHashFunction64 hashFunction)
190 mPointCoordAdded(false),
191 mFrontFacingAdded(false),
192 mFragCoordAdded(false),
193 mHashFunction(hashFunction)
197 // We want to check whether a uniform/varying is statically used
198 // because we only count the used ones in packing computing.
199 // Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
200 // toward varying counting if they are statically used in a fragment
202 void CollectVariables::visitSymbol(TIntermSymbol* symbol)
204 ASSERT(symbol != NULL);
205 TVariableInfo* var = NULL;
206 switch (symbol->getQualifier())
209 case EvqInvariantVaryingOut:
211 case EvqInvariantVaryingIn:
212 var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
215 var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
218 if (!mFragCoordAdded) {
220 info.name = "gl_FragCoord";
221 info.mappedName = "gl_FragCoord";
222 info.type = SH_FLOAT_VEC4;
224 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
225 info.staticUse = true;
226 mVaryings.push_back(info);
227 mFragCoordAdded = true;
231 if (!mFrontFacingAdded) {
233 info.name = "gl_FrontFacing";
234 info.mappedName = "gl_FrontFacing";
237 info.precision = EbpUndefined;
238 info.staticUse = true;
239 mVaryings.push_back(info);
240 mFrontFacingAdded = true;
244 if (!mPointCoordAdded) {
246 info.name = "gl_PointCoord";
247 info.mappedName = "gl_PointCoord";
248 info.type = SH_FLOAT_VEC2;
250 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
251 info.staticUse = true;
252 mVaryings.push_back(info);
253 mPointCoordAdded = true;
260 var->staticUse = true;
263 bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
265 bool visitChildren = true;
267 switch (node->getOp())
269 case EOpDeclaration: {
270 const TIntermSequence& sequence = node->getSequence();
271 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
272 if (qualifier == EvqAttribute || qualifier == EvqUniform ||
273 qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
274 qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
276 TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs :
277 (qualifier == EvqUniform ? mUniforms : mVaryings);
278 for (TIntermSequence::const_iterator i = sequence.begin();
279 i != sequence.end(); ++i)
281 const TIntermSymbol* variable = (*i)->getAsSymbolNode();
282 // The only case in which the sequence will not contain a
283 // TIntermSymbol node is initialization. It will contain a
284 // TInterBinary node in that case. Since attributes, uniforms,
285 // and varyings cannot be initialized in a shader, we must have
286 // only TIntermSymbol nodes in the sequence.
287 ASSERT(variable != NULL);
288 TString processedSymbol;
289 if (mHashFunction == NULL)
290 processedSymbol = variable->getSymbol();
292 processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
293 getVariableInfo(variable->getType(),
294 variable->getOriginalSymbol(),
298 visitChildren = false;
306 return visitChildren;