blob: dd820bd9c9c3de3a14701d3efeaf5b09a6471d01 [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
Jamie Madill4667c452014-07-08 15:02:36 -04007#include "angle_gl.h"
Geoff Lang17732822013-08-29 13:46:49 -04008#include "compiler/translator/VariableInfo.h"
Jamie Madillaa72d782014-07-02 15:31:19 -04009#include "compiler/translator/util.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
Jamie Madilla718c1e2014-07-02 15:31:22 -040020template <typename VarT>
21void getBuiltInVariableInfo(const TType &type,
22 const TString &name,
23 const TString &mappedName,
24 std::vector<VarT> &infoList);
25
26template <typename VarT>
27void getUserDefinedVariableInfo(const TType &type,
28 const TString &name,
29 const TString &mappedName,
30 std::vector<VarT> &infoList,
Zhenyao Mod2d340b2013-09-23 14:57:05 -040031 ShHashFunction64 hashFunction);
32
33// Returns info for an attribute, uniform, or varying.
Jamie Madilla718c1e2014-07-02 15:31:22 -040034template <typename VarT>
35void getVariableInfo(const TType &type,
36 const TString &name,
37 const TString &mappedName,
38 std::vector<VarT> &infoList,
Zhenyao Mod2d340b2013-09-23 14:57:05 -040039 ShHashFunction64 hashFunction)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000040{
Dan Glastonburyb66feb32014-05-14 15:38:55 +100041 if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000042 if (type.isArray()) {
43 for (int i = 0; i < type.getArraySize(); ++i) {
44 TString lname = name + arrayBrackets(i);
zmo@google.comfd747b82011-04-23 01:30:07 +000045 TString lmappedName = mappedName + arrayBrackets(i);
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000046 getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000047 }
48 } else {
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000049 getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000050 }
51 } else {
zmo@google.comfd747b82011-04-23 01:30:07 +000052 getBuiltInVariableInfo(type, name, mappedName, infoList);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000053 }
54}
55
Jamie Madilla718c1e2014-07-02 15:31:22 -040056template <class VarT>
57void getBuiltInVariableInfo(const TType &type,
58 const TString &name,
59 const TString &mappedName,
60 std::vector<VarT> &infoList)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000061{
62 ASSERT(type.getBasicType() != EbtStruct);
63
Jamie Madilla718c1e2014-07-02 15:31:22 -040064 VarT varInfo;
Jamie Madill4667c452014-07-08 15:02:36 -040065 if (type.isArray())
66 {
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000067 varInfo.name = (name + "[0]").c_str();
zmo@google.comfd747b82011-04-23 01:30:07 +000068 varInfo.mappedName = (mappedName + "[0]").c_str();
Jamie Madilla718c1e2014-07-02 15:31:22 -040069 varInfo.arraySize = type.getArraySize();
Jamie Madill4667c452014-07-08 15:02:36 -040070 }
71 else
72 {
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000073 varInfo.name = name.c_str();
zmo@google.comfd747b82011-04-23 01:30:07 +000074 varInfo.mappedName = mappedName.c_str();
Jamie Madilla718c1e2014-07-02 15:31:22 -040075 varInfo.arraySize = 0;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000076 }
Jamie Madilla718c1e2014-07-02 15:31:22 -040077 varInfo.precision = sh::GLVariablePrecision(type);
Jamie Madillaa72d782014-07-02 15:31:19 -040078 varInfo.type = sh::GLVariableType(type);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000079 infoList.push_back(varInfo);
80}
81
Jamie Madilla718c1e2014-07-02 15:31:22 -040082template <class VarT>
83void getUserDefinedVariableInfo(const TType &type,
84 const TString &name,
85 const TString &mappedName,
86 std::vector<VarT> &infoList,
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000087 ShHashFunction64 hashFunction)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000088{
Jamie Madill98493dd2013-07-08 14:39:03 -040089 ASSERT(type.getBasicType() == EbtStruct || type.isInterfaceBlock());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000090
Dan Glastonburyb66feb32014-05-14 15:38:55 +100091 const TFieldList& fields = type.isInterfaceBlock() ?
92 type.getInterfaceBlock()->fields() :
93 type.getStruct()->fields();
Jamie Madill4667c452014-07-08 15:02:36 -040094 for (size_t i = 0; i < fields.size(); ++i)
95 {
Jamie Madill98493dd2013-07-08 14:39:03 -040096 const TType& fieldType = *(fields[i]->type());
97 const TString& fieldName = fields[i]->name();
98 getVariableInfo(fieldType,
99 name + "." + fieldName,
100 mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000101 infoList,
102 hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000103 }
104}
105
Jamie Madilla718c1e2014-07-02 15:31:22 -0400106template <class VarT>
107VarT* findVariable(const TType &type,
108 const TString &name,
109 std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400110{
111 // TODO(zmo): optimize this function.
112 TString myName = name;
113 if (type.isArray())
114 myName += "[0]";
Jamie Madilla718c1e2014-07-02 15:31:22 -0400115 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400116 {
Jamie Madilla718c1e2014-07-02 15:31:22 -0400117 if ((*infoList)[ii].name.c_str() == myName)
118 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400119 }
120 return NULL;
121}
122
123} // namespace anonymous
124
Jamie Madilla718c1e2014-07-02 15:31:22 -0400125CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
126 std::vector<sh::Uniform> *uniforms,
127 std::vector<sh::Varying> *varyings,
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400128 ShHashFunction64 hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000129 : mAttribs(attribs),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000130 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400131 mVaryings(varyings),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400132 mPointCoordAdded(false),
133 mFrontFacingAdded(false),
134 mFragCoordAdded(false),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000135 mHashFunction(hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000136{
137}
138
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400139// We want to check whether a uniform/varying is statically used
140// because we only count the used ones in packing computing.
141// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
142// toward varying counting if they are statically used in a fragment
143// shader.
Jamie Madill4667c452014-07-08 15:02:36 -0400144void CollectVariables::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000145{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400146 ASSERT(symbol != NULL);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400147 sh::ShaderVariable *var = NULL;
Jamie Madill4667c452014-07-08 15:02:36 -0400148
149 if (sh::IsVarying(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400150 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400151 var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400152 }
153 else
154 {
155 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400156 {
Jamie Madill4667c452014-07-08 15:02:36 -0400157 case EvqUniform:
158 var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
159 break;
160 case EvqFragCoord:
161 if (!mFragCoordAdded)
162 {
163 sh::Varying info;
164 info.name = "gl_FragCoord";
165 info.mappedName = "gl_FragCoord";
166 info.type = GL_FLOAT_VEC4;
167 info.arraySize = 0;
168 info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
169 info.staticUse = true;
170 mVaryings->push_back(info);
171 mFragCoordAdded = true;
172 }
173 return;
174 case EvqFrontFacing:
175 if (!mFrontFacingAdded)
176 {
177 sh::Varying info;
178 info.name = "gl_FrontFacing";
179 info.mappedName = "gl_FrontFacing";
180 info.type = GL_BOOL;
181 info.arraySize = 0;
182 info.precision = GL_NONE;
183 info.staticUse = true;
184 mVaryings->push_back(info);
185 mFrontFacingAdded = true;
186 }
187 return;
188 case EvqPointCoord:
189 if (!mPointCoordAdded)
190 {
191 sh::Varying info;
192 info.name = "gl_PointCoord";
193 info.mappedName = "gl_PointCoord";
194 info.type = GL_FLOAT_VEC2;
195 info.arraySize = 0;
196 info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
197 info.staticUse = true;
198 mVaryings->push_back(info);
199 mPointCoordAdded = true;
200 }
201 return;
202 default:
203 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400204 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400205 }
206 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400207 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400208 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400209 }
210}
211
212template <typename VarT>
Jamie Madill4667c452014-07-08 15:02:36 -0400213void CollectVariables::visitVariable(const TIntermSymbol *variable,
214 std::vector<VarT> *infoList) const
215{
216 TString processedSymbol;
217 if (mHashFunction == NULL)
218 processedSymbol = variable->getSymbol();
219 else
220 processedSymbol = TIntermTraverser::hash(variable->getSymbol(), mHashFunction);
221 getVariableInfo(variable->getType(),
222 variable->getSymbol(),
223 processedSymbol,
224 *infoList,
225 mHashFunction);
226}
227
228template <typename VarT>
229void CollectVariables::visitInfoList(const TIntermSequence &sequence,
230 std::vector<VarT> *infoList) const
Jamie Madilla718c1e2014-07-02 15:31:22 -0400231{
232 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
233 {
Jamie Madill4667c452014-07-08 15:02:36 -0400234 const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
Jamie Madilla718c1e2014-07-02 15:31:22 -0400235 // The only case in which the sequence will not contain a
236 // TIntermSymbol node is initialization. It will contain a
237 // TInterBinary node in that case. Since attributes, uniforms,
238 // and varyings cannot be initialized in a shader, we must have
239 // only TIntermSymbol nodes in the sequence.
240 ASSERT(variable != NULL);
Jamie Madill4667c452014-07-08 15:02:36 -0400241 visitVariable(variable, infoList);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400242 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000243}
244
Jamie Madill4667c452014-07-08 15:02:36 -0400245bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000246{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400247 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000248
249 switch (node->getOp())
250 {
Jamie Madill4667c452014-07-08 15:02:36 -0400251 case EOpDeclaration:
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000252 {
Jamie Madill4667c452014-07-08 15:02:36 -0400253 const TIntermSequence &sequence = node->getSequence();
254 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
255 if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform ||
256 sh::IsVarying(qualifier))
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400257 {
Jamie Madill4667c452014-07-08 15:02:36 -0400258 switch (qualifier)
259 {
260 case EvqAttribute:
261 case EvqVertexIn:
262 visitInfoList(sequence, mAttribs);
263 break;
264 case EvqUniform:
265 visitInfoList(sequence, mUniforms);
266 break;
267 default:
268 visitInfoList(sequence, mVaryings);
269 break;
270 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400271
Jamie Madill4667c452014-07-08 15:02:36 -0400272 if (!sequence.empty())
273 {
274 visitChildren = false;
275 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000276 }
Jamie Madill4667c452014-07-08 15:02:36 -0400277 break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000278 }
Jamie Madill4667c452014-07-08 15:02:36 -0400279 default: break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000280 }
281
282 return visitChildren;
283}