• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
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.
5 //
6 
7 #include "compiler/VariableInfo.h"
8 
9 namespace {
10 
arrayBrackets(int index)11 TString arrayBrackets(int index)
12 {
13     TStringStream stream;
14     stream << "[" << index << "]";
15     return stream.str();
16 }
17 
18 // Returns the data type for an attribute, uniform, or varying.
getVariableDataType(const TType & type)19 ShDataType getVariableDataType(const TType& type)
20 {
21     switch (type.getBasicType()) {
22       case EbtFloat:
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();
29               }
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();
36               }
37           } else {
38               return SH_FLOAT;
39           }
40       case EbtInt:
41           if (type.isMatrix()) {
42               UNREACHABLE();
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();
49               }
50           } else {
51               return SH_INT;
52           }
53       case EbtBool:
54           if (type.isMatrix()) {
55               UNREACHABLE();
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();
62               }
63           } else {
64               return SH_BOOL;
65           }
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();
71     }
72     return SH_NONE;
73 }
74 
75 void getBuiltInVariableInfo(const TType& type,
76                             const TString& name,
77                             const TString& mappedName,
78                             TVariableInfoList& infoList);
79 void getUserDefinedVariableInfo(const TType& type,
80                                 const TString& name,
81                                 const TString& mappedName,
82                                 TVariableInfoList& infoList,
83                                 ShHashFunction64 hashFunction);
84 
85 // Returns info for an attribute, uniform, or varying.
getVariableInfo(const TType & type,const TString & name,const TString & mappedName,TVariableInfoList & infoList,ShHashFunction64 hashFunction)86 void getVariableInfo(const TType& type,
87                      const TString& name,
88                      const TString& mappedName,
89                      TVariableInfoList& infoList,
90                      ShHashFunction64 hashFunction)
91 {
92     if (type.getBasicType() == EbtStruct) {
93         if (type.isArray()) {
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);
98             }
99         } else {
100             getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
101         }
102     } else {
103         getBuiltInVariableInfo(type, name, mappedName, infoList);
104     }
105 }
106 
getBuiltInVariableInfo(const TType & type,const TString & name,const TString & mappedName,TVariableInfoList & infoList)107 void getBuiltInVariableInfo(const TType& type,
108                             const TString& name,
109                             const TString& mappedName,
110                             TVariableInfoList& infoList)
111 {
112     ASSERT(type.getBasicType() != EbtStruct);
113 
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     } else {
120         varInfo.name = name.c_str();
121         varInfo.mappedName = mappedName.c_str();
122         varInfo.size = 1;
123     }
124     varInfo.precision = type.getPrecision();
125     varInfo.type = getVariableDataType(type);
126     infoList.push_back(varInfo);
127 }
128 
getUserDefinedVariableInfo(const TType & type,const TString & name,const TString & mappedName,TVariableInfoList & infoList,ShHashFunction64 hashFunction)129 void getUserDefinedVariableInfo(const TType& type,
130                                 const TString& name,
131                                 const TString& mappedName,
132                                 TVariableInfoList& infoList,
133                                 ShHashFunction64 hashFunction)
134 {
135     ASSERT(type.getBasicType() == EbtStruct);
136 
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),
144                         infoList,
145                         hashFunction);
146     }
147 }
148 
findVariable(const TType & type,const TString & name,TVariableInfoList & infoList)149 TVariableInfo* findVariable(const TType& type,
150                             const TString& name,
151                             TVariableInfoList& infoList)
152 {
153     // TODO(zmo): optimize this function.
154     TString myName = name;
155     if (type.isArray())
156         myName += "[0]";
157     for (size_t ii = 0; ii < infoList.size(); ++ii)
158     {
159         if (infoList[ii].name.c_str() == myName)
160             return &(infoList[ii]);
161     }
162     return NULL;
163 }
164 
165 }  // namespace anonymous
166 
TVariableInfo()167 TVariableInfo::TVariableInfo()
168     : type(SH_NONE),
169       size(0),
170       precision(EbpUndefined),
171       staticUse(false)
172 {
173 }
174 
TVariableInfo(ShDataType type,int size)175 TVariableInfo::TVariableInfo(ShDataType type, int size)
176     : type(type),
177       size(size),
178       precision(EbpUndefined),
179       staticUse(false)
180 {
181 }
182 
CollectVariables(TVariableInfoList & attribs,TVariableInfoList & uniforms,TVariableInfoList & varyings,ShHashFunction64 hashFunction)183 CollectVariables::CollectVariables(TVariableInfoList& attribs,
184                                    TVariableInfoList& uniforms,
185                                    TVariableInfoList& varyings,
186                                    ShHashFunction64 hashFunction)
187     : mAttribs(attribs),
188       mUniforms(uniforms),
189       mVaryings(varyings),
190       mPointCoordAdded(false),
191       mFrontFacingAdded(false),
192       mFragCoordAdded(false),
193       mHashFunction(hashFunction)
194 {
195 }
196 
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
201 // shader.
visitSymbol(TIntermSymbol * symbol)202 void CollectVariables::visitSymbol(TIntermSymbol* symbol)
203 {
204     ASSERT(symbol != NULL);
205     TVariableInfo* var = NULL;
206     switch (symbol->getQualifier())
207     {
208     case EvqVaryingOut:
209     case EvqInvariantVaryingOut:
210     case EvqVaryingIn:
211     case EvqInvariantVaryingIn:
212         var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
213         break;
214     case EvqUniform:
215         var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
216         break;
217     case EvqFragCoord:
218         if (!mFragCoordAdded) {
219             TVariableInfo info;
220             info.name = "gl_FragCoord";
221             info.mappedName = "gl_FragCoord";
222             info.type = SH_FLOAT_VEC4;
223             info.size = 1;
224             info.precision = EbpMedium;  // Use mediump as it doesn't really matter.
225             info.staticUse = true;
226 	    mVaryings.push_back(info);
227             mFragCoordAdded = true;
228         }
229         return;
230     case EvqFrontFacing:
231         if (!mFrontFacingAdded) {
232             TVariableInfo info;
233             info.name = "gl_FrontFacing";
234             info.mappedName = "gl_FrontFacing";
235             info.type = SH_BOOL;
236             info.size = 1;
237             info.precision = EbpUndefined;
238             info.staticUse = true;
239 	    mVaryings.push_back(info);
240             mFrontFacingAdded = true;
241         }
242         return;
243     case EvqPointCoord:
244         if (!mPointCoordAdded) {
245             TVariableInfo info;
246             info.name = "gl_PointCoord";
247             info.mappedName = "gl_PointCoord";
248             info.type = SH_FLOAT_VEC2;
249             info.size = 1;
250             info.precision = EbpMedium;  // Use mediump as it doesn't really matter.
251             info.staticUse = true;
252 	    mVaryings.push_back(info);
253             mPointCoordAdded = true;
254         }
255         return;
256     default:
257         break;
258     }
259     if (var)
260         var->staticUse = true;
261 }
262 
visitAggregate(Visit,TIntermAggregate * node)263 bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
264 {
265     bool visitChildren = true;
266 
267     switch (node->getOp())
268     {
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)
275         {
276             TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs :
277                 (qualifier == EvqUniform ? mUniforms : mVaryings);
278             for (TIntermSequence::const_iterator i = sequence.begin();
279                  i != sequence.end(); ++i)
280             {
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();
291                 else
292                     processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
293                 getVariableInfo(variable->getType(),
294                                 variable->getOriginalSymbol(),
295                                 processedSymbol,
296                                 infoList,
297                                 mHashFunction);
298                 visitChildren = false;
299             }
300         }
301         break;
302     }
303     default: break;
304     }
305 
306     return visitChildren;
307 }
308 
309