blob: d61dc40666ac1cc913e126be5c3ff91e4135aa86 [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 Madill54ad4f82014-09-03 09:40:46 -040019TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
20{
21 if (interfaceBlock.hasInstanceName())
22 {
23 return interfaceBlock.name() + "." + field.name();
24 }
25 else
26 {
27 return field.name();
28 }
29}
30
Jamie Madilla2fbb842014-09-03 09:40:47 -040031BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
Jamie Madill54ad4f82014-09-03 09:40:46 -040032{
33 switch (blockStorage)
34 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040035 case EbsPacked: return BLOCKLAYOUT_PACKED;
36 case EbsShared: return BLOCKLAYOUT_SHARED;
37 case EbsStd140: return BLOCKLAYOUT_STANDARD;
38 default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
Jamie Madill54ad4f82014-09-03 09:40:46 -040039 }
40}
41
Jamie Madilla2fbb842014-09-03 09:40:47 -040042void ExpandUserDefinedVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040043 const std::string &name,
44 const std::string &mappedName,
45 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040046 std::vector<ShaderVariable> *expanded);
Jamie Madill54ad4f82014-09-03 09:40:46 -040047
Jamie Madilla2fbb842014-09-03 09:40:47 -040048void ExpandVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040049 const std::string &name,
50 const std::string &mappedName,
51 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040052 std::vector<ShaderVariable> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000053{
Jamie Madill23a8a432014-07-09 13:27:42 -040054 if (variable.isStruct())
Jamie Madill4667c452014-07-08 15:02:36 -040055 {
Jamie Madill23a8a432014-07-09 13:27:42 -040056 if (variable.isArray())
57 {
Jamie Madillb1956432015-08-12 17:35:20 +000058 for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++)
Jamie Madill23a8a432014-07-09 13:27:42 -040059 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040060 std::string lname = name + ::ArrayString(elementIndex);
61 std::string lmappedName = mappedName + ::ArrayString(elementIndex);
Jamie Madill23a8a432014-07-09 13:27:42 -040062 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
63 }
64 }
65 else
66 {
67 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
68 }
Jamie Madill4667c452014-07-08 15:02:36 -040069 }
70 else
71 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040072 ShaderVariable expandedVar = variable;
Jamie Madill23a8a432014-07-09 13:27:42 -040073
74 expandedVar.name = name;
75 expandedVar.mappedName = mappedName;
76
77 // Mark all expanded fields as used if the parent is used
78 if (markStaticUse)
79 {
80 expandedVar.staticUse = true;
81 }
82
83 if (expandedVar.isArray())
84 {
85 expandedVar.name += "[0]";
86 expandedVar.mappedName += "[0]";
87 }
88
89 expanded->push_back(expandedVar);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000090 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000091}
92
Jamie Madilla2fbb842014-09-03 09:40:47 -040093void ExpandUserDefinedVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040094 const std::string &name,
95 const std::string &mappedName,
96 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040097 std::vector<ShaderVariable> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000098{
Jamie Madill23a8a432014-07-09 13:27:42 -040099 ASSERT(variable.isStruct());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000100
Jamie Madilla2fbb842014-09-03 09:40:47 -0400101 const std::vector<ShaderVariable> &fields = variable.fields;
Jamie Madill23a8a432014-07-09 13:27:42 -0400102
103 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
Jamie Madill4667c452014-07-08 15:02:36 -0400104 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400105 const ShaderVariable &field = fields[fieldIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -0400106 ExpandVariable(field,
107 name + "." + field.name,
108 mappedName + "." + field.mappedName,
109 markStaticUse,
110 expanded);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000111 }
112}
113
Jamie Madilla718c1e2014-07-02 15:31:22 -0400114template <class VarT>
Jamie Madill54ad4f82014-09-03 09:40:46 -0400115VarT *FindVariable(const TString &name,
116 std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400117{
118 // TODO(zmo): optimize this function.
Jamie Madilla718c1e2014-07-02 15:31:22 -0400119 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400120 {
Jamie Madill23a8a432014-07-09 13:27:42 -0400121 if ((*infoList)[ii].name.c_str() == name)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400122 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400123 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400124
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400125 return NULL;
126}
127
Jamie Madill54ad4f82014-09-03 09:40:46 -0400128}
129
Jamie Madilla718c1e2014-07-02 15:31:22 -0400130CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
Jamie Madilld5512cd2014-07-10 17:50:08 -0400131 std::vector<sh::Attribute> *outputVariables,
Jamie Madilla718c1e2014-07-02 15:31:22 -0400132 std::vector<sh::Uniform> *uniforms,
133 std::vector<sh::Varying> *varyings,
Jamie Madilld5512cd2014-07-10 17:50:08 -0400134 std::vector<sh::InterfaceBlock> *interfaceBlocks,
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700135 ShHashFunction64 hashFunction,
136 const TSymbolTable &symbolTable)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300137 : TIntermTraverser(true, false, false),
138 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400139 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000140 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400141 mVaryings(varyings),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400142 mInterfaceBlocks(interfaceBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400143 mDepthRangeAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400144 mPointCoordAdded(false),
145 mFrontFacingAdded(false),
146 mFragCoordAdded(false),
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000147 mInstanceIDAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700148 mPositionAdded(false),
149 mPointSizeAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100150 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300151 mFragColorAdded(false),
152 mFragDataAdded(false),
153 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300154 mSecondaryFragColorEXTAdded(false),
155 mSecondaryFragDataEXTAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700156 mHashFunction(hashFunction),
157 mSymbolTable(symbolTable)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000158{
159}
160
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400161// We want to check whether a uniform/varying is statically used
162// because we only count the used ones in packing computing.
163// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
164// toward varying counting if they are statically used in a fragment
165// shader.
Jamie Madill4667c452014-07-08 15:02:36 -0400166void CollectVariables::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000167{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400168 ASSERT(symbol != NULL);
Jamie Madilla2fbb842014-09-03 09:40:47 -0400169 ShaderVariable *var = NULL;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400170 const TString &symbolName = symbol->getSymbol();
Jamie Madill4667c452014-07-08 15:02:36 -0400171
Jamie Madilla2fbb842014-09-03 09:40:47 -0400172 if (IsVarying(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400173 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400174 var = FindVariable(symbolName, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400175 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400176 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
177 {
178 UNREACHABLE();
179 }
Jamie Madill55def582015-05-04 11:24:57 -0400180 else if (symbolName == "gl_DepthRange")
181 {
182 ASSERT(symbol->getQualifier() == EvqUniform);
183
184 if (!mDepthRangeAdded)
185 {
186 Uniform info;
187 const char kName[] = "gl_DepthRange";
188 info.name = kName;
189 info.mappedName = kName;
190 info.type = GL_STRUCT_ANGLEX;
191 info.arraySize = 0;
192 info.precision = GL_NONE;
193 info.staticUse = true;
194
195 ShaderVariable nearInfo;
196 const char kNearName[] = "near";
197 nearInfo.name = kNearName;
198 nearInfo.mappedName = kNearName;
199 nearInfo.type = GL_FLOAT;
200 nearInfo.arraySize = 0;
201 nearInfo.precision = GL_HIGH_FLOAT;
202 nearInfo.staticUse = true;
203
204 ShaderVariable farInfo;
205 const char kFarName[] = "far";
206 farInfo.name = kFarName;
207 farInfo.mappedName = kFarName;
208 farInfo.type = GL_FLOAT;
209 farInfo.arraySize = 0;
210 farInfo.precision = GL_HIGH_FLOAT;
211 farInfo.staticUse = true;
212
213 ShaderVariable diffInfo;
214 const char kDiffName[] = "diff";
215 diffInfo.name = kDiffName;
216 diffInfo.mappedName = kDiffName;
217 diffInfo.type = GL_FLOAT;
218 diffInfo.arraySize = 0;
219 diffInfo.precision = GL_HIGH_FLOAT;
220 diffInfo.staticUse = true;
221
222 info.fields.push_back(nearInfo);
223 info.fields.push_back(farInfo);
224 info.fields.push_back(diffInfo);
225
226 mUniforms->push_back(info);
227 mDepthRangeAdded = true;
228 }
229 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400230 else
Jamie Madill4667c452014-07-08 15:02:36 -0400231 {
232 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400233 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400234 case EvqAttribute:
235 case EvqVertexIn:
236 var = FindVariable(symbolName, mAttribs);
237 break;
238 case EvqFragmentOut:
239 var = FindVariable(symbolName, mOutputVariables);
240 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400241 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400242 {
243 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
244 if (interfaceBlock)
245 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400246 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400247 ASSERT(namedBlock);
248 var = FindVariable(symbolName, &namedBlock->fields);
249
250 // Set static use on the parent interface block here
251 namedBlock->staticUse = true;
252 }
253 else
254 {
255 var = FindVariable(symbolName, mUniforms);
256 }
257
258 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400259 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400260 }
Jamie Madill4667c452014-07-08 15:02:36 -0400261 break;
262 case EvqFragCoord:
263 if (!mFragCoordAdded)
264 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400265 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700266 const char kName[] = "gl_FragCoord";
267 info.name = kName;
268 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400269 info.type = GL_FLOAT_VEC4;
270 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700271 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400272 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700273 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400274 mVaryings->push_back(info);
275 mFragCoordAdded = true;
276 }
277 return;
278 case EvqFrontFacing:
279 if (!mFrontFacingAdded)
280 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400281 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700282 const char kName[] = "gl_FrontFacing";
283 info.name = kName;
284 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400285 info.type = GL_BOOL;
286 info.arraySize = 0;
287 info.precision = GL_NONE;
288 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700289 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400290 mVaryings->push_back(info);
291 mFrontFacingAdded = true;
292 }
293 return;
294 case EvqPointCoord:
295 if (!mPointCoordAdded)
296 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400297 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700298 const char kName[] = "gl_PointCoord";
299 info.name = kName;
300 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400301 info.type = GL_FLOAT_VEC2;
302 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700303 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400304 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700305 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400306 mVaryings->push_back(info);
307 mPointCoordAdded = true;
308 }
309 return;
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000310 case EvqInstanceID:
311 if (!mInstanceIDAdded)
312 {
313 Attribute info;
314 const char kName[] = "gl_InstanceID";
315 info.name = kName;
316 info.mappedName = kName;
317 info.type = GL_INT;
318 info.arraySize = 0;
319 info.precision = GL_HIGH_INT; // Defined by spec.
320 info.staticUse = true;
321 info.location = -1;
322 mAttribs->push_back(info);
323 mInstanceIDAdded = true;
324 }
325 return;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700326 case EvqPosition:
327 if (!mPositionAdded)
328 {
329 Varying info;
330 const char kName[] = "gl_Position";
331 info.name = kName;
332 info.mappedName = kName;
333 info.type = GL_FLOAT_VEC4;
334 info.arraySize = 0;
335 info.precision = GL_HIGH_FLOAT; // Defined by spec.
336 info.staticUse = true;
337 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
338 mVaryings->push_back(info);
339 mPositionAdded = true;
340 }
341 return;
342 case EvqPointSize:
343 if (!mPointSizeAdded)
344 {
345 Varying info;
346 const char kName[] = "gl_PointSize";
347 info.name = kName;
348 info.mappedName = kName;
349 info.type = GL_FLOAT;
350 info.arraySize = 0;
351 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
352 info.staticUse = true;
353 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
354 mVaryings->push_back(info);
355 mPointSizeAdded = true;
356 }
357 return;
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100358 case EvqLastFragData:
359 if (!mLastFragDataAdded)
360 {
361 Varying info;
362 const char kName[] = "gl_LastFragData";
363 info.name = kName;
364 info.mappedName = kName;
365 info.type = GL_FLOAT_VEC4;
366 info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
367 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
368 info.staticUse = true;
369 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
370 mVaryings->push_back(info);
371 mLastFragDataAdded = true;
372 }
373 return;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300374 case EvqFragColor:
375 if (!mFragColorAdded)
376 {
377 Attribute info;
378 const char kName[] = "gl_FragColor";
379 info.name = kName;
380 info.mappedName = kName;
381 info.type = GL_FLOAT_VEC4;
382 info.arraySize = 0;
383 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
384 info.staticUse = true;
385 mOutputVariables->push_back(info);
386 mFragColorAdded = true;
387 }
388 return;
389 case EvqFragData:
390 if (!mFragDataAdded)
391 {
392 Attribute info;
393 const char kName[] = "gl_FragData";
394 info.name = kName;
395 info.mappedName = kName;
396 info.type = GL_FLOAT_VEC4;
397 info.arraySize = static_cast<const TVariable *>(
398 mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
399 ->getConstPointer()
400 ->getIConst();
401 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
402 info.staticUse = true;
403 mOutputVariables->push_back(info);
404 mFragDataAdded = true;
405 }
406 return;
Geoff Lange2bfe2c2015-07-23 21:25:45 +0000407 case EvqFragDepth:
408 if (!mFragDepthAdded)
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300409 {
410 Attribute info;
411 const char kName[] = "gl_FragDepthEXT";
412 info.name = kName;
413 info.mappedName = kName;
414 info.type = GL_FLOAT;
415 info.arraySize = 0;
416 info.precision =
417 GLVariablePrecision(static_cast<const TVariable *>(
418 mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
419 ->getType());
420 info.staticUse = true;
421 mOutputVariables->push_back(info);
422 mFragDepthAdded = true;
423 }
424 return;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300425 case EvqSecondaryFragColorEXT:
426 if (!mSecondaryFragColorEXTAdded)
427 {
428 Attribute info;
429 const char kName[] = "gl_SecondaryFragColorEXT";
430 info.name = kName;
431 info.mappedName = kName;
432 info.type = GL_FLOAT_VEC4;
433 info.arraySize = 0;
434 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
435 info.staticUse = true;
436 mOutputVariables->push_back(info);
437 mSecondaryFragColorEXTAdded = true;
438 }
439 return;
440 case EvqSecondaryFragDataEXT:
441 if (!mSecondaryFragDataEXTAdded)
442 {
443 Attribute info;
444 const char kName[] = "gl_SecondaryFragDataEXT";
445 info.name = kName;
446 info.mappedName = kName;
447 info.type = GL_FLOAT_VEC4;
448
449 const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
450 mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
451 info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
452 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
453 info.staticUse = true;
454 mOutputVariables->push_back(info);
455 mSecondaryFragDataEXTAdded = true;
456 }
457 return;
Jamie Madill4667c452014-07-08 15:02:36 -0400458 default:
459 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400460 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400461 }
462 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400463 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400464 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400465 }
466}
467
Jamie Madilla2fbb842014-09-03 09:40:47 -0400468class NameHashingTraverser : public GetVariableTraverser
Jamie Madill23a8a432014-07-09 13:27:42 -0400469{
470 public:
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700471 NameHashingTraverser(ShHashFunction64 hashFunction,
472 const TSymbolTable &symbolTable)
473 : GetVariableTraverser(symbolTable),
474 mHashFunction(hashFunction)
Jamie Madill23a8a432014-07-09 13:27:42 -0400475 {}
476
477 private:
Jamie Madilla2fbb842014-09-03 09:40:47 -0400478 virtual void visitVariable(ShaderVariable *variable)
Jamie Madill23a8a432014-07-09 13:27:42 -0400479 {
480 TString stringName = TString(variable->name.c_str());
481 variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
482 }
483
484 ShHashFunction64 mHashFunction;
485};
486
487// Attributes, which cannot have struct fields, are a special case
488template <>
489void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400490 std::vector<Attribute> *infoList) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400491{
492 ASSERT(variable);
493 const TType &type = variable->getType();
494 ASSERT(!type.getStruct());
495
Jamie Madilla2fbb842014-09-03 09:40:47 -0400496 Attribute attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400497
Jamie Madilla2fbb842014-09-03 09:40:47 -0400498 attribute.type = GLVariableType(type);
499 attribute.precision = GLVariablePrecision(type);
Jamie Madill23a8a432014-07-09 13:27:42 -0400500 attribute.name = variable->getSymbol().c_str();
501 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
502 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
503 attribute.location = variable->getType().getLayoutQualifier().location;
504
505 infoList->push_back(attribute);
506}
507
Jamie Madilld5512cd2014-07-10 17:50:08 -0400508template <>
509void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400510 std::vector<InterfaceBlock> *infoList) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400511{
Jamie Madilla2fbb842014-09-03 09:40:47 -0400512 InterfaceBlock interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400513 const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400514 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400515
516 interfaceBlock.name = blockType->name().c_str();
517 interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
Jamie Madill42bcf322014-08-25 16:20:46 -0400518 interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
Jamie Madilld5512cd2014-07-10 17:50:08 -0400519 interfaceBlock.arraySize = variable->getArraySize();
Jamie Madill42bcf322014-08-25 16:20:46 -0400520 interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400521 interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400522
Jamie Madilla6f267f2014-08-27 11:44:15 -0400523 // Gather field information
Jamie Madill54ad4f82014-09-03 09:40:46 -0400524 const TFieldList &fieldList = blockType->fields();
525
526 for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
527 {
528 const TField &field = *fieldList[fieldIndex];
529 const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
530 const TType &fieldType = *field.type();
531
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700532 GetVariableTraverser traverser(mSymbolTable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400533 traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
534
535 interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
536 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400537
538 infoList->push_back(interfaceBlock);
539}
540
Jamie Madill23a8a432014-07-09 13:27:42 -0400541template <typename VarT>
Jamie Madill4667c452014-07-08 15:02:36 -0400542void CollectVariables::visitVariable(const TIntermSymbol *variable,
543 std::vector<VarT> *infoList) const
544{
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700545 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill42bcf322014-08-25 16:20:46 -0400546 traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
Jamie Madill4667c452014-07-08 15:02:36 -0400547}
548
549template <typename VarT>
550void CollectVariables::visitInfoList(const TIntermSequence &sequence,
551 std::vector<VarT> *infoList) const
Jamie Madilla718c1e2014-07-02 15:31:22 -0400552{
553 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
554 {
Jamie Madill4667c452014-07-08 15:02:36 -0400555 const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
Jamie Madilla718c1e2014-07-02 15:31:22 -0400556 // The only case in which the sequence will not contain a
557 // TIntermSymbol node is initialization. It will contain a
558 // TInterBinary node in that case. Since attributes, uniforms,
559 // and varyings cannot be initialized in a shader, we must have
560 // only TIntermSymbol nodes in the sequence.
561 ASSERT(variable != NULL);
Jamie Madill4667c452014-07-08 15:02:36 -0400562 visitVariable(variable, infoList);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400563 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000564}
565
Jamie Madill4667c452014-07-08 15:02:36 -0400566bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000567{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400568 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000569
570 switch (node->getOp())
571 {
Jamie Madill4667c452014-07-08 15:02:36 -0400572 case EOpDeclaration:
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000573 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700574 const TIntermSequence &sequence = *(node->getSequence());
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400575 ASSERT(!sequence.empty());
576
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700577 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400578 TQualifier qualifier = typedNode.getQualifier();
579
580 if (typedNode.getBasicType() == EbtInterfaceBlock)
581 {
582 visitInfoList(sequence, mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400583 visitChildren = false;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400584 }
585 else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
586 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
Jamie Madilla2fbb842014-09-03 09:40:47 -0400587 IsVarying(qualifier))
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400588 {
Jamie Madill4667c452014-07-08 15:02:36 -0400589 switch (qualifier)
590 {
591 case EvqAttribute:
592 case EvqVertexIn:
593 visitInfoList(sequence, mAttribs);
594 break;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400595 case EvqFragmentOut:
596 visitInfoList(sequence, mOutputVariables);
597 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400598 case EvqUniform:
599 visitInfoList(sequence, mUniforms);
600 break;
601 default:
Jamie Madill3b5c2da2014-08-19 15:23:32 -0400602 visitInfoList(sequence, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400603 break;
604 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400605
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400606 visitChildren = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000607 }
Jamie Madill4667c452014-07-08 15:02:36 -0400608 break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000609 }
Jamie Madill4667c452014-07-08 15:02:36 -0400610 default: break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000611 }
612
613 return visitChildren;
614}
Jamie Madill23a8a432014-07-09 13:27:42 -0400615
Jamie Madillb547ddf2014-08-25 16:20:46 -0400616bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
617{
618 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
619 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400620 // NOTE: we do not determine static use for individual blocks of an array
621 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
622 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400623
624 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
625 ASSERT(constantUnion);
626
Jamie Madilla6f267f2014-08-27 11:44:15 -0400627 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jamie Madilla2fbb842014-09-03 09:40:47 -0400628 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400629 ASSERT(namedBlock);
630 namedBlock->staticUse = true;
631
632 unsigned int fieldIndex = constantUnion->getUConst(0);
633 ASSERT(fieldIndex < namedBlock->fields.size());
634 namedBlock->fields[fieldIndex].staticUse = true;
635 return false;
636 }
637
638 return true;
639}
640
Zhenyao Mo409078f2014-10-28 13:23:18 -0700641void ExpandUniforms(const std::vector<Uniform> &compact,
642 std::vector<ShaderVariable> *expanded)
Jamie Madill23a8a432014-07-09 13:27:42 -0400643{
644 for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
645 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400646 const ShaderVariable &variable = compact[variableIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -0400647 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
648 }
649}
650
Jamie Madilla2fbb842014-09-03 09:40:47 -0400651}