blob: a69abcde1c0fb0f89f59975afe0f06baea623d1e [file] [log] [blame]
alokp@chromium.org07620a52010-09-23 17:53:56 +00001//
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
alokp@chromium.org07620a52010-09-23 17:53:56 +00003// 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
Zhenyao Mod2d340b2013-09-23 14:57:05 -04009namespace {
10
11TString arrayBrackets(int index)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000012{
13 TStringStream stream;
14 stream << "[" << index << "]";
15 return stream.str();
16}
17
Zhenyao Mod2d340b2013-09-23 14:57:05 -040018// Returns the data type for an attribute, uniform, or varying.
19ShDataType getVariableDataType(const TType& type)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000020{
21 switch (type.getBasicType()) {
22 case EbtFloat:
23 if (type.isMatrix()) {
shannonwoods@chromium.org8da034c2013-05-30 00:19:15 +000024 switch (type.getCols())
25 {
26 case 2:
27 switch (type.getRows())
28 {
29 case 2: return SH_FLOAT_MAT2;
30 case 3: return SH_FLOAT_MAT2x3;
31 case 4: return SH_FLOAT_MAT2x4;
32 default: UNREACHABLE();
33 }
34 case 3:
35 switch (type.getRows())
36 {
37 case 2: return SH_FLOAT_MAT3x2;
38 case 3: return SH_FLOAT_MAT3;
39 case 4: return SH_FLOAT_MAT3x4;
40 default: UNREACHABLE();
41 }
42 case 4:
43 switch (type.getRows())
44 {
45 case 2: return SH_FLOAT_MAT4x2;
46 case 3: return SH_FLOAT_MAT4x3;
47 case 4: return SH_FLOAT_MAT4;
48 default: UNREACHABLE();
49 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000050 }
51 } else if (type.isVector()) {
52 switch (type.getNominalSize()) {
53 case 2: return SH_FLOAT_VEC2;
54 case 3: return SH_FLOAT_VEC3;
55 case 4: return SH_FLOAT_VEC4;
56 default: UNREACHABLE();
57 }
58 } else {
59 return SH_FLOAT;
60 }
61 case EbtInt:
62 if (type.isMatrix()) {
63 UNREACHABLE();
64 } else if (type.isVector()) {
65 switch (type.getNominalSize()) {
66 case 2: return SH_INT_VEC2;
67 case 3: return SH_INT_VEC3;
68 case 4: return SH_INT_VEC4;
69 default: UNREACHABLE();
70 }
71 } else {
72 return SH_INT;
73 }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +000074 case EbtUInt:
75 if (type.isMatrix()) {
76 UNREACHABLE();
77 } else if (type.isVector()) {
Jamie Madill22d63da2013-06-07 12:45:12 -040078 switch (type.getNominalSize()) {
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +000079 case 2: return SH_UNSIGNED_INT_VEC2;
80 case 3: return SH_UNSIGNED_INT_VEC3;
81 case 4: return SH_UNSIGNED_INT_VEC4;
82 default: UNREACHABLE();
83 }
84 } else {
85 return SH_UNSIGNED_INT;
86 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000087 case EbtBool:
88 if (type.isMatrix()) {
89 UNREACHABLE();
90 } else if (type.isVector()) {
91 switch (type.getNominalSize()) {
92 case 2: return SH_BOOL_VEC2;
93 case 3: return SH_BOOL_VEC3;
94 case 4: return SH_BOOL_VEC4;
95 default: UNREACHABLE();
96 }
97 } else {
98 return SH_BOOL;
99 }
100 case EbtSampler2D: return SH_SAMPLER_2D;
Nicolas Capens8772b582013-06-24 16:14:19 -0400101 case EbtSampler3D: return SH_SAMPLER_3D;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000102 case EbtSamplerCube: return SH_SAMPLER_CUBE;
apatrick@chromium.org65756022012-01-17 21:45:38 +0000103 case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES;
kbr@chromium.org205fef32011-11-22 20:50:02 +0000104 case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB;
Nicolas Capens8772b582013-06-24 16:14:19 -0400105 case EbtSampler2DArray: return SH_SAMPLER_2D_ARRAY;
Nicolas Capens344e7142013-06-24 15:39:21 -0400106 case EbtISampler2D: return SH_INT_SAMPLER_2D;
Nicolas Capens8772b582013-06-24 16:14:19 -0400107 case EbtISampler3D: return SH_INT_SAMPLER_3D;
Nicolas Capens344e7142013-06-24 15:39:21 -0400108 case EbtISamplerCube: return SH_INT_SAMPLER_CUBE;
Nicolas Capens8772b582013-06-24 16:14:19 -0400109 case EbtISampler2DArray: return SH_INT_SAMPLER_2D_ARRAY;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -0400110 case EbtUSampler2D: return SH_UNSIGNED_INT_SAMPLER_2D;
Nicolas Capens8772b582013-06-24 16:14:19 -0400111 case EbtUSampler3D: return SH_UNSIGNED_INT_SAMPLER_3D;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -0400112 case EbtUSamplerCube: return SH_UNSIGNED_INT_SAMPLER_CUBE;
Nicolas Capens8772b582013-06-24 16:14:19 -0400113 case EbtUSampler2DArray: return SH_UNSIGNED_INT_SAMPLER_2D_ARRAY;
Nicolas Capens2a1d8a32013-07-18 11:49:40 -0400114 case EbtSampler2DShadow: return SH_SAMPLER_2D_SHADOW;
115 case EbtSamplerCubeShadow: return SH_SAMPLER_CUBE_SHADOW;
116 case EbtSampler2DArrayShadow: return SH_SAMPLER_2D_ARRAY_SHADOW;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000117 default: UNREACHABLE();
118 }
119 return SH_NONE;
120}
121
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400122void getBuiltInVariableInfo(const TType& type,
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000123 const TString& name,
zmo@google.comfd747b82011-04-23 01:30:07 +0000124 const TString& mappedName,
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400125 TVariableInfoList& infoList);
126void getUserDefinedVariableInfo(const TType& type,
127 const TString& name,
128 const TString& mappedName,
129 TVariableInfoList& infoList,
130 ShHashFunction64 hashFunction);
131
132// Returns info for an attribute, uniform, or varying.
133void getVariableInfo(const TType& type,
134 const TString& name,
135 const TString& mappedName,
136 TVariableInfoList& infoList,
137 ShHashFunction64 hashFunction)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000138{
139 if (type.getBasicType() == EbtStruct) {
140 if (type.isArray()) {
141 for (int i = 0; i < type.getArraySize(); ++i) {
142 TString lname = name + arrayBrackets(i);
zmo@google.comfd747b82011-04-23 01:30:07 +0000143 TString lmappedName = mappedName + arrayBrackets(i);
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000144 getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000145 }
146 } else {
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000147 getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000148 }
149 } else {
zmo@google.comfd747b82011-04-23 01:30:07 +0000150 getBuiltInVariableInfo(type, name, mappedName, infoList);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000151 }
152}
153
154void getBuiltInVariableInfo(const TType& type,
155 const TString& name,
zmo@google.comfd747b82011-04-23 01:30:07 +0000156 const TString& mappedName,
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000157 TVariableInfoList& infoList)
158{
159 ASSERT(type.getBasicType() != EbtStruct);
160
161 TVariableInfo varInfo;
162 if (type.isArray()) {
163 varInfo.name = (name + "[0]").c_str();
zmo@google.comfd747b82011-04-23 01:30:07 +0000164 varInfo.mappedName = (mappedName + "[0]").c_str();
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000165 varInfo.size = type.getArraySize();
166 } else {
167 varInfo.name = name.c_str();
zmo@google.comfd747b82011-04-23 01:30:07 +0000168 varInfo.mappedName = mappedName.c_str();
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000169 varInfo.size = 1;
170 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400171 varInfo.precision = type.getPrecision();
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000172 varInfo.type = getVariableDataType(type);
173 infoList.push_back(varInfo);
174}
175
176void getUserDefinedVariableInfo(const TType& type,
177 const TString& name,
zmo@google.comfd747b82011-04-23 01:30:07 +0000178 const TString& mappedName,
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000179 TVariableInfoList& infoList,
180 ShHashFunction64 hashFunction)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000181{
Jamie Madill98493dd2013-07-08 14:39:03 -0400182 ASSERT(type.getBasicType() == EbtStruct || type.isInterfaceBlock());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000183
Jamie Madill98493dd2013-07-08 14:39:03 -0400184 const TFieldList& fields = type.getStruct()->fields();
185 for (size_t i = 0; i < fields.size(); ++i) {
186 const TType& fieldType = *(fields[i]->type());
187 const TString& fieldName = fields[i]->name();
188 getVariableInfo(fieldType,
189 name + "." + fieldName,
190 mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000191 infoList,
192 hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000193 }
194}
195
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400196TVariableInfo* findVariable(const TType& type,
197 const TString& name,
198 TVariableInfoList& infoList)
199{
200 // TODO(zmo): optimize this function.
201 TString myName = name;
202 if (type.isArray())
203 myName += "[0]";
204 for (size_t ii = 0; ii < infoList.size(); ++ii)
205 {
206 if (infoList[ii].name.c_str() == myName)
207 return &(infoList[ii]);
208 }
209 return NULL;
210}
211
212} // namespace anonymous
213
gman@chromium.org8d804792012-10-17 21:33:48 +0000214TVariableInfo::TVariableInfo()
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400215 : type(SH_NONE),
216 size(0),
217 precision(EbpUndefined),
218 staticUse(false)
gman@chromium.org8d804792012-10-17 21:33:48 +0000219{
220}
221
222TVariableInfo::TVariableInfo(ShDataType type, int size)
223 : type(type),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400224 size(size),
225 precision(EbpUndefined),
226 staticUse(false)
gman@chromium.org8d804792012-10-17 21:33:48 +0000227{
228}
229
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400230CollectVariables::CollectVariables(TVariableInfoList& attribs,
231 TVariableInfoList& uniforms,
232 TVariableInfoList& varyings,
233 ShHashFunction64 hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000234 : mAttribs(attribs),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000235 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400236 mVaryings(varyings),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400237 mPointCoordAdded(false),
238 mFrontFacingAdded(false),
239 mFragCoordAdded(false),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000240 mHashFunction(hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000241{
242}
243
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400244// We want to check whether a uniform/varying is statically used
245// because we only count the used ones in packing computing.
246// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
247// toward varying counting if they are statically used in a fragment
248// shader.
249void CollectVariables::visitSymbol(TIntermSymbol* symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000250{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400251 ASSERT(symbol != NULL);
252 TVariableInfo* var = NULL;
253 switch (symbol->getQualifier())
254 {
255 case EvqVaryingOut:
256 case EvqInvariantVaryingOut:
257 case EvqVaryingIn:
258 case EvqInvariantVaryingIn:
259 var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
260 break;
261 case EvqUniform:
262 var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
263 break;
264 case EvqFragCoord:
265 if (!mFragCoordAdded) {
266 TVariableInfo info;
267 info.name = "gl_FragCoord";
268 info.mappedName = "gl_FragCoord";
269 info.type = SH_FLOAT_VEC4;
270 info.size = 1;
271 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
272 info.staticUse = true;
273 mVaryings.push_back(info);
274 mFragCoordAdded = true;
275 }
276 return;
277 case EvqFrontFacing:
278 if (!mFrontFacingAdded) {
279 TVariableInfo info;
280 info.name = "gl_FrontFacing";
281 info.mappedName = "gl_FrontFacing";
282 info.type = SH_BOOL;
283 info.size = 1;
284 info.precision = EbpUndefined;
285 info.staticUse = true;
286 mVaryings.push_back(info);
287 mFrontFacingAdded = true;
288 }
289 return;
290 case EvqPointCoord:
291 if (!mPointCoordAdded) {
292 TVariableInfo info;
293 info.name = "gl_PointCoord";
294 info.mappedName = "gl_PointCoord";
295 info.type = SH_FLOAT_VEC2;
296 info.size = 1;
297 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
298 info.staticUse = true;
299 mVaryings.push_back(info);
300 mPointCoordAdded = true;
301 }
302 return;
303 default:
304 break;
305 }
306 if (var)
307 var->staticUse = true;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000308}
309
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400310bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000311{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400312 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000313
314 switch (node->getOp())
315 {
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000316 case EOpDeclaration: {
317 const TIntermSequence& sequence = node->getSequence();
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000318 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400319 if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform ||
320 qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
321 qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000322 {
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400323 TVariableInfoList *infoList = NULL;
324
325 switch (qualifier)
326 {
327 case EvqAttribute:
328 case EvqVertexIn:
329 infoList = &mAttribs;
330 break;
331 case EvqUniform:
332 infoList = &mUniforms;
333 break;
334 default:
335 infoList = &mVaryings;
336 break;
337 }
338
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000339 for (TIntermSequence::const_iterator i = sequence.begin();
340 i != sequence.end(); ++i)
341 {
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000342 const TIntermSymbol* variable = (*i)->getAsSymbolNode();
343 // The only case in which the sequence will not contain a
344 // TIntermSymbol node is initialization. It will contain a
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400345 // TInterBinary node in that case. Since attributes, uniforms,
346 // and varyings cannot be initialized in a shader, we must have
347 // only TIntermSymbol nodes in the sequence.
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000348 ASSERT(variable != NULL);
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000349 TString processedSymbol;
350 if (mHashFunction == NULL)
351 processedSymbol = variable->getSymbol();
352 else
353 processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
zmo@google.comfd747b82011-04-23 01:30:07 +0000354 getVariableInfo(variable->getType(),
355 variable->getOriginalSymbol(),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000356 processedSymbol,
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400357 *infoList,
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000358 mHashFunction);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400359 visitChildren = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000360 }
361 }
362 break;
363 }
364 default: break;
365 }
366
367 return visitChildren;
368}
369