blob: 611c1512d1f217ee30a6c4b7f94a3bcb32e77be2 [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"
Zhenyao Mo94ac7b72014-10-15 18:22:08 -07008#include "compiler/translator/SymbolTable.h"
Geoff Lang17732822013-08-29 13:46:49 -04009#include "compiler/translator/VariableInfo.h"
Jamie Madillaa72d782014-07-02 15:31:19 -040010#include "compiler/translator/util.h"
Jamie Madilld5512cd2014-07-10 17:50:08 -040011#include "common/utilities.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000012
Jamie Madilla2fbb842014-09-03 09:40:47 -040013namespace sh
14{
15
Jamie Madill54ad4f82014-09-03 09:40:46 -040016namespace
17{
Zhenyao Mod2d340b2013-09-23 14:57:05 -040018
Jamie Madilla2fbb842014-09-03 09:40:47 -040019BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
Jamie Madill54ad4f82014-09-03 09:40:46 -040020{
21 switch (blockStorage)
22 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040023 case EbsPacked: return BLOCKLAYOUT_PACKED;
24 case EbsShared: return BLOCKLAYOUT_SHARED;
25 case EbsStd140: return BLOCKLAYOUT_STANDARD;
26 default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
Jamie Madill54ad4f82014-09-03 09:40:46 -040027 }
28}
29
Jamie Madilla2fbb842014-09-03 09:40:47 -040030void ExpandUserDefinedVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040031 const std::string &name,
32 const std::string &mappedName,
33 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040034 std::vector<ShaderVariable> *expanded);
Jamie Madill54ad4f82014-09-03 09:40:46 -040035
Jamie Madilla2fbb842014-09-03 09:40:47 -040036void ExpandVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040037 const std::string &name,
38 const std::string &mappedName,
39 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040040 std::vector<ShaderVariable> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000041{
Jamie Madill23a8a432014-07-09 13:27:42 -040042 if (variable.isStruct())
Jamie Madill4667c452014-07-08 15:02:36 -040043 {
Jamie Madill23a8a432014-07-09 13:27:42 -040044 if (variable.isArray())
45 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070046 for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
47 elementIndex++)
Jamie Madill23a8a432014-07-09 13:27:42 -040048 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040049 std::string lname = name + ::ArrayString(elementIndex);
50 std::string lmappedName = mappedName + ::ArrayString(elementIndex);
Jamie Madill23a8a432014-07-09 13:27:42 -040051 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
52 }
53 }
54 else
55 {
56 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
57 }
Jamie Madill4667c452014-07-08 15:02:36 -040058 }
59 else
60 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040061 ShaderVariable expandedVar = variable;
Jamie Madill23a8a432014-07-09 13:27:42 -040062
63 expandedVar.name = name;
64 expandedVar.mappedName = mappedName;
65
66 // Mark all expanded fields as used if the parent is used
67 if (markStaticUse)
68 {
69 expandedVar.staticUse = true;
70 }
71
72 if (expandedVar.isArray())
73 {
74 expandedVar.name += "[0]";
75 expandedVar.mappedName += "[0]";
76 }
77
78 expanded->push_back(expandedVar);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000079 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000080}
81
Jamie Madilla2fbb842014-09-03 09:40:47 -040082void ExpandUserDefinedVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040083 const std::string &name,
84 const std::string &mappedName,
85 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040086 std::vector<ShaderVariable> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000087{
Jamie Madill23a8a432014-07-09 13:27:42 -040088 ASSERT(variable.isStruct());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000089
Jamie Madilla2fbb842014-09-03 09:40:47 -040090 const std::vector<ShaderVariable> &fields = variable.fields;
Jamie Madill23a8a432014-07-09 13:27:42 -040091
92 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
Jamie Madill4667c452014-07-08 15:02:36 -040093 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040094 const ShaderVariable &field = fields[fieldIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -040095 ExpandVariable(field,
96 name + "." + field.name,
97 mappedName + "." + field.mappedName,
98 markStaticUse,
99 expanded);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000100 }
101}
102
Jamie Madilla718c1e2014-07-02 15:31:22 -0400103template <class VarT>
Jamie Madill54ad4f82014-09-03 09:40:46 -0400104VarT *FindVariable(const TString &name,
105 std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400106{
107 // TODO(zmo): optimize this function.
Jamie Madilla718c1e2014-07-02 15:31:22 -0400108 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400109 {
Jamie Madill23a8a432014-07-09 13:27:42 -0400110 if ((*infoList)[ii].name.c_str() == name)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400111 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400112 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400113
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400114 return NULL;
115}
116
Jamie Madill54ad4f82014-09-03 09:40:46 -0400117}
118
Jamie Madilla718c1e2014-07-02 15:31:22 -0400119CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
Jamie Madilla0a9e122015-09-02 15:54:30 -0400120 std::vector<sh::OutputVariable> *outputVariables,
Jamie Madilla718c1e2014-07-02 15:31:22 -0400121 std::vector<sh::Uniform> *uniforms,
122 std::vector<sh::Varying> *varyings,
Jamie Madilld5512cd2014-07-10 17:50:08 -0400123 std::vector<sh::InterfaceBlock> *interfaceBlocks,
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700124 ShHashFunction64 hashFunction,
125 const TSymbolTable &symbolTable)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300126 : TIntermTraverser(true, false, false),
127 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400128 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000129 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400130 mVaryings(varyings),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400131 mInterfaceBlocks(interfaceBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400132 mDepthRangeAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400133 mPointCoordAdded(false),
134 mFrontFacingAdded(false),
135 mFragCoordAdded(false),
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000136 mInstanceIDAdded(false),
Corentin Wallezb076add2016-01-11 16:45:46 -0500137 mVertexIDAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700138 mPositionAdded(false),
139 mPointSizeAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100140 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300141 mFragColorAdded(false),
142 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300143 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300144 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300145 mSecondaryFragColorEXTAdded(false),
146 mSecondaryFragDataEXTAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700147 mHashFunction(hashFunction),
148 mSymbolTable(symbolTable)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000149{
150}
151
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400152// We want to check whether a uniform/varying is statically used
153// because we only count the used ones in packing computing.
154// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
155// toward varying counting if they are statically used in a fragment
156// shader.
Jamie Madill4667c452014-07-08 15:02:36 -0400157void CollectVariables::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000158{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400159 ASSERT(symbol != NULL);
Jamie Madilla2fbb842014-09-03 09:40:47 -0400160 ShaderVariable *var = NULL;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400161 const TString &symbolName = symbol->getSymbol();
Jamie Madill4667c452014-07-08 15:02:36 -0400162
Jamie Madilla2fbb842014-09-03 09:40:47 -0400163 if (IsVarying(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400164 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400165 var = FindVariable(symbolName, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400166 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400167 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
168 {
169 UNREACHABLE();
170 }
Jamie Madill55def582015-05-04 11:24:57 -0400171 else if (symbolName == "gl_DepthRange")
172 {
173 ASSERT(symbol->getQualifier() == EvqUniform);
174
175 if (!mDepthRangeAdded)
176 {
177 Uniform info;
178 const char kName[] = "gl_DepthRange";
179 info.name = kName;
180 info.mappedName = kName;
181 info.type = GL_STRUCT_ANGLEX;
182 info.arraySize = 0;
183 info.precision = GL_NONE;
184 info.staticUse = true;
185
186 ShaderVariable nearInfo;
187 const char kNearName[] = "near";
188 nearInfo.name = kNearName;
189 nearInfo.mappedName = kNearName;
190 nearInfo.type = GL_FLOAT;
191 nearInfo.arraySize = 0;
192 nearInfo.precision = GL_HIGH_FLOAT;
193 nearInfo.staticUse = true;
194
195 ShaderVariable farInfo;
196 const char kFarName[] = "far";
197 farInfo.name = kFarName;
198 farInfo.mappedName = kFarName;
199 farInfo.type = GL_FLOAT;
200 farInfo.arraySize = 0;
201 farInfo.precision = GL_HIGH_FLOAT;
202 farInfo.staticUse = true;
203
204 ShaderVariable diffInfo;
205 const char kDiffName[] = "diff";
206 diffInfo.name = kDiffName;
207 diffInfo.mappedName = kDiffName;
208 diffInfo.type = GL_FLOAT;
209 diffInfo.arraySize = 0;
210 diffInfo.precision = GL_HIGH_FLOAT;
211 diffInfo.staticUse = true;
212
213 info.fields.push_back(nearInfo);
214 info.fields.push_back(farInfo);
215 info.fields.push_back(diffInfo);
216
217 mUniforms->push_back(info);
218 mDepthRangeAdded = true;
219 }
220 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400221 else
Jamie Madill4667c452014-07-08 15:02:36 -0400222 {
223 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400224 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400225 case EvqAttribute:
226 case EvqVertexIn:
227 var = FindVariable(symbolName, mAttribs);
228 break;
229 case EvqFragmentOut:
230 var = FindVariable(symbolName, mOutputVariables);
231 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400232 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400233 {
234 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
235 if (interfaceBlock)
236 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400237 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400238 ASSERT(namedBlock);
239 var = FindVariable(symbolName, &namedBlock->fields);
240
241 // Set static use on the parent interface block here
242 namedBlock->staticUse = true;
243 }
244 else
245 {
246 var = FindVariable(symbolName, mUniforms);
247 }
248
249 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400250 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400251 }
Jamie Madill4667c452014-07-08 15:02:36 -0400252 break;
253 case EvqFragCoord:
254 if (!mFragCoordAdded)
255 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400256 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700257 const char kName[] = "gl_FragCoord";
258 info.name = kName;
259 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400260 info.type = GL_FLOAT_VEC4;
261 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700262 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400263 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700264 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400265 mVaryings->push_back(info);
266 mFragCoordAdded = true;
267 }
268 return;
269 case EvqFrontFacing:
270 if (!mFrontFacingAdded)
271 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400272 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700273 const char kName[] = "gl_FrontFacing";
274 info.name = kName;
275 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400276 info.type = GL_BOOL;
277 info.arraySize = 0;
278 info.precision = GL_NONE;
279 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700280 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400281 mVaryings->push_back(info);
282 mFrontFacingAdded = true;
283 }
284 return;
285 case EvqPointCoord:
286 if (!mPointCoordAdded)
287 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400288 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700289 const char kName[] = "gl_PointCoord";
290 info.name = kName;
291 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400292 info.type = GL_FLOAT_VEC2;
293 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700294 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400295 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700296 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400297 mVaryings->push_back(info);
298 mPointCoordAdded = true;
299 }
300 return;
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000301 case EvqInstanceID:
302 if (!mInstanceIDAdded)
303 {
304 Attribute info;
305 const char kName[] = "gl_InstanceID";
306 info.name = kName;
307 info.mappedName = kName;
308 info.type = GL_INT;
309 info.arraySize = 0;
310 info.precision = GL_HIGH_INT; // Defined by spec.
311 info.staticUse = true;
312 info.location = -1;
313 mAttribs->push_back(info);
314 mInstanceIDAdded = true;
315 }
316 return;
Corentin Wallezb076add2016-01-11 16:45:46 -0500317 case EvqVertexID:
318 if (!mVertexIDAdded)
319 {
320 Attribute info;
321 const char kName[] = "gl_VertexID";
322 info.name = kName;
323 info.mappedName = kName;
324 info.type = GL_INT;
325 info.arraySize = 0;
326 info.precision = GL_HIGH_INT; // Defined by spec.
327 info.staticUse = true;
328 info.location = -1;
329 mAttribs->push_back(info);
330 mVertexIDAdded = true;
331 }
332 return;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700333 case EvqPosition:
334 if (!mPositionAdded)
335 {
336 Varying info;
337 const char kName[] = "gl_Position";
338 info.name = kName;
339 info.mappedName = kName;
340 info.type = GL_FLOAT_VEC4;
341 info.arraySize = 0;
342 info.precision = GL_HIGH_FLOAT; // Defined by spec.
343 info.staticUse = true;
344 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
345 mVaryings->push_back(info);
346 mPositionAdded = true;
347 }
348 return;
349 case EvqPointSize:
350 if (!mPointSizeAdded)
351 {
352 Varying info;
353 const char kName[] = "gl_PointSize";
354 info.name = kName;
355 info.mappedName = kName;
356 info.type = GL_FLOAT;
357 info.arraySize = 0;
358 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
359 info.staticUse = true;
360 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
361 mVaryings->push_back(info);
362 mPointSizeAdded = true;
363 }
364 return;
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100365 case EvqLastFragData:
366 if (!mLastFragDataAdded)
367 {
368 Varying info;
369 const char kName[] = "gl_LastFragData";
370 info.name = kName;
371 info.mappedName = kName;
372 info.type = GL_FLOAT_VEC4;
373 info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
374 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
375 info.staticUse = true;
376 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
377 mVaryings->push_back(info);
378 mLastFragDataAdded = true;
379 }
380 return;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300381 case EvqFragColor:
382 if (!mFragColorAdded)
383 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400384 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300385 const char kName[] = "gl_FragColor";
386 info.name = kName;
387 info.mappedName = kName;
388 info.type = GL_FLOAT_VEC4;
389 info.arraySize = 0;
390 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
391 info.staticUse = true;
392 mOutputVariables->push_back(info);
393 mFragColorAdded = true;
394 }
395 return;
396 case EvqFragData:
397 if (!mFragDataAdded)
398 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400399 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300400 const char kName[] = "gl_FragData";
401 info.name = kName;
402 info.mappedName = kName;
403 info.type = GL_FLOAT_VEC4;
404 info.arraySize = static_cast<const TVariable *>(
405 mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
406 ->getConstPointer()
407 ->getIConst();
408 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
409 info.staticUse = true;
410 mOutputVariables->push_back(info);
411 mFragDataAdded = true;
412 }
413 return;
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300414 case EvqFragDepthEXT:
415 if (!mFragDepthEXTAdded)
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300416 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400417 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300418 const char kName[] = "gl_FragDepthEXT";
419 info.name = kName;
420 info.mappedName = kName;
421 info.type = GL_FLOAT;
422 info.arraySize = 0;
423 info.precision =
424 GLVariablePrecision(static_cast<const TVariable *>(
425 mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
426 ->getType());
427 info.staticUse = true;
428 mOutputVariables->push_back(info);
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300429 mFragDepthEXTAdded = true;
430 }
431 return;
432 case EvqFragDepth:
433 if (!mFragDepthAdded)
434 {
435 OutputVariable info;
436 const char kName[] = "gl_FragDepth";
437 info.name = kName;
438 info.mappedName = kName;
439 info.type = GL_FLOAT;
440 info.arraySize = 0;
441 info.precision = GL_HIGH_FLOAT;
442 info.staticUse = true;
443 mOutputVariables->push_back(info);
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300444 mFragDepthAdded = true;
445 }
446 return;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300447 case EvqSecondaryFragColorEXT:
448 if (!mSecondaryFragColorEXTAdded)
449 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400450 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300451 const char kName[] = "gl_SecondaryFragColorEXT";
452 info.name = kName;
453 info.mappedName = kName;
454 info.type = GL_FLOAT_VEC4;
455 info.arraySize = 0;
456 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
457 info.staticUse = true;
458 mOutputVariables->push_back(info);
459 mSecondaryFragColorEXTAdded = true;
460 }
461 return;
462 case EvqSecondaryFragDataEXT:
463 if (!mSecondaryFragDataEXTAdded)
464 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400465 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300466 const char kName[] = "gl_SecondaryFragDataEXT";
467 info.name = kName;
468 info.mappedName = kName;
469 info.type = GL_FLOAT_VEC4;
470
471 const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
472 mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
473 info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
474 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
475 info.staticUse = true;
476 mOutputVariables->push_back(info);
477 mSecondaryFragDataEXTAdded = true;
478 }
479 return;
Jamie Madill4667c452014-07-08 15:02:36 -0400480 default:
481 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400482 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400483 }
484 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400485 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400486 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400487 }
488}
489
Jamie Madilla2fbb842014-09-03 09:40:47 -0400490class NameHashingTraverser : public GetVariableTraverser
Jamie Madill23a8a432014-07-09 13:27:42 -0400491{
492 public:
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700493 NameHashingTraverser(ShHashFunction64 hashFunction,
494 const TSymbolTable &symbolTable)
495 : GetVariableTraverser(symbolTable),
496 mHashFunction(hashFunction)
Jamie Madill23a8a432014-07-09 13:27:42 -0400497 {}
498
499 private:
Corentin Walleze5a1f272015-08-21 02:58:25 +0200500 void visitVariable(ShaderVariable *variable) override
Jamie Madill23a8a432014-07-09 13:27:42 -0400501 {
502 TString stringName = TString(variable->name.c_str());
503 variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
504 }
505
506 ShHashFunction64 mHashFunction;
507};
508
509// Attributes, which cannot have struct fields, are a special case
510template <>
511void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400512 std::vector<Attribute> *infoList) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400513{
514 ASSERT(variable);
515 const TType &type = variable->getType();
516 ASSERT(!type.getStruct());
517
Jamie Madilla2fbb842014-09-03 09:40:47 -0400518 Attribute attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400519
Jamie Madilla2fbb842014-09-03 09:40:47 -0400520 attribute.type = GLVariableType(type);
521 attribute.precision = GLVariablePrecision(type);
Jamie Madill23a8a432014-07-09 13:27:42 -0400522 attribute.name = variable->getSymbol().c_str();
523 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
524 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
525 attribute.location = variable->getType().getLayoutQualifier().location;
526
527 infoList->push_back(attribute);
528}
529
Jamie Madilld5512cd2014-07-10 17:50:08 -0400530template <>
531void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla0a9e122015-09-02 15:54:30 -0400532 std::vector<OutputVariable> *infoList) const
533{
534 ASSERT(variable);
535 const TType &type = variable->getType();
536 ASSERT(!type.getStruct());
537
538 OutputVariable attribute;
539
540 attribute.type = GLVariableType(type);
541 attribute.precision = GLVariablePrecision(type);
542 attribute.name = variable->getSymbol().c_str();
543 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
544 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
545 attribute.location = variable->getType().getLayoutQualifier().location;
546
547 infoList->push_back(attribute);
548}
549
550template <>
551void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400552 std::vector<InterfaceBlock> *infoList) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400553{
Jamie Madilla2fbb842014-09-03 09:40:47 -0400554 InterfaceBlock interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400555 const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400556 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400557
558 interfaceBlock.name = blockType->name().c_str();
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500559 interfaceBlock.mappedName =
560 TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
Jamie Madill42bcf322014-08-25 16:20:46 -0400561 interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
Jamie Madilld5512cd2014-07-10 17:50:08 -0400562 interfaceBlock.arraySize = variable->getArraySize();
Jamie Madill42bcf322014-08-25 16:20:46 -0400563 interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400564 interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400565
Jamie Madilla6f267f2014-08-27 11:44:15 -0400566 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500567 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400568 {
Jamie Madill39046162016-02-08 15:05:17 -0500569 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400570
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500571 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill39046162016-02-08 15:05:17 -0500572 traverser.traverse(fieldType, field->name(), &interfaceBlock.fields);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400573
574 interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
575 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400576
577 infoList->push_back(interfaceBlock);
578}
579
Jamie Madill23a8a432014-07-09 13:27:42 -0400580template <typename VarT>
Jamie Madill4667c452014-07-08 15:02:36 -0400581void CollectVariables::visitVariable(const TIntermSymbol *variable,
582 std::vector<VarT> *infoList) const
583{
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700584 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill42bcf322014-08-25 16:20:46 -0400585 traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
Jamie Madill4667c452014-07-08 15:02:36 -0400586}
587
588template <typename VarT>
589void CollectVariables::visitInfoList(const TIntermSequence &sequence,
590 std::vector<VarT> *infoList) const
Jamie Madilla718c1e2014-07-02 15:31:22 -0400591{
592 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
593 {
Jamie Madill4667c452014-07-08 15:02:36 -0400594 const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
Jamie Madilla718c1e2014-07-02 15:31:22 -0400595 // The only case in which the sequence will not contain a
596 // TIntermSymbol node is initialization. It will contain a
597 // TInterBinary node in that case. Since attributes, uniforms,
598 // and varyings cannot be initialized in a shader, we must have
599 // only TIntermSymbol nodes in the sequence.
600 ASSERT(variable != NULL);
Jamie Madill4667c452014-07-08 15:02:36 -0400601 visitVariable(variable, infoList);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400602 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000603}
604
Jamie Madill4667c452014-07-08 15:02:36 -0400605bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000606{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400607 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000608
609 switch (node->getOp())
610 {
Jamie Madill4667c452014-07-08 15:02:36 -0400611 case EOpDeclaration:
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000612 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700613 const TIntermSequence &sequence = *(node->getSequence());
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400614 ASSERT(!sequence.empty());
615
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700616 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400617 TQualifier qualifier = typedNode.getQualifier();
618
619 if (typedNode.getBasicType() == EbtInterfaceBlock)
620 {
621 visitInfoList(sequence, mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400622 visitChildren = false;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400623 }
624 else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
625 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
Jamie Madilla2fbb842014-09-03 09:40:47 -0400626 IsVarying(qualifier))
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400627 {
Jamie Madill4667c452014-07-08 15:02:36 -0400628 switch (qualifier)
629 {
630 case EvqAttribute:
631 case EvqVertexIn:
632 visitInfoList(sequence, mAttribs);
633 break;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400634 case EvqFragmentOut:
635 visitInfoList(sequence, mOutputVariables);
636 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400637 case EvqUniform:
638 visitInfoList(sequence, mUniforms);
639 break;
640 default:
Jamie Madill3b5c2da2014-08-19 15:23:32 -0400641 visitInfoList(sequence, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400642 break;
643 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400644
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400645 visitChildren = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000646 }
Jamie Madill4667c452014-07-08 15:02:36 -0400647 break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000648 }
Jamie Madill4667c452014-07-08 15:02:36 -0400649 default: break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000650 }
651
652 return visitChildren;
653}
Jamie Madill23a8a432014-07-09 13:27:42 -0400654
Jamie Madillb547ddf2014-08-25 16:20:46 -0400655bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
656{
657 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
658 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400659 // NOTE: we do not determine static use for individual blocks of an array
660 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
661 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400662
663 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
664 ASSERT(constantUnion);
665
Jamie Madilla6f267f2014-08-27 11:44:15 -0400666 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jamie Madilla2fbb842014-09-03 09:40:47 -0400667 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400668 ASSERT(namedBlock);
669 namedBlock->staticUse = true;
670
671 unsigned int fieldIndex = constantUnion->getUConst(0);
672 ASSERT(fieldIndex < namedBlock->fields.size());
673 namedBlock->fields[fieldIndex].staticUse = true;
674 return false;
675 }
676
677 return true;
678}
679
Zhenyao Mo409078f2014-10-28 13:23:18 -0700680void ExpandUniforms(const std::vector<Uniform> &compact,
681 std::vector<ShaderVariable> *expanded)
Jamie Madill23a8a432014-07-09 13:27:42 -0400682{
683 for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
684 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400685 const ShaderVariable &variable = compact[variableIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -0400686 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
687 }
688}
689
Jamie Madilla2fbb842014-09-03 09:40:47 -0400690}