blob: b712574c5ff41b09daa193c341a32499500e3d3d [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
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;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000065 if (type.isArray()) {
66 varInfo.name = (name + "[0]").c_str();
zmo@google.comfd747b82011-04-23 01:30:07 +000067 varInfo.mappedName = (mappedName + "[0]").c_str();
Jamie Madilla718c1e2014-07-02 15:31:22 -040068 varInfo.arraySize = type.getArraySize();
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000069 } else {
70 varInfo.name = name.c_str();
zmo@google.comfd747b82011-04-23 01:30:07 +000071 varInfo.mappedName = mappedName.c_str();
Jamie Madilla718c1e2014-07-02 15:31:22 -040072 varInfo.arraySize = 0;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000073 }
Jamie Madilla718c1e2014-07-02 15:31:22 -040074 varInfo.precision = sh::GLVariablePrecision(type);
Jamie Madillaa72d782014-07-02 15:31:19 -040075 varInfo.type = sh::GLVariableType(type);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000076 infoList.push_back(varInfo);
77}
78
Jamie Madilla718c1e2014-07-02 15:31:22 -040079template <class VarT>
80void getUserDefinedVariableInfo(const TType &type,
81 const TString &name,
82 const TString &mappedName,
83 std::vector<VarT> &infoList,
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000084 ShHashFunction64 hashFunction)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000085{
Jamie Madill98493dd2013-07-08 14:39:03 -040086 ASSERT(type.getBasicType() == EbtStruct || type.isInterfaceBlock());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000087
Dan Glastonburyb66feb32014-05-14 15:38:55 +100088 const TFieldList& fields = type.isInterfaceBlock() ?
89 type.getInterfaceBlock()->fields() :
90 type.getStruct()->fields();
Jamie Madill98493dd2013-07-08 14:39:03 -040091 for (size_t i = 0; i < fields.size(); ++i) {
92 const TType& fieldType = *(fields[i]->type());
93 const TString& fieldName = fields[i]->name();
94 getVariableInfo(fieldType,
95 name + "." + fieldName,
96 mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000097 infoList,
98 hashFunction);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000099 }
100}
101
Jamie Madilla718c1e2014-07-02 15:31:22 -0400102template <class VarT>
103VarT* findVariable(const TType &type,
104 const TString &name,
105 std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400106{
107 // TODO(zmo): optimize this function.
108 TString myName = name;
109 if (type.isArray())
110 myName += "[0]";
Jamie Madilla718c1e2014-07-02 15:31:22 -0400111 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400112 {
Jamie Madilla718c1e2014-07-02 15:31:22 -0400113 if ((*infoList)[ii].name.c_str() == myName)
114 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400115 }
116 return NULL;
117}
118
119} // namespace anonymous
120
Jamie Madilla718c1e2014-07-02 15:31:22 -0400121CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
122 std::vector<sh::Uniform> *uniforms,
123 std::vector<sh::Varying> *varyings,
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400124 ShHashFunction64 hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000125 : mAttribs(attribs),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000126 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400127 mVaryings(varyings),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400128 mPointCoordAdded(false),
129 mFrontFacingAdded(false),
130 mFragCoordAdded(false),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000131 mHashFunction(hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000132{
133}
134
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400135// We want to check whether a uniform/varying is statically used
136// because we only count the used ones in packing computing.
137// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
138// toward varying counting if they are statically used in a fragment
139// shader.
140void CollectVariables::visitSymbol(TIntermSymbol* symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000141{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400142 ASSERT(symbol != NULL);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400143 sh::ShaderVariable *var = NULL;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400144 switch (symbol->getQualifier())
145 {
Jamie Madilla718c1e2014-07-02 15:31:22 -0400146 case EvqVaryingOut:
147 case EvqInvariantVaryingOut:
148 case EvqVaryingIn:
149 case EvqInvariantVaryingIn:
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400150 var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
151 break;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400152 case EvqUniform:
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400153 var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
154 break;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400155 case EvqFragCoord:
156 if (!mFragCoordAdded)
157 {
158 sh::Varying info;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400159 info.name = "gl_FragCoord";
160 info.mappedName = "gl_FragCoord";
Jamie Madill183bde52014-07-02 15:31:19 -0400161 info.type = GL_FLOAT_VEC4;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400162 info.arraySize = 0;
163 info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400164 info.staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400165 mVaryings->push_back(info);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400166 mFragCoordAdded = true;
167 }
168 return;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400169 case EvqFrontFacing:
170 if (!mFrontFacingAdded)
171 {
172 sh::Varying info;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400173 info.name = "gl_FrontFacing";
174 info.mappedName = "gl_FrontFacing";
Jamie Madill183bde52014-07-02 15:31:19 -0400175 info.type = GL_BOOL;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400176 info.arraySize = 0;
177 info.precision = GL_NONE;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400178 info.staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400179 mVaryings->push_back(info);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400180 mFrontFacingAdded = true;
181 }
182 return;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400183 case EvqPointCoord:
184 if (!mPointCoordAdded)
185 {
186 sh::Varying info;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400187 info.name = "gl_PointCoord";
188 info.mappedName = "gl_PointCoord";
Jamie Madill183bde52014-07-02 15:31:19 -0400189 info.type = GL_FLOAT_VEC2;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400190 info.arraySize = 0;
191 info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400192 info.staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400193 mVaryings->push_back(info);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400194 mPointCoordAdded = true;
195 }
196 return;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400197 default:
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400198 break;
199 }
200 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400201 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400202 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400203 }
204}
205
206template <typename VarT>
207void CollectVariables::visitInfoList(const TIntermSequence& sequence, std::vector<VarT> *infoList) const
208{
209 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
210 {
211 const TIntermSymbol* variable = sequence[seqIndex]->getAsSymbolNode();
212 // The only case in which the sequence will not contain a
213 // TIntermSymbol node is initialization. It will contain a
214 // TInterBinary node in that case. Since attributes, uniforms,
215 // and varyings cannot be initialized in a shader, we must have
216 // only TIntermSymbol nodes in the sequence.
217 ASSERT(variable != NULL);
218 TString processedSymbol;
219 if (mHashFunction == NULL)
220 processedSymbol = variable->getSymbol();
221 else
222 processedSymbol = TIntermTraverser::hash(variable->getSymbol(), mHashFunction);
223 getVariableInfo(variable->getType(),
224 variable->getSymbol(),
225 processedSymbol,
226 *infoList,
227 mHashFunction);
228 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000229}
230
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400231bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000232{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400233 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000234
235 switch (node->getOp())
236 {
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000237 case EOpDeclaration: {
238 const TIntermSequence& sequence = node->getSequence();
alokp@chromium.org10e6e9e2010-09-27 21:03:45 +0000239 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400240 if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform ||
241 qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
242 qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000243 {
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400244 switch (qualifier)
245 {
246 case EvqAttribute:
247 case EvqVertexIn:
Jamie Madilla718c1e2014-07-02 15:31:22 -0400248 visitInfoList(sequence, mAttribs);
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400249 break;
250 case EvqUniform:
Jamie Madilla718c1e2014-07-02 15:31:22 -0400251 visitInfoList(sequence, mUniforms);
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400252 break;
253 default:
Jamie Madilla718c1e2014-07-02 15:31:22 -0400254 visitInfoList(sequence, mVaryings);
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400255 break;
256 }
257
Jamie Madilla718c1e2014-07-02 15:31:22 -0400258 if (!sequence.empty())
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000259 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400260 visitChildren = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000261 }
262 }
263 break;
264 }
265 default: break;
266 }
267
268 return visitChildren;
269}