blob: fdaef297349b73420152df28305075e2ecd31e7e [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
Geoff Lang17732822013-08-29 13:46:49 -04007#include "compiler/translator/VariableInfo.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +00008
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();
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800166 varInfo.isArray = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000167 } else {
168 varInfo.name = name.c_str();
zmo@google.comfd747b82011-04-23 01:30:07 +0000169 varInfo.mappedName = mappedName.c_str();
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000170 varInfo.size = 1;
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800171 varInfo.isArray = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000172 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400173 varInfo.precision = type.getPrecision();
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000174 varInfo.type = getVariableDataType(type);
175 infoList.push_back(varInfo);
176}
177
178void getUserDefinedVariableInfo(const TType& type,
179 const TString& name,
zmo@google.comfd747b82011-04-23 01:30:07 +0000180 const TString& mappedName,
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000181 TVariableInfoList& infoList,
182 ShHashFunction64 hashFunction)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000183{
Jamie Madill98493dd2013-07-08 14:39:03 -0400184 ASSERT(type.getBasicType() == EbtStruct || type.isInterfaceBlock());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000185
Jamie Madill98493dd2013-07-08 14:39:03 -0400186 const TFieldList& fields = type.getStruct()->fields();
187 for (size_t i = 0; i < fields.size(); ++i) {
188 const TType& fieldType = *(fields[i]->type());
189 const TString& fieldName = fields[i]->name();
190 getVariableInfo(fieldType,
191 name + "." + fieldName,
192 mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000193 infoList,
194 hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000195 }
196}
197
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400198TVariableInfo* findVariable(const TType& type,
199 const TString& name,
200 TVariableInfoList& infoList)
201{
202 // TODO(zmo): optimize this function.
203 TString myName = name;
204 if (type.isArray())
205 myName += "[0]";
206 for (size_t ii = 0; ii < infoList.size(); ++ii)
207 {
208 if (infoList[ii].name.c_str() == myName)
209 return &(infoList[ii]);
210 }
211 return NULL;
212}
213
214} // namespace anonymous
215
gman@chromium.org8d804792012-10-17 21:33:48 +0000216TVariableInfo::TVariableInfo()
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400217 : type(SH_NONE),
218 size(0),
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800219 isArray(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400220 precision(EbpUndefined),
221 staticUse(false)
gman@chromium.org8d804792012-10-17 21:33:48 +0000222{
223}
224
225TVariableInfo::TVariableInfo(ShDataType type, int size)
226 : type(type),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400227 size(size),
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800228 isArray(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400229 precision(EbpUndefined),
230 staticUse(false)
gman@chromium.org8d804792012-10-17 21:33:48 +0000231{
232}
233
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400234CollectVariables::CollectVariables(TVariableInfoList& attribs,
235 TVariableInfoList& uniforms,
236 TVariableInfoList& varyings,
237 ShHashFunction64 hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000238 : mAttribs(attribs),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000239 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400240 mVaryings(varyings),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400241 mPointCoordAdded(false),
242 mFrontFacingAdded(false),
243 mFragCoordAdded(false),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000244 mHashFunction(hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000245{
246}
247
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400248// We want to check whether a uniform/varying is statically used
249// because we only count the used ones in packing computing.
250// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
251// toward varying counting if they are statically used in a fragment
252// shader.
253void CollectVariables::visitSymbol(TIntermSymbol* symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000254{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400255 ASSERT(symbol != NULL);
256 TVariableInfo* var = NULL;
257 switch (symbol->getQualifier())
258 {
259 case EvqVaryingOut:
260 case EvqInvariantVaryingOut:
261 case EvqVaryingIn:
262 case EvqInvariantVaryingIn:
263 var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
264 break;
265 case EvqUniform:
266 var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
267 break;
268 case EvqFragCoord:
269 if (!mFragCoordAdded) {
270 TVariableInfo info;
271 info.name = "gl_FragCoord";
272 info.mappedName = "gl_FragCoord";
273 info.type = SH_FLOAT_VEC4;
274 info.size = 1;
275 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
276 info.staticUse = true;
277 mVaryings.push_back(info);
278 mFragCoordAdded = true;
279 }
280 return;
281 case EvqFrontFacing:
282 if (!mFrontFacingAdded) {
283 TVariableInfo info;
284 info.name = "gl_FrontFacing";
285 info.mappedName = "gl_FrontFacing";
286 info.type = SH_BOOL;
287 info.size = 1;
288 info.precision = EbpUndefined;
289 info.staticUse = true;
290 mVaryings.push_back(info);
291 mFrontFacingAdded = true;
292 }
293 return;
294 case EvqPointCoord:
295 if (!mPointCoordAdded) {
296 TVariableInfo info;
297 info.name = "gl_PointCoord";
298 info.mappedName = "gl_PointCoord";
299 info.type = SH_FLOAT_VEC2;
300 info.size = 1;
301 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
302 info.staticUse = true;
303 mVaryings.push_back(info);
304 mPointCoordAdded = true;
305 }
306 return;
307 default:
308 break;
309 }
310 if (var)
311 var->staticUse = true;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000312}
313
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400314bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000315{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400316 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000317
318 switch (node->getOp())
319 {
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000320 case EOpDeclaration: {
321 const TIntermSequence& sequence = node->getSequence();
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000322 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400323 if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform ||
324 qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
325 qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000326 {
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400327 TVariableInfoList *infoList = NULL;
328
329 switch (qualifier)
330 {
331 case EvqAttribute:
332 case EvqVertexIn:
333 infoList = &mAttribs;
334 break;
335 case EvqUniform:
336 infoList = &mUniforms;
337 break;
338 default:
339 infoList = &mVaryings;
340 break;
341 }
342
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000343 for (TIntermSequence::const_iterator i = sequence.begin();
344 i != sequence.end(); ++i)
345 {
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000346 const TIntermSymbol* variable = (*i)->getAsSymbolNode();
347 // The only case in which the sequence will not contain a
348 // TIntermSymbol node is initialization. It will contain a
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400349 // TInterBinary node in that case. Since attributes, uniforms,
350 // and varyings cannot be initialized in a shader, we must have
351 // only TIntermSymbol nodes in the sequence.
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000352 ASSERT(variable != NULL);
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000353 TString processedSymbol;
354 if (mHashFunction == NULL)
355 processedSymbol = variable->getSymbol();
356 else
357 processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
zmo@google.comfd747b82011-04-23 01:30:07 +0000358 getVariableInfo(variable->getType(),
359 variable->getOriginalSymbol(),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000360 processedSymbol,
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400361 *infoList,
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000362 mHashFunction);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400363 visitChildren = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000364 }
365 }
366 break;
367 }
368 default: break;
369 }
370
371 return visitChildren;
372}
373