blob: 5b7a759e634cd1939a4198be3b5d57f7c9796e2b [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 Madilld7b1ab52016-12-12 14:42:19 -050023 case EbsPacked:
24 return BLOCKLAYOUT_PACKED;
25 case EbsShared:
26 return BLOCKLAYOUT_SHARED;
27 case EbsStd140:
28 return BLOCKLAYOUT_STANDARD;
29 default:
30 UNREACHABLE();
31 return BLOCKLAYOUT_SHARED;
Jamie Madill54ad4f82014-09-03 09:40:46 -040032 }
33}
34
Jamie Madilla2fbb842014-09-03 09:40:47 -040035void ExpandUserDefinedVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040036 const std::string &name,
37 const std::string &mappedName,
38 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040039 std::vector<ShaderVariable> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000040{
Jamie Madill23a8a432014-07-09 13:27:42 -040041 ASSERT(variable.isStruct());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000042
Jamie Madilla2fbb842014-09-03 09:40:47 -040043 const std::vector<ShaderVariable> &fields = variable.fields;
Jamie Madill23a8a432014-07-09 13:27:42 -040044
45 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
Jamie Madill4667c452014-07-08 15:02:36 -040046 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040047 const ShaderVariable &field = fields[fieldIndex];
Jamie Madilld7b1ab52016-12-12 14:42:19 -050048 ExpandVariable(field, name + "." + field.name, mappedName + "." + field.mappedName,
49 markStaticUse, expanded);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000050 }
51}
52
Jamie Madilla718c1e2014-07-02 15:31:22 -040053template <class VarT>
Jamie Madilld7b1ab52016-12-12 14:42:19 -050054VarT *FindVariable(const TString &name, std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040055{
56 // TODO(zmo): optimize this function.
Jamie Madilla718c1e2014-07-02 15:31:22 -040057 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040058 {
Jamie Madill23a8a432014-07-09 13:27:42 -040059 if ((*infoList)[ii].name.c_str() == name)
Jamie Madilla718c1e2014-07-02 15:31:22 -040060 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -040061 }
Jamie Madilld5512cd2014-07-10 17:50:08 -040062
Zhenyao Mod2d340b2013-09-23 14:57:05 -040063 return NULL;
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 Madilld7b1ab52016-12-12 14:42:19 -0500110 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";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500129 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;
Jamie Madill55def582015-05-04 11:24:57 -0400135
136 ShaderVariable nearInfo;
137 const char kNearName[] = "near";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500138 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;
Jamie Madill55def582015-05-04 11:24:57 -0400144
145 ShaderVariable farInfo;
146 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500147 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;
Jamie Madill55def582015-05-04 11:24:57 -0400153
154 ShaderVariable diffInfo;
155 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500156 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;
Jamie Madill55def582015-05-04 11:24:57 -0400162
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 Madilld7b1ab52016-12-12 14:42:19 -0500175 case EvqAttribute:
176 case EvqVertexIn:
177 var = FindVariable(symbolName, mAttribs);
178 break;
179 case EvqFragmentOut:
180 var = FindVariable(symbolName, mOutputVariables);
181 break;
182 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400183 {
184 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
185 if (interfaceBlock)
186 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500187 InterfaceBlock *namedBlock =
188 FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400189 ASSERT(namedBlock);
190 var = FindVariable(symbolName, &namedBlock->fields);
191
192 // Set static use on the parent interface block here
193 namedBlock->staticUse = true;
194 }
195 else
196 {
197 var = FindVariable(symbolName, mUniforms);
198 }
199
200 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400201 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400202 }
Jamie Madill4667c452014-07-08 15:02:36 -0400203 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500204 case EvqFragCoord:
205 if (!mFragCoordAdded)
206 {
207 Varying info;
208 const char kName[] = "gl_FragCoord";
209 info.name = kName;
210 info.mappedName = kName;
211 info.type = GL_FLOAT_VEC4;
212 info.arraySize = 0;
213 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
214 info.staticUse = true;
215 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
216 mVaryings->push_back(info);
217 mFragCoordAdded = true;
218 }
219 return;
220 case EvqFrontFacing:
221 if (!mFrontFacingAdded)
222 {
223 Varying info;
224 const char kName[] = "gl_FrontFacing";
225 info.name = kName;
226 info.mappedName = kName;
227 info.type = GL_BOOL;
228 info.arraySize = 0;
229 info.precision = GL_NONE;
230 info.staticUse = true;
231 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
232 mVaryings->push_back(info);
233 mFrontFacingAdded = true;
234 }
235 return;
236 case EvqPointCoord:
237 if (!mPointCoordAdded)
238 {
239 Varying info;
240 const char kName[] = "gl_PointCoord";
241 info.name = kName;
242 info.mappedName = kName;
243 info.type = GL_FLOAT_VEC2;
244 info.arraySize = 0;
245 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
246 info.staticUse = true;
247 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
248 mVaryings->push_back(info);
249 mPointCoordAdded = true;
250 }
251 return;
252 case EvqInstanceID:
253 if (!mInstanceIDAdded)
254 {
255 Attribute info;
256 const char kName[] = "gl_InstanceID";
257 info.name = kName;
258 info.mappedName = kName;
259 info.type = GL_INT;
260 info.arraySize = 0;
261 info.precision = GL_HIGH_INT; // Defined by spec.
262 info.staticUse = true;
263 info.location = -1;
264 mAttribs->push_back(info);
265 mInstanceIDAdded = true;
266 }
267 return;
268 case EvqVertexID:
269 if (!mVertexIDAdded)
270 {
271 Attribute info;
272 const char kName[] = "gl_VertexID";
273 info.name = kName;
274 info.mappedName = kName;
275 info.type = GL_INT;
276 info.arraySize = 0;
277 info.precision = GL_HIGH_INT; // Defined by spec.
278 info.staticUse = true;
279 info.location = -1;
280 mAttribs->push_back(info);
281 mVertexIDAdded = true;
282 }
283 return;
284 case EvqPosition:
285 if (!mPositionAdded)
286 {
287 Varying info;
288 const char kName[] = "gl_Position";
289 info.name = kName;
290 info.mappedName = kName;
291 info.type = GL_FLOAT_VEC4;
292 info.arraySize = 0;
293 info.precision = GL_HIGH_FLOAT; // Defined by spec.
294 info.staticUse = true;
295 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
296 mVaryings->push_back(info);
297 mPositionAdded = true;
298 }
299 return;
300 case EvqPointSize:
301 if (!mPointSizeAdded)
302 {
303 Varying info;
304 const char kName[] = "gl_PointSize";
305 info.name = kName;
306 info.mappedName = kName;
307 info.type = GL_FLOAT;
308 info.arraySize = 0;
309 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
310 info.staticUse = true;
311 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
312 mVaryings->push_back(info);
313 mPointSizeAdded = true;
314 }
315 return;
316 case EvqLastFragData:
317 if (!mLastFragDataAdded)
318 {
319 Varying info;
320 const char kName[] = "gl_LastFragData";
321 info.name = kName;
322 info.mappedName = kName;
323 info.type = GL_FLOAT_VEC4;
324 info.arraySize = static_cast<const TVariable *>(
325 mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
326 ->getConstPointer()
327 ->getIConst();
328 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
329 info.staticUse = true;
330 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
331 mVaryings->push_back(info);
332 mLastFragDataAdded = true;
333 }
334 return;
335 case EvqFragColor:
336 if (!mFragColorAdded)
337 {
338 OutputVariable info;
339 const char kName[] = "gl_FragColor";
340 info.name = kName;
341 info.mappedName = kName;
342 info.type = GL_FLOAT_VEC4;
343 info.arraySize = 0;
344 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
345 info.staticUse = true;
346 mOutputVariables->push_back(info);
347 mFragColorAdded = true;
348 }
349 return;
350 case EvqFragData:
351 if (!mFragDataAdded)
352 {
353 OutputVariable info;
354 const char kName[] = "gl_FragData";
355 info.name = kName;
356 info.mappedName = kName;
357 info.type = GL_FLOAT_VEC4;
358 if (::IsExtensionEnabled(mExtensionBehavior, "GL_EXT_draw_buffers"))
359 {
360 info.arraySize = static_cast<const TVariable *>(
361 mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
362 ->getConstPointer()
363 ->getIConst();
364 }
365 else
366 {
367 info.arraySize = 1;
368 }
369 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
370 info.staticUse = true;
371 mOutputVariables->push_back(info);
372 mFragDataAdded = true;
373 }
374 return;
375 case EvqFragDepthEXT:
376 if (!mFragDepthEXTAdded)
377 {
378 OutputVariable info;
379 const char kName[] = "gl_FragDepthEXT";
380 info.name = kName;
381 info.mappedName = kName;
382 info.type = GL_FLOAT;
383 info.arraySize = 0;
384 info.precision =
385 GLVariablePrecision(static_cast<const TVariable *>(
386 mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
387 ->getType());
388 info.staticUse = true;
389 mOutputVariables->push_back(info);
390 mFragDepthEXTAdded = true;
391 }
392 return;
393 case EvqFragDepth:
394 if (!mFragDepthAdded)
395 {
396 OutputVariable info;
397 const char kName[] = "gl_FragDepth";
398 info.name = kName;
399 info.mappedName = kName;
400 info.type = GL_FLOAT;
401 info.arraySize = 0;
402 info.precision = GL_HIGH_FLOAT;
403 info.staticUse = true;
404 mOutputVariables->push_back(info);
405 mFragDepthAdded = true;
406 }
407 return;
408 case EvqSecondaryFragColorEXT:
409 if (!mSecondaryFragColorEXTAdded)
410 {
411 OutputVariable info;
412 const char kName[] = "gl_SecondaryFragColorEXT";
413 info.name = kName;
414 info.mappedName = kName;
415 info.type = GL_FLOAT_VEC4;
416 info.arraySize = 0;
417 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
418 info.staticUse = true;
419 mOutputVariables->push_back(info);
420 mSecondaryFragColorEXTAdded = true;
421 }
422 return;
423 case EvqSecondaryFragDataEXT:
424 if (!mSecondaryFragDataEXTAdded)
425 {
426 OutputVariable info;
427 const char kName[] = "gl_SecondaryFragDataEXT";
428 info.name = kName;
429 info.mappedName = kName;
430 info.type = GL_FLOAT_VEC4;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300431
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500432 const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
433 mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
434 info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
435 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
436 info.staticUse = true;
437 mOutputVariables->push_back(info);
438 mSecondaryFragDataEXTAdded = true;
439 }
440 return;
441 default:
442 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400443 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400444 }
445 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400446 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400447 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400448 }
449}
450
Olli Etuahoa55102c2017-02-24 12:36:50 +0000451void CollectVariables::setCommonVariableProperties(const TType &type,
452 const TString &name,
453 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400454{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000455 ASSERT(variableOut);
456
457 const TStructure *structure = type.getStruct();
458
459 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500460 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000461 variableOut->type = GLVariableType(type);
462 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500463 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000464 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400465 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000466 // Note: this enum value is not exposed outside ANGLE
467 variableOut->type = GL_STRUCT_ANGLEX;
468 variableOut->structName = structure->name().c_str();
469
470 const TFieldList &fields = structure->fields();
471
472 for (TField *field : fields)
473 {
474 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
475 // ShaderVariable objects.
476 ShaderVariable fieldVariable;
477 setCommonVariableProperties(*field->type(), field->name(), &fieldVariable);
478 variableOut->fields.push_back(fieldVariable);
479 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400480 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000481 variableOut->name = name.c_str();
482 variableOut->mappedName = TIntermTraverser::hash(name, mHashFunction).c_str();
483 variableOut->arraySize = type.getArraySize();
484}
Jamie Madill23a8a432014-07-09 13:27:42 -0400485
Olli Etuahoa55102c2017-02-24 12:36:50 +0000486Attribute CollectVariables::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400487{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000488 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400489 ASSERT(!type.getStruct());
490
Jamie Madilla2fbb842014-09-03 09:40:47 -0400491 Attribute attribute;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000492 setCommonVariableProperties(type, variable.getSymbol(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400493
Olli Etuahoa55102c2017-02-24 12:36:50 +0000494 attribute.location = type.getLayoutQualifier().location;
495 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400496}
497
Olli Etuahoa55102c2017-02-24 12:36:50 +0000498OutputVariable CollectVariables::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400499{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000500 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400501 ASSERT(!type.getStruct());
502
Olli Etuahoa55102c2017-02-24 12:36:50 +0000503 OutputVariable outputVariable;
504 setCommonVariableProperties(type, variable.getSymbol(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400505
Olli Etuahoa55102c2017-02-24 12:36:50 +0000506 outputVariable.location = type.getLayoutQualifier().location;
507 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400508}
509
Olli Etuahoa55102c2017-02-24 12:36:50 +0000510Varying CollectVariables::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400511{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000512 const TType &type = variable.getType();
513
514 Varying varying;
515 setCommonVariableProperties(type, variable.getSymbol(), &varying);
516
517 switch (type.getQualifier())
518 {
519 case EvqVaryingIn:
520 case EvqVaryingOut:
521 case EvqVertexOut:
522 case EvqSmoothOut:
523 case EvqFlatOut:
524 case EvqCentroidOut:
525 if (mSymbolTable.isVaryingInvariant(std::string(variable.getSymbol().c_str())) ||
526 type.isInvariant())
527 {
528 varying.isInvariant = true;
529 }
530 break;
531 default:
532 break;
533 }
534
535 varying.interpolation = GetInterpolationType(type.getQualifier());
536 return varying;
537}
538
539InterfaceBlock CollectVariables::recordInterfaceBlock(const TIntermSymbol &variable) const
540{
541 const TInterfaceBlock *blockType = variable.getType().getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400542 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400543
Olli Etuahoa55102c2017-02-24 12:36:50 +0000544 InterfaceBlock interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400545 interfaceBlock.name = blockType->name().c_str();
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500546 interfaceBlock.mappedName =
547 TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500548 interfaceBlock.instanceName =
549 (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
Olli Etuahoa55102c2017-02-24 12:36:50 +0000550 interfaceBlock.arraySize = variable.getArraySize();
Jamie Madill42bcf322014-08-25 16:20:46 -0400551 interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500552 interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400553
Jamie Madilla6f267f2014-08-27 11:44:15 -0400554 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500555 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400556 {
Jamie Madill39046162016-02-08 15:05:17 -0500557 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400558
Olli Etuahoa55102c2017-02-24 12:36:50 +0000559 InterfaceBlockField fieldVariable;
560 setCommonVariableProperties(fieldType, field->name(), &fieldVariable);
561 fieldVariable.isRowMajorLayout =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500562 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000563 interfaceBlock.fields.push_back(fieldVariable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400564 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000565 return interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400566}
567
Olli Etuahoa55102c2017-02-24 12:36:50 +0000568Uniform CollectVariables::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400569{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000570 Uniform uniform;
571 setCommonVariableProperties(variable.getType(), variable.getSymbol(), &uniform);
572 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000573}
574
Olli Etuaho13389b62016-10-16 11:48:18 +0100575bool CollectVariables::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000576{
Olli Etuaho13389b62016-10-16 11:48:18 +0100577 const TIntermSequence &sequence = *(node->getSequence());
578 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000579
Olli Etuaho13389b62016-10-16 11:48:18 +0100580 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
581 TQualifier qualifier = typedNode.getQualifier();
582
Olli Etuahoa55102c2017-02-24 12:36:50 +0000583 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
584 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
585 IsVarying(qualifier);
586
587 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000588 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000589 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100590 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000591
592 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100593 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000594 // The only case in which the sequence will not contain a TIntermSymbol node is
595 // initialization. It will contain a TInterBinary node in that case. Since attributes,
596 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
597 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
598 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
599 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000600 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000601 mInterfaceBlocks->push_back(recordInterfaceBlock(variable));
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000602 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000603 else
604 {
605 switch (qualifier)
606 {
607 case EvqAttribute:
608 case EvqVertexIn:
609 mAttribs->push_back(recordAttribute(variable));
610 break;
611 case EvqFragmentOut:
612 mOutputVariables->push_back(recordOutputVariable(variable));
613 break;
614 case EvqUniform:
615 mUniforms->push_back(recordUniform(variable));
616 break;
617 default:
618 mVaryings->push_back(recordVarying(variable));
619 break;
620 }
621 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000622 }
623
Olli Etuahoa55102c2017-02-24 12:36:50 +0000624 // None of the recorded variables can have initializers, so we don't need to traverse the
625 // declarators.
626 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000627}
Jamie Madill23a8a432014-07-09 13:27:42 -0400628
Jamie Madillb547ddf2014-08-25 16:20:46 -0400629bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
630{
631 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
632 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400633 // NOTE: we do not determine static use for individual blocks of an array
634 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
635 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400636
637 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
638 ASSERT(constantUnion);
639
Jamie Madilla6f267f2014-08-27 11:44:15 -0400640 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jamie Madilla2fbb842014-09-03 09:40:47 -0400641 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400642 ASSERT(namedBlock);
643 namedBlock->staticUse = true;
644
645 unsigned int fieldIndex = constantUnion->getUConst(0);
646 ASSERT(fieldIndex < namedBlock->fields.size());
647 namedBlock->fields[fieldIndex].staticUse = true;
648 return false;
649 }
650
651 return true;
652}
653
Corentin Walleze58e1412016-07-18 16:40:46 -0400654void ExpandVariable(const ShaderVariable &variable,
655 const std::string &name,
656 const std::string &mappedName,
657 bool markStaticUse,
658 std::vector<ShaderVariable> *expanded)
659{
660 if (variable.isStruct())
661 {
662 if (variable.isArray())
663 {
664 for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
665 elementIndex++)
666 {
667 std::string lname = name + ::ArrayString(elementIndex);
668 std::string lmappedName = mappedName + ::ArrayString(elementIndex);
669 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
670 }
671 }
672 else
673 {
674 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
675 }
676 }
677 else
678 {
679 ShaderVariable expandedVar = variable;
680
681 expandedVar.name = name;
682 expandedVar.mappedName = mappedName;
683
684 // Mark all expanded fields as used if the parent is used
685 if (markStaticUse)
686 {
687 expandedVar.staticUse = true;
688 }
689
690 if (expandedVar.isArray())
691 {
692 expandedVar.name += "[0]";
693 expandedVar.mappedName += "[0]";
694 }
695
696 expanded->push_back(expandedVar);
697 }
698}
699
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500700void ExpandUniforms(const std::vector<Uniform> &compact, std::vector<ShaderVariable> *expanded)
Jamie Madill23a8a432014-07-09 13:27:42 -0400701{
702 for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
703 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400704 const ShaderVariable &variable = compact[variableIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -0400705 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
706 }
707}
Jamie Madilla2fbb842014-09-03 09:40:47 -0400708}