blob: b2c3205aaf86191e2ba8bba0aabf5ced7f00bfd7 [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"
Jamie Madillaa72d782014-07-02 15:31:19 -04008#include "compiler/translator/util.h"
Jamie Madill183bde52014-07-02 15:31:19 -04009#include "angle_gl.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000010
Zhenyao Mod2d340b2013-09-23 14:57:05 -040011namespace {
12
13TString arrayBrackets(int index)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000014{
15 TStringStream stream;
16 stream << "[" << index << "]";
17 return stream.str();
18}
19
Zhenyao Mod2d340b2013-09-23 14:57:05 -040020void getBuiltInVariableInfo(const TType& type,
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000021 const TString& name,
zmo@google.comfd747b82011-04-23 01:30:07 +000022 const TString& mappedName,
Zhenyao Mod2d340b2013-09-23 14:57:05 -040023 TVariableInfoList& infoList);
24void getUserDefinedVariableInfo(const TType& type,
25 const TString& name,
26 const TString& mappedName,
27 TVariableInfoList& infoList,
28 ShHashFunction64 hashFunction);
29
30// Returns info for an attribute, uniform, or varying.
31void getVariableInfo(const TType& type,
32 const TString& name,
33 const TString& mappedName,
34 TVariableInfoList& infoList,
35 ShHashFunction64 hashFunction)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000036{
Dan Glastonburyb66feb32014-05-14 15:38:55 +100037 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000038 if (type.isArray()) {
39 for (int i = 0; i < type.getArraySize(); ++i) {
40 TString lname = name + arrayBrackets(i);
zmo@google.comfd747b82011-04-23 01:30:07 +000041 TString lmappedName = mappedName + arrayBrackets(i);
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000042 getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000043 }
44 } else {
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000045 getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000046 }
47 } else {
zmo@google.comfd747b82011-04-23 01:30:07 +000048 getBuiltInVariableInfo(type, name, mappedName, infoList);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000049 }
50}
51
52void getBuiltInVariableInfo(const TType& type,
53 const TString& name,
zmo@google.comfd747b82011-04-23 01:30:07 +000054 const TString& mappedName,
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000055 TVariableInfoList& infoList)
56{
57 ASSERT(type.getBasicType() != EbtStruct);
58
59 TVariableInfo varInfo;
60 if (type.isArray()) {
61 varInfo.name = (name + "[0]").c_str();
zmo@google.comfd747b82011-04-23 01:30:07 +000062 varInfo.mappedName = (mappedName + "[0]").c_str();
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000063 varInfo.size = type.getArraySize();
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080064 varInfo.isArray = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000065 } else {
66 varInfo.name = name.c_str();
zmo@google.comfd747b82011-04-23 01:30:07 +000067 varInfo.mappedName = mappedName.c_str();
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000068 varInfo.size = 1;
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080069 varInfo.isArray = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000070 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -040071 varInfo.precision = type.getPrecision();
Jamie Madillaa72d782014-07-02 15:31:19 -040072 varInfo.type = sh::GLVariableType(type);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000073 infoList.push_back(varInfo);
74}
75
76void getUserDefinedVariableInfo(const TType& type,
77 const TString& name,
zmo@google.comfd747b82011-04-23 01:30:07 +000078 const TString& mappedName,
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000079 TVariableInfoList& infoList,
80 ShHashFunction64 hashFunction)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000081{
Jamie Madill98493dd2013-07-08 14:39:03 -040082 ASSERT(type.getBasicType() == EbtStruct || type.isInterfaceBlock());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000083
Dan Glastonburyb66feb32014-05-14 15:38:55 +100084 const TFieldList& fields = type.isInterfaceBlock() ?
85 type.getInterfaceBlock()->fields() :
86 type.getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -040087 for (size_t i = 0; i < fields.size(); ++i) {
88 const TType& fieldType = *(fields[i]->type());
89 const TString& fieldName = fields[i]->name();
90 getVariableInfo(fieldType,
91 name + "." + fieldName,
92 mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000093 infoList,
94 hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000095 }
96}
97
Zhenyao Mod2d340b2013-09-23 14:57:05 -040098TVariableInfo* findVariable(const TType& type,
99 const TString& name,
100 TVariableInfoList& infoList)
101{
102 // TODO(zmo): optimize this function.
103 TString myName = name;
104 if (type.isArray())
105 myName += "[0]";
106 for (size_t ii = 0; ii < infoList.size(); ++ii)
107 {
108 if (infoList[ii].name.c_str() == myName)
109 return &(infoList[ii]);
110 }
111 return NULL;
112}
113
114} // namespace anonymous
115
gman@chromium.org8d804792012-10-17 21:33:48 +0000116TVariableInfo::TVariableInfo()
Jamie Madill183bde52014-07-02 15:31:19 -0400117 : type(GL_NONE),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400118 size(0),
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800119 isArray(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400120 precision(EbpUndefined),
121 staticUse(false)
gman@chromium.org8d804792012-10-17 21:33:48 +0000122{
123}
124
Jamie Madill183bde52014-07-02 15:31:19 -0400125TVariableInfo::TVariableInfo(sh::GLenum type, int size)
gman@chromium.org8d804792012-10-17 21:33:48 +0000126 : type(type),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400127 size(size),
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800128 isArray(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400129 precision(EbpUndefined),
130 staticUse(false)
gman@chromium.org8d804792012-10-17 21:33:48 +0000131{
132}
133
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400134CollectVariables::CollectVariables(TVariableInfoList& attribs,
135 TVariableInfoList& uniforms,
136 TVariableInfoList& varyings,
137 ShHashFunction64 hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000138 : mAttribs(attribs),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000139 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400140 mVaryings(varyings),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400141 mPointCoordAdded(false),
142 mFrontFacingAdded(false),
143 mFragCoordAdded(false),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000144 mHashFunction(hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000145{
146}
147
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400148// We want to check whether a uniform/varying is statically used
149// because we only count the used ones in packing computing.
150// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
151// toward varying counting if they are statically used in a fragment
152// shader.
153void CollectVariables::visitSymbol(TIntermSymbol* symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000154{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400155 ASSERT(symbol != NULL);
156 TVariableInfo* var = NULL;
157 switch (symbol->getQualifier())
158 {
159 case EvqVaryingOut:
160 case EvqInvariantVaryingOut:
161 case EvqVaryingIn:
162 case EvqInvariantVaryingIn:
163 var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
164 break;
165 case EvqUniform:
166 var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
167 break;
168 case EvqFragCoord:
169 if (!mFragCoordAdded) {
170 TVariableInfo info;
171 info.name = "gl_FragCoord";
172 info.mappedName = "gl_FragCoord";
Jamie Madill183bde52014-07-02 15:31:19 -0400173 info.type = GL_FLOAT_VEC4;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400174 info.size = 1;
175 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
176 info.staticUse = true;
177 mVaryings.push_back(info);
178 mFragCoordAdded = true;
179 }
180 return;
181 case EvqFrontFacing:
182 if (!mFrontFacingAdded) {
183 TVariableInfo info;
184 info.name = "gl_FrontFacing";
185 info.mappedName = "gl_FrontFacing";
Jamie Madill183bde52014-07-02 15:31:19 -0400186 info.type = GL_BOOL;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400187 info.size = 1;
188 info.precision = EbpUndefined;
189 info.staticUse = true;
190 mVaryings.push_back(info);
191 mFrontFacingAdded = true;
192 }
193 return;
194 case EvqPointCoord:
195 if (!mPointCoordAdded) {
196 TVariableInfo info;
197 info.name = "gl_PointCoord";
198 info.mappedName = "gl_PointCoord";
Jamie Madill183bde52014-07-02 15:31:19 -0400199 info.type = GL_FLOAT_VEC2;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400200 info.size = 1;
201 info.precision = EbpMedium; // Use mediump as it doesn't really matter.
202 info.staticUse = true;
203 mVaryings.push_back(info);
204 mPointCoordAdded = true;
205 }
206 return;
207 default:
208 break;
209 }
210 if (var)
211 var->staticUse = true;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000212}
213
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400214bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000215{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400216 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000217
218 switch (node->getOp())
219 {
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000220 case EOpDeclaration: {
221 const TIntermSequence& sequence = node->getSequence();
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000222 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400223 if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform ||
224 qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
225 qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000226 {
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400227 TVariableInfoList *infoList = NULL;
228
229 switch (qualifier)
230 {
231 case EvqAttribute:
232 case EvqVertexIn:
233 infoList = &mAttribs;
234 break;
235 case EvqUniform:
236 infoList = &mUniforms;
237 break;
238 default:
239 infoList = &mVaryings;
240 break;
241 }
242
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000243 for (TIntermSequence::const_iterator i = sequence.begin();
244 i != sequence.end(); ++i)
245 {
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000246 const TIntermSymbol* variable = (*i)->getAsSymbolNode();
247 // The only case in which the sequence will not contain a
248 // TIntermSymbol node is initialization. It will contain a
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400249 // TInterBinary node in that case. Since attributes, uniforms,
250 // and varyings cannot be initialized in a shader, we must have
251 // only TIntermSymbol nodes in the sequence.
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000252 ASSERT(variable != NULL);
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000253 TString processedSymbol;
254 if (mHashFunction == NULL)
255 processedSymbol = variable->getSymbol();
256 else
Zhenyao Mo3cdfcce2014-03-07 13:00:08 -0800257 processedSymbol = TIntermTraverser::hash(variable->getSymbol(), mHashFunction);
zmo@google.comfd747b82011-04-23 01:30:07 +0000258 getVariableInfo(variable->getType(),
Zhenyao Mo3cdfcce2014-03-07 13:00:08 -0800259 variable->getSymbol(),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000260 processedSymbol,
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400261 *infoList,
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000262 mHashFunction);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400263 visitChildren = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000264 }
265 }
266 break;
267 }
268 default: break;
269 }
270
271 return visitChildren;
272}