blob: 57a5cd7bdf82c37db86be025a6c84627df1bcf2a [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
Jamie Madilla718c1e2014-07-02 15:31:22 -040011template <typename VarT>
Jamie Madill23a8a432014-07-09 13:27:42 -040012static void ExpandUserDefinedVariable(const VarT &variable,
13 const std::string &name,
14 const std::string &mappedName,
15 bool markStaticUse,
16 std::vector<VarT> *expanded);
Zhenyao Mod2d340b2013-09-23 14:57:05 -040017
18// Returns info for an attribute, uniform, or varying.
Jamie Madilla718c1e2014-07-02 15:31:22 -040019template <typename VarT>
Jamie Madill23a8a432014-07-09 13:27:42 -040020static void ExpandVariable(const VarT &variable,
21 const std::string &name,
22 const std::string &mappedName,
23 bool markStaticUse,
24 std::vector<VarT> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000025{
Jamie Madill23a8a432014-07-09 13:27:42 -040026 if (variable.isStruct())
Jamie Madill4667c452014-07-08 15:02:36 -040027 {
Jamie Madill23a8a432014-07-09 13:27:42 -040028 if (variable.isArray())
29 {
30 for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++)
31 {
32 std::string lname = name + ArrayString(elementIndex);
33 std::string lmappedName = mappedName + ArrayString(elementIndex);
34 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
35 }
36 }
37 else
38 {
39 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
40 }
Jamie Madill4667c452014-07-08 15:02:36 -040041 }
42 else
43 {
Jamie Madill23a8a432014-07-09 13:27:42 -040044 VarT expandedVar = variable;
45
46 expandedVar.name = name;
47 expandedVar.mappedName = mappedName;
48
49 // Mark all expanded fields as used if the parent is used
50 if (markStaticUse)
51 {
52 expandedVar.staticUse = true;
53 }
54
55 if (expandedVar.isArray())
56 {
57 expandedVar.name += "[0]";
58 expandedVar.mappedName += "[0]";
59 }
60
61 expanded->push_back(expandedVar);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000062 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000063}
64
Jamie Madilla718c1e2014-07-02 15:31:22 -040065template <class VarT>
Jamie Madill23a8a432014-07-09 13:27:42 -040066static void ExpandUserDefinedVariable(const VarT &variable,
67 const std::string &name,
68 const std::string &mappedName,
69 bool markStaticUse,
70 std::vector<VarT> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000071{
Jamie Madill23a8a432014-07-09 13:27:42 -040072 ASSERT(variable.isStruct());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000073
Jamie Madill23a8a432014-07-09 13:27:42 -040074 const std::vector<VarT> &fields = variable.fields;
75
76 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
Jamie Madill4667c452014-07-08 15:02:36 -040077 {
Jamie Madill23a8a432014-07-09 13:27:42 -040078 const VarT &field = fields[fieldIndex];
79 ExpandVariable(field,
80 name + "." + field.name,
81 mappedName + "." + field.mappedName,
82 markStaticUse,
83 expanded);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000084 }
85}
86
Jamie Madilla718c1e2014-07-02 15:31:22 -040087template <class VarT>
Jamie Madill23a8a432014-07-09 13:27:42 -040088static VarT* findVariable(const TString &name,
89 std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040090{
91 // TODO(zmo): optimize this function.
Jamie Madilla718c1e2014-07-02 15:31:22 -040092 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040093 {
Jamie Madill23a8a432014-07-09 13:27:42 -040094 if ((*infoList)[ii].name.c_str() == name)
Jamie Madilla718c1e2014-07-02 15:31:22 -040095 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -040096 }
97 return NULL;
98}
99
Jamie Madilla718c1e2014-07-02 15:31:22 -0400100CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
101 std::vector<sh::Uniform> *uniforms,
102 std::vector<sh::Varying> *varyings,
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400103 ShHashFunction64 hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000104 : mAttribs(attribs),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000105 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400106 mVaryings(varyings),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400107 mPointCoordAdded(false),
108 mFrontFacingAdded(false),
109 mFragCoordAdded(false),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000110 mHashFunction(hashFunction)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000111{
112}
113
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400114// We want to check whether a uniform/varying is statically used
115// because we only count the used ones in packing computing.
116// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
117// toward varying counting if they are statically used in a fragment
118// shader.
Jamie Madill4667c452014-07-08 15:02:36 -0400119void CollectVariables::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000120{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400121 ASSERT(symbol != NULL);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400122 sh::ShaderVariable *var = NULL;
Jamie Madill4667c452014-07-08 15:02:36 -0400123
124 if (sh::IsVarying(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400125 {
Jamie Madill23a8a432014-07-09 13:27:42 -0400126 var = findVariable(symbol->getSymbol(), mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400127 }
128 else
129 {
130 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400131 {
Jamie Madill4667c452014-07-08 15:02:36 -0400132 case EvqUniform:
Jamie Madill23a8a432014-07-09 13:27:42 -0400133 var = findVariable(symbol->getSymbol(), mUniforms);
Jamie Madill4667c452014-07-08 15:02:36 -0400134 break;
135 case EvqFragCoord:
136 if (!mFragCoordAdded)
137 {
138 sh::Varying info;
139 info.name = "gl_FragCoord";
140 info.mappedName = "gl_FragCoord";
141 info.type = GL_FLOAT_VEC4;
142 info.arraySize = 0;
143 info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
144 info.staticUse = true;
145 mVaryings->push_back(info);
146 mFragCoordAdded = true;
147 }
148 return;
149 case EvqFrontFacing:
150 if (!mFrontFacingAdded)
151 {
152 sh::Varying info;
153 info.name = "gl_FrontFacing";
154 info.mappedName = "gl_FrontFacing";
155 info.type = GL_BOOL;
156 info.arraySize = 0;
157 info.precision = GL_NONE;
158 info.staticUse = true;
159 mVaryings->push_back(info);
160 mFrontFacingAdded = true;
161 }
162 return;
163 case EvqPointCoord:
164 if (!mPointCoordAdded)
165 {
166 sh::Varying info;
167 info.name = "gl_PointCoord";
168 info.mappedName = "gl_PointCoord";
169 info.type = GL_FLOAT_VEC2;
170 info.arraySize = 0;
171 info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
172 info.staticUse = true;
173 mVaryings->push_back(info);
174 mPointCoordAdded = true;
175 }
176 return;
177 default:
178 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400179 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400180 }
181 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400182 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400183 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400184 }
185}
186
187template <typename VarT>
Jamie Madill23a8a432014-07-09 13:27:42 -0400188class NameHashingTraverser : public sh::GetVariableTraverser<VarT>
189{
190 public:
191 NameHashingTraverser(std::vector<VarT> *output, ShHashFunction64 hashFunction)
192 : sh::GetVariableTraverser<VarT>(output),
193 mHashFunction(hashFunction)
194 {}
195
196 private:
197 void visitVariable(VarT *variable)
198 {
199 TString stringName = TString(variable->name.c_str());
200 variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
201 }
202
203 ShHashFunction64 mHashFunction;
204};
205
206// Attributes, which cannot have struct fields, are a special case
207template <>
208void CollectVariables::visitVariable(const TIntermSymbol *variable,
209 std::vector<sh::Attribute> *infoList) const
210{
211 ASSERT(variable);
212 const TType &type = variable->getType();
213 ASSERT(!type.getStruct());
214
215 sh::Attribute attribute;
216
217 attribute.type = sh::GLVariableType(type);
218 attribute.precision = sh::GLVariablePrecision(type);
219 attribute.name = variable->getSymbol().c_str();
220 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
221 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
222 attribute.location = variable->getType().getLayoutQualifier().location;
223
224 infoList->push_back(attribute);
225}
226
227template <typename VarT>
Jamie Madill4667c452014-07-08 15:02:36 -0400228void CollectVariables::visitVariable(const TIntermSymbol *variable,
229 std::vector<VarT> *infoList) const
230{
Jamie Madill23a8a432014-07-09 13:27:42 -0400231 NameHashingTraverser<VarT> traverser(infoList, mHashFunction);
232 traverser.traverse(variable->getType(), variable->getSymbol());
Jamie Madill4667c452014-07-08 15:02:36 -0400233}
234
235template <typename VarT>
236void CollectVariables::visitInfoList(const TIntermSequence &sequence,
237 std::vector<VarT> *infoList) const
Jamie Madilla718c1e2014-07-02 15:31:22 -0400238{
239 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
240 {
Jamie Madill4667c452014-07-08 15:02:36 -0400241 const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
Jamie Madilla718c1e2014-07-02 15:31:22 -0400242 // The only case in which the sequence will not contain a
243 // TIntermSymbol node is initialization. It will contain a
244 // TInterBinary node in that case. Since attributes, uniforms,
245 // and varyings cannot be initialized in a shader, we must have
246 // only TIntermSymbol nodes in the sequence.
247 ASSERT(variable != NULL);
Jamie Madill4667c452014-07-08 15:02:36 -0400248 visitVariable(variable, infoList);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400249 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000250}
251
Jamie Madill4667c452014-07-08 15:02:36 -0400252bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000253{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400254 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000255
256 switch (node->getOp())
257 {
Jamie Madill4667c452014-07-08 15:02:36 -0400258 case EOpDeclaration:
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000259 {
Jamie Madill4667c452014-07-08 15:02:36 -0400260 const TIntermSequence &sequence = node->getSequence();
261 TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
262 if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform ||
263 sh::IsVarying(qualifier))
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400264 {
Jamie Madill4667c452014-07-08 15:02:36 -0400265 switch (qualifier)
266 {
267 case EvqAttribute:
268 case EvqVertexIn:
269 visitInfoList(sequence, mAttribs);
270 break;
271 case EvqUniform:
272 visitInfoList(sequence, mUniforms);
273 break;
274 default:
275 visitInfoList(sequence, mVaryings);
276 break;
277 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400278
Jamie Madill4667c452014-07-08 15:02:36 -0400279 if (!sequence.empty())
280 {
281 visitChildren = false;
282 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000283 }
Jamie Madill4667c452014-07-08 15:02:36 -0400284 break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000285 }
Jamie Madill4667c452014-07-08 15:02:36 -0400286 default: break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000287 }
288
289 return visitChildren;
290}
Jamie Madill23a8a432014-07-09 13:27:42 -0400291
292template <typename VarT>
293void ExpandVariables(const std::vector<VarT> &compact, std::vector<VarT> *expanded)
294{
295 for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
296 {
297 const VarT &variable = compact[variableIndex];
298 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
299 }
300}
301
302template void ExpandVariables(const std::vector<sh::Uniform> &, std::vector<sh::Uniform> *);
303template void ExpandVariables(const std::vector<sh::Varying> &, std::vector<sh::Varying> *);