blob: 07fe12e5d1d54824fa0a43af6a4bc1caf8669b9b [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)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000035{
Jamie Madill23a8a432014-07-09 13:27:42 -040036 ASSERT(variable.isStruct());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000037
Jamie Madilla2fbb842014-09-03 09:40:47 -040038 const std::vector<ShaderVariable> &fields = variable.fields;
Jamie Madill23a8a432014-07-09 13:27:42 -040039
40 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
Jamie Madill4667c452014-07-08 15:02:36 -040041 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040042 const ShaderVariable &field = fields[fieldIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -040043 ExpandVariable(field,
44 name + "." + field.name,
45 mappedName + "." + field.mappedName,
46 markStaticUse,
47 expanded);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000048 }
49}
50
Jamie Madilla718c1e2014-07-02 15:31:22 -040051template <class VarT>
Jamie Madill54ad4f82014-09-03 09:40:46 -040052VarT *FindVariable(const TString &name,
53 std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040054{
55 // TODO(zmo): optimize this function.
Jamie Madilla718c1e2014-07-02 15:31:22 -040056 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040057 {
Jamie Madill23a8a432014-07-09 13:27:42 -040058 if ((*infoList)[ii].name.c_str() == name)
Jamie Madilla718c1e2014-07-02 15:31:22 -040059 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -040060 }
Jamie Madilld5512cd2014-07-10 17:50:08 -040061
Zhenyao Mod2d340b2013-09-23 14:57:05 -040062 return NULL;
63}
64
Jamie Madill54ad4f82014-09-03 09:40:46 -040065}
66
Jamie Madilla718c1e2014-07-02 15:31:22 -040067CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
Jamie Madilla0a9e122015-09-02 15:54:30 -040068 std::vector<sh::OutputVariable> *outputVariables,
Jamie Madilla718c1e2014-07-02 15:31:22 -040069 std::vector<sh::Uniform> *uniforms,
70 std::vector<sh::Varying> *varyings,
Jamie Madilld5512cd2014-07-10 17:50:08 -040071 std::vector<sh::InterfaceBlock> *interfaceBlocks,
Zhenyao Mo94ac7b72014-10-15 18:22:08 -070072 ShHashFunction64 hashFunction,
Zhenyao Mof178d0b2016-07-23 06:59:00 -070073 const TSymbolTable &symbolTable,
74 const TExtensionBehavior &extensionBehavior)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +030075 : TIntermTraverser(true, false, false),
76 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -040077 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000078 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -040079 mVaryings(varyings),
Jamie Madilld5512cd2014-07-10 17:50:08 -040080 mInterfaceBlocks(interfaceBlocks),
Jamie Madill55def582015-05-04 11:24:57 -040081 mDepthRangeAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -040082 mPointCoordAdded(false),
83 mFrontFacingAdded(false),
84 mFragCoordAdded(false),
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +000085 mInstanceIDAdded(false),
Corentin Wallezb076add2016-01-11 16:45:46 -050086 mVertexIDAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -070087 mPositionAdded(false),
88 mPointSizeAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +010089 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +030090 mFragColorAdded(false),
91 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +030092 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +030093 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030094 mSecondaryFragColorEXTAdded(false),
95 mSecondaryFragDataEXTAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -070096 mHashFunction(hashFunction),
Zhenyao Mof178d0b2016-07-23 06:59:00 -070097 mSymbolTable(symbolTable),
98 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +000099{
100}
101
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400102// We want to check whether a uniform/varying is statically used
103// because we only count the used ones in packing computing.
104// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
105// toward varying counting if they are statically used in a fragment
106// shader.
Jamie Madill4667c452014-07-08 15:02:36 -0400107void CollectVariables::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000108{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400109 ASSERT(symbol != NULL);
Jamie Madilla2fbb842014-09-03 09:40:47 -0400110 ShaderVariable *var = NULL;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400111 const TString &symbolName = symbol->getSymbol();
Jamie Madill4667c452014-07-08 15:02:36 -0400112
Jamie Madilla2fbb842014-09-03 09:40:47 -0400113 if (IsVarying(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400114 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400115 var = FindVariable(symbolName, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400116 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400117 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
118 {
119 UNREACHABLE();
120 }
Jamie Madill55def582015-05-04 11:24:57 -0400121 else if (symbolName == "gl_DepthRange")
122 {
123 ASSERT(symbol->getQualifier() == EvqUniform);
124
125 if (!mDepthRangeAdded)
126 {
127 Uniform info;
128 const char kName[] = "gl_DepthRange";
129 info.name = kName;
130 info.mappedName = kName;
131 info.type = GL_STRUCT_ANGLEX;
132 info.arraySize = 0;
133 info.precision = GL_NONE;
134 info.staticUse = true;
135
136 ShaderVariable nearInfo;
137 const char kNearName[] = "near";
138 nearInfo.name = kNearName;
139 nearInfo.mappedName = kNearName;
140 nearInfo.type = GL_FLOAT;
141 nearInfo.arraySize = 0;
142 nearInfo.precision = GL_HIGH_FLOAT;
143 nearInfo.staticUse = true;
144
145 ShaderVariable farInfo;
146 const char kFarName[] = "far";
147 farInfo.name = kFarName;
148 farInfo.mappedName = kFarName;
149 farInfo.type = GL_FLOAT;
150 farInfo.arraySize = 0;
151 farInfo.precision = GL_HIGH_FLOAT;
152 farInfo.staticUse = true;
153
154 ShaderVariable diffInfo;
155 const char kDiffName[] = "diff";
156 diffInfo.name = kDiffName;
157 diffInfo.mappedName = kDiffName;
158 diffInfo.type = GL_FLOAT;
159 diffInfo.arraySize = 0;
160 diffInfo.precision = GL_HIGH_FLOAT;
161 diffInfo.staticUse = true;
162
163 info.fields.push_back(nearInfo);
164 info.fields.push_back(farInfo);
165 info.fields.push_back(diffInfo);
166
167 mUniforms->push_back(info);
168 mDepthRangeAdded = true;
169 }
170 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400171 else
Jamie Madill4667c452014-07-08 15:02:36 -0400172 {
173 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400174 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400175 case EvqAttribute:
176 case EvqVertexIn:
177 var = FindVariable(symbolName, mAttribs);
178 break;
179 case EvqFragmentOut:
180 var = FindVariable(symbolName, mOutputVariables);
181 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400182 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400183 {
184 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
185 if (interfaceBlock)
186 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400187 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400188 ASSERT(namedBlock);
189 var = FindVariable(symbolName, &namedBlock->fields);
190
191 // Set static use on the parent interface block here
192 namedBlock->staticUse = true;
193 }
194 else
195 {
196 var = FindVariable(symbolName, mUniforms);
197 }
198
199 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400200 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400201 }
Jamie Madill4667c452014-07-08 15:02:36 -0400202 break;
203 case EvqFragCoord:
204 if (!mFragCoordAdded)
205 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400206 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700207 const char kName[] = "gl_FragCoord";
208 info.name = kName;
209 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400210 info.type = GL_FLOAT_VEC4;
211 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700212 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400213 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700214 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400215 mVaryings->push_back(info);
216 mFragCoordAdded = true;
217 }
218 return;
219 case EvqFrontFacing:
220 if (!mFrontFacingAdded)
221 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400222 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700223 const char kName[] = "gl_FrontFacing";
224 info.name = kName;
225 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400226 info.type = GL_BOOL;
227 info.arraySize = 0;
228 info.precision = GL_NONE;
229 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700230 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400231 mVaryings->push_back(info);
232 mFrontFacingAdded = true;
233 }
234 return;
235 case EvqPointCoord:
236 if (!mPointCoordAdded)
237 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400238 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700239 const char kName[] = "gl_PointCoord";
240 info.name = kName;
241 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400242 info.type = GL_FLOAT_VEC2;
243 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700244 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400245 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700246 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400247 mVaryings->push_back(info);
248 mPointCoordAdded = true;
249 }
250 return;
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000251 case EvqInstanceID:
252 if (!mInstanceIDAdded)
253 {
254 Attribute info;
255 const char kName[] = "gl_InstanceID";
256 info.name = kName;
257 info.mappedName = kName;
258 info.type = GL_INT;
259 info.arraySize = 0;
260 info.precision = GL_HIGH_INT; // Defined by spec.
261 info.staticUse = true;
262 info.location = -1;
263 mAttribs->push_back(info);
264 mInstanceIDAdded = true;
265 }
266 return;
Corentin Wallezb076add2016-01-11 16:45:46 -0500267 case EvqVertexID:
268 if (!mVertexIDAdded)
269 {
270 Attribute info;
271 const char kName[] = "gl_VertexID";
272 info.name = kName;
273 info.mappedName = kName;
274 info.type = GL_INT;
275 info.arraySize = 0;
276 info.precision = GL_HIGH_INT; // Defined by spec.
277 info.staticUse = true;
278 info.location = -1;
279 mAttribs->push_back(info);
280 mVertexIDAdded = true;
281 }
282 return;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700283 case EvqPosition:
284 if (!mPositionAdded)
285 {
286 Varying info;
287 const char kName[] = "gl_Position";
288 info.name = kName;
289 info.mappedName = kName;
290 info.type = GL_FLOAT_VEC4;
291 info.arraySize = 0;
292 info.precision = GL_HIGH_FLOAT; // Defined by spec.
293 info.staticUse = true;
294 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
295 mVaryings->push_back(info);
296 mPositionAdded = true;
297 }
298 return;
299 case EvqPointSize:
300 if (!mPointSizeAdded)
301 {
302 Varying info;
303 const char kName[] = "gl_PointSize";
304 info.name = kName;
305 info.mappedName = kName;
306 info.type = GL_FLOAT;
307 info.arraySize = 0;
308 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
309 info.staticUse = true;
310 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
311 mVaryings->push_back(info);
312 mPointSizeAdded = true;
313 }
314 return;
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100315 case EvqLastFragData:
316 if (!mLastFragDataAdded)
317 {
318 Varying info;
319 const char kName[] = "gl_LastFragData";
320 info.name = kName;
321 info.mappedName = kName;
322 info.type = GL_FLOAT_VEC4;
323 info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
324 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
325 info.staticUse = true;
326 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
327 mVaryings->push_back(info);
328 mLastFragDataAdded = true;
329 }
330 return;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300331 case EvqFragColor:
332 if (!mFragColorAdded)
333 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400334 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300335 const char kName[] = "gl_FragColor";
336 info.name = kName;
337 info.mappedName = kName;
338 info.type = GL_FLOAT_VEC4;
339 info.arraySize = 0;
340 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
341 info.staticUse = true;
342 mOutputVariables->push_back(info);
343 mFragColorAdded = true;
344 }
345 return;
346 case EvqFragData:
347 if (!mFragDataAdded)
348 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400349 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300350 const char kName[] = "gl_FragData";
351 info.name = kName;
352 info.mappedName = kName;
353 info.type = GL_FLOAT_VEC4;
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700354 if (::IsExtensionEnabled(mExtensionBehavior, "GL_EXT_draw_buffers"))
355 {
356 info.arraySize = static_cast<const TVariable *>(
357 mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
358 ->getConstPointer()
359 ->getIConst();
360 }
361 else
362 {
363 info.arraySize = 1;
364 }
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300365 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
366 info.staticUse = true;
367 mOutputVariables->push_back(info);
368 mFragDataAdded = true;
369 }
370 return;
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300371 case EvqFragDepthEXT:
372 if (!mFragDepthEXTAdded)
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300373 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400374 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300375 const char kName[] = "gl_FragDepthEXT";
376 info.name = kName;
377 info.mappedName = kName;
378 info.type = GL_FLOAT;
379 info.arraySize = 0;
380 info.precision =
381 GLVariablePrecision(static_cast<const TVariable *>(
382 mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
383 ->getType());
384 info.staticUse = true;
385 mOutputVariables->push_back(info);
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300386 mFragDepthEXTAdded = true;
387 }
388 return;
389 case EvqFragDepth:
390 if (!mFragDepthAdded)
391 {
392 OutputVariable info;
393 const char kName[] = "gl_FragDepth";
394 info.name = kName;
395 info.mappedName = kName;
396 info.type = GL_FLOAT;
397 info.arraySize = 0;
398 info.precision = GL_HIGH_FLOAT;
399 info.staticUse = true;
400 mOutputVariables->push_back(info);
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300401 mFragDepthAdded = true;
402 }
403 return;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300404 case EvqSecondaryFragColorEXT:
405 if (!mSecondaryFragColorEXTAdded)
406 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400407 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300408 const char kName[] = "gl_SecondaryFragColorEXT";
409 info.name = kName;
410 info.mappedName = kName;
411 info.type = GL_FLOAT_VEC4;
412 info.arraySize = 0;
413 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
414 info.staticUse = true;
415 mOutputVariables->push_back(info);
416 mSecondaryFragColorEXTAdded = true;
417 }
418 return;
419 case EvqSecondaryFragDataEXT:
420 if (!mSecondaryFragDataEXTAdded)
421 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400422 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300423 const char kName[] = "gl_SecondaryFragDataEXT";
424 info.name = kName;
425 info.mappedName = kName;
426 info.type = GL_FLOAT_VEC4;
427
428 const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
429 mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
430 info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
431 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
432 info.staticUse = true;
433 mOutputVariables->push_back(info);
434 mSecondaryFragDataEXTAdded = true;
435 }
436 return;
Jamie Madill4667c452014-07-08 15:02:36 -0400437 default:
438 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400439 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400440 }
441 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400442 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400443 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400444 }
445}
446
Jamie Madilla2fbb842014-09-03 09:40:47 -0400447class NameHashingTraverser : public GetVariableTraverser
Jamie Madill23a8a432014-07-09 13:27:42 -0400448{
449 public:
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700450 NameHashingTraverser(ShHashFunction64 hashFunction,
451 const TSymbolTable &symbolTable)
452 : GetVariableTraverser(symbolTable),
453 mHashFunction(hashFunction)
Jamie Madill23a8a432014-07-09 13:27:42 -0400454 {}
455
456 private:
Corentin Walleze5a1f272015-08-21 02:58:25 +0200457 void visitVariable(ShaderVariable *variable) override
Jamie Madill23a8a432014-07-09 13:27:42 -0400458 {
459 TString stringName = TString(variable->name.c_str());
460 variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
461 }
462
463 ShHashFunction64 mHashFunction;
464};
465
466// Attributes, which cannot have struct fields, are a special case
467template <>
468void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400469 std::vector<Attribute> *infoList) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400470{
471 ASSERT(variable);
472 const TType &type = variable->getType();
473 ASSERT(!type.getStruct());
474
Jamie Madilla2fbb842014-09-03 09:40:47 -0400475 Attribute attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400476
Jamie Madilla2fbb842014-09-03 09:40:47 -0400477 attribute.type = GLVariableType(type);
478 attribute.precision = GLVariablePrecision(type);
Jamie Madill23a8a432014-07-09 13:27:42 -0400479 attribute.name = variable->getSymbol().c_str();
Olli Etuaho856c4972016-08-08 11:38:39 +0300480 attribute.arraySize = type.getArraySize();
Jamie Madill23a8a432014-07-09 13:27:42 -0400481 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
482 attribute.location = variable->getType().getLayoutQualifier().location;
483
484 infoList->push_back(attribute);
485}
486
Jamie Madilld5512cd2014-07-10 17:50:08 -0400487template <>
488void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla0a9e122015-09-02 15:54:30 -0400489 std::vector<OutputVariable> *infoList) const
490{
491 ASSERT(variable);
492 const TType &type = variable->getType();
493 ASSERT(!type.getStruct());
494
495 OutputVariable attribute;
496
497 attribute.type = GLVariableType(type);
498 attribute.precision = GLVariablePrecision(type);
499 attribute.name = variable->getSymbol().c_str();
Olli Etuaho856c4972016-08-08 11:38:39 +0300500 attribute.arraySize = type.getArraySize();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400501 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
502 attribute.location = variable->getType().getLayoutQualifier().location;
503
504 infoList->push_back(attribute);
505}
506
507template <>
508void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400509 std::vector<InterfaceBlock> *infoList) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400510{
Jamie Madilla2fbb842014-09-03 09:40:47 -0400511 InterfaceBlock interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400512 const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400513 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400514
515 interfaceBlock.name = blockType->name().c_str();
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500516 interfaceBlock.mappedName =
517 TIntermTraverser::hash(blockType->name().c_str(), 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 Madill39046162016-02-08 15:05:17 -0500524 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400525 {
Jamie Madill39046162016-02-08 15:05:17 -0500526 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400527
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500528 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill39046162016-02-08 15:05:17 -0500529 traverser.traverse(fieldType, field->name(), &interfaceBlock.fields);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400530
531 interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
532 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400533
534 infoList->push_back(interfaceBlock);
535}
536
Jamie Madill23a8a432014-07-09 13:27:42 -0400537template <typename VarT>
Jamie Madill4667c452014-07-08 15:02:36 -0400538void CollectVariables::visitVariable(const TIntermSymbol *variable,
539 std::vector<VarT> *infoList) const
540{
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700541 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill42bcf322014-08-25 16:20:46 -0400542 traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
Jamie Madill4667c452014-07-08 15:02:36 -0400543}
544
545template <typename VarT>
546void CollectVariables::visitInfoList(const TIntermSequence &sequence,
547 std::vector<VarT> *infoList) const
Jamie Madilla718c1e2014-07-02 15:31:22 -0400548{
549 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
550 {
Jamie Madill4667c452014-07-08 15:02:36 -0400551 const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
Jamie Madilla718c1e2014-07-02 15:31:22 -0400552 // The only case in which the sequence will not contain a
553 // TIntermSymbol node is initialization. It will contain a
554 // TInterBinary node in that case. Since attributes, uniforms,
555 // and varyings cannot be initialized in a shader, we must have
556 // only TIntermSymbol nodes in the sequence.
557 ASSERT(variable != NULL);
Jamie Madill4667c452014-07-08 15:02:36 -0400558 visitVariable(variable, infoList);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400559 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000560}
561
Olli Etuaho13389b62016-10-16 11:48:18 +0100562bool CollectVariables::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000563{
Olli Etuaho13389b62016-10-16 11:48:18 +0100564 const TIntermSequence &sequence = *(node->getSequence());
565 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000566
Olli Etuaho13389b62016-10-16 11:48:18 +0100567 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
568 TQualifier qualifier = typedNode.getQualifier();
569
570 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000571 {
Olli Etuaho13389b62016-10-16 11:48:18 +0100572 visitInfoList(sequence, mInterfaceBlocks);
573 return false;
574 }
575 else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqFragmentOut ||
576 qualifier == EvqUniform || IsVarying(qualifier))
577 {
578 switch (qualifier)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000579 {
Olli Etuaho13389b62016-10-16 11:48:18 +0100580 case EvqAttribute:
581 case EvqVertexIn:
582 visitInfoList(sequence, mAttribs);
583 break;
584 case EvqFragmentOut:
585 visitInfoList(sequence, mOutputVariables);
586 break;
587 case EvqUniform:
588 visitInfoList(sequence, mUniforms);
589 break;
590 default:
591 visitInfoList(sequence, mVaryings);
592 break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000593 }
Olli Etuaho13389b62016-10-16 11:48:18 +0100594
595 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000596 }
597
Olli Etuaho13389b62016-10-16 11:48:18 +0100598 return true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000599}
Jamie Madill23a8a432014-07-09 13:27:42 -0400600
Jamie Madillb547ddf2014-08-25 16:20:46 -0400601bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
602{
603 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
604 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400605 // NOTE: we do not determine static use for individual blocks of an array
606 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
607 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400608
609 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
610 ASSERT(constantUnion);
611
Jamie Madilla6f267f2014-08-27 11:44:15 -0400612 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jamie Madilla2fbb842014-09-03 09:40:47 -0400613 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400614 ASSERT(namedBlock);
615 namedBlock->staticUse = true;
616
617 unsigned int fieldIndex = constantUnion->getUConst(0);
618 ASSERT(fieldIndex < namedBlock->fields.size());
619 namedBlock->fields[fieldIndex].staticUse = true;
620 return false;
621 }
622
623 return true;
624}
625
Corentin Walleze58e1412016-07-18 16:40:46 -0400626void ExpandVariable(const ShaderVariable &variable,
627 const std::string &name,
628 const std::string &mappedName,
629 bool markStaticUse,
630 std::vector<ShaderVariable> *expanded)
631{
632 if (variable.isStruct())
633 {
634 if (variable.isArray())
635 {
636 for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
637 elementIndex++)
638 {
639 std::string lname = name + ::ArrayString(elementIndex);
640 std::string lmappedName = mappedName + ::ArrayString(elementIndex);
641 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
642 }
643 }
644 else
645 {
646 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
647 }
648 }
649 else
650 {
651 ShaderVariable expandedVar = variable;
652
653 expandedVar.name = name;
654 expandedVar.mappedName = mappedName;
655
656 // Mark all expanded fields as used if the parent is used
657 if (markStaticUse)
658 {
659 expandedVar.staticUse = true;
660 }
661
662 if (expandedVar.isArray())
663 {
664 expandedVar.name += "[0]";
665 expandedVar.mappedName += "[0]";
666 }
667
668 expanded->push_back(expandedVar);
669 }
670}
671
Zhenyao Mo409078f2014-10-28 13:23:18 -0700672void ExpandUniforms(const std::vector<Uniform> &compact,
673 std::vector<ShaderVariable> *expanded)
Jamie Madill23a8a432014-07-09 13:27:42 -0400674{
675 for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
676 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400677 const ShaderVariable &variable = compact[variableIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -0400678 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
679 }
680}
681
Jamie Madilla2fbb842014-09-03 09:40:47 -0400682}