blob: 6b9c940d172e9a46662af7de878dfaaa4183c7aa [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,
73 const TSymbolTable &symbolTable)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +030074 : TIntermTraverser(true, false, false),
75 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -040076 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000077 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -040078 mVaryings(varyings),
Jamie Madilld5512cd2014-07-10 17:50:08 -040079 mInterfaceBlocks(interfaceBlocks),
Jamie Madill55def582015-05-04 11:24:57 -040080 mDepthRangeAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -040081 mPointCoordAdded(false),
82 mFrontFacingAdded(false),
83 mFragCoordAdded(false),
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +000084 mInstanceIDAdded(false),
Corentin Wallezb076add2016-01-11 16:45:46 -050085 mVertexIDAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -070086 mPositionAdded(false),
87 mPointSizeAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +010088 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +030089 mFragColorAdded(false),
90 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +030091 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +030092 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +030093 mSecondaryFragColorEXTAdded(false),
94 mSecondaryFragDataEXTAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -070095 mHashFunction(hashFunction),
96 mSymbolTable(symbolTable)
alokp@chromium.org07620a52010-09-23 17:53:56 +000097{
98}
99
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400100// We want to check whether a uniform/varying is statically used
101// because we only count the used ones in packing computing.
102// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
103// toward varying counting if they are statically used in a fragment
104// shader.
Jamie Madill4667c452014-07-08 15:02:36 -0400105void CollectVariables::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000106{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400107 ASSERT(symbol != NULL);
Jamie Madilla2fbb842014-09-03 09:40:47 -0400108 ShaderVariable *var = NULL;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400109 const TString &symbolName = symbol->getSymbol();
Jamie Madill4667c452014-07-08 15:02:36 -0400110
Jamie Madilla2fbb842014-09-03 09:40:47 -0400111 if (IsVarying(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400112 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400113 var = FindVariable(symbolName, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400114 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400115 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
116 {
117 UNREACHABLE();
118 }
Jamie Madill55def582015-05-04 11:24:57 -0400119 else if (symbolName == "gl_DepthRange")
120 {
121 ASSERT(symbol->getQualifier() == EvqUniform);
122
123 if (!mDepthRangeAdded)
124 {
125 Uniform info;
126 const char kName[] = "gl_DepthRange";
127 info.name = kName;
128 info.mappedName = kName;
129 info.type = GL_STRUCT_ANGLEX;
130 info.arraySize = 0;
131 info.precision = GL_NONE;
132 info.staticUse = true;
133
134 ShaderVariable nearInfo;
135 const char kNearName[] = "near";
136 nearInfo.name = kNearName;
137 nearInfo.mappedName = kNearName;
138 nearInfo.type = GL_FLOAT;
139 nearInfo.arraySize = 0;
140 nearInfo.precision = GL_HIGH_FLOAT;
141 nearInfo.staticUse = true;
142
143 ShaderVariable farInfo;
144 const char kFarName[] = "far";
145 farInfo.name = kFarName;
146 farInfo.mappedName = kFarName;
147 farInfo.type = GL_FLOAT;
148 farInfo.arraySize = 0;
149 farInfo.precision = GL_HIGH_FLOAT;
150 farInfo.staticUse = true;
151
152 ShaderVariable diffInfo;
153 const char kDiffName[] = "diff";
154 diffInfo.name = kDiffName;
155 diffInfo.mappedName = kDiffName;
156 diffInfo.type = GL_FLOAT;
157 diffInfo.arraySize = 0;
158 diffInfo.precision = GL_HIGH_FLOAT;
159 diffInfo.staticUse = true;
160
161 info.fields.push_back(nearInfo);
162 info.fields.push_back(farInfo);
163 info.fields.push_back(diffInfo);
164
165 mUniforms->push_back(info);
166 mDepthRangeAdded = true;
167 }
168 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400169 else
Jamie Madill4667c452014-07-08 15:02:36 -0400170 {
171 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400172 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400173 case EvqAttribute:
174 case EvqVertexIn:
175 var = FindVariable(symbolName, mAttribs);
176 break;
177 case EvqFragmentOut:
178 var = FindVariable(symbolName, mOutputVariables);
179 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400180 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400181 {
182 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
183 if (interfaceBlock)
184 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400185 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400186 ASSERT(namedBlock);
187 var = FindVariable(symbolName, &namedBlock->fields);
188
189 // Set static use on the parent interface block here
190 namedBlock->staticUse = true;
191 }
192 else
193 {
194 var = FindVariable(symbolName, mUniforms);
195 }
196
197 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400198 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400199 }
Jamie Madill4667c452014-07-08 15:02:36 -0400200 break;
201 case EvqFragCoord:
202 if (!mFragCoordAdded)
203 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400204 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700205 const char kName[] = "gl_FragCoord";
206 info.name = kName;
207 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400208 info.type = GL_FLOAT_VEC4;
209 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700210 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400211 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700212 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400213 mVaryings->push_back(info);
214 mFragCoordAdded = true;
215 }
216 return;
217 case EvqFrontFacing:
218 if (!mFrontFacingAdded)
219 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400220 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700221 const char kName[] = "gl_FrontFacing";
222 info.name = kName;
223 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400224 info.type = GL_BOOL;
225 info.arraySize = 0;
226 info.precision = GL_NONE;
227 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700228 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400229 mVaryings->push_back(info);
230 mFrontFacingAdded = true;
231 }
232 return;
233 case EvqPointCoord:
234 if (!mPointCoordAdded)
235 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400236 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700237 const char kName[] = "gl_PointCoord";
238 info.name = kName;
239 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400240 info.type = GL_FLOAT_VEC2;
241 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700242 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400243 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700244 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400245 mVaryings->push_back(info);
246 mPointCoordAdded = true;
247 }
248 return;
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000249 case EvqInstanceID:
250 if (!mInstanceIDAdded)
251 {
252 Attribute info;
253 const char kName[] = "gl_InstanceID";
254 info.name = kName;
255 info.mappedName = kName;
256 info.type = GL_INT;
257 info.arraySize = 0;
258 info.precision = GL_HIGH_INT; // Defined by spec.
259 info.staticUse = true;
260 info.location = -1;
261 mAttribs->push_back(info);
262 mInstanceIDAdded = true;
263 }
264 return;
Corentin Wallezb076add2016-01-11 16:45:46 -0500265 case EvqVertexID:
266 if (!mVertexIDAdded)
267 {
268 Attribute info;
269 const char kName[] = "gl_VertexID";
270 info.name = kName;
271 info.mappedName = kName;
272 info.type = GL_INT;
273 info.arraySize = 0;
274 info.precision = GL_HIGH_INT; // Defined by spec.
275 info.staticUse = true;
276 info.location = -1;
277 mAttribs->push_back(info);
278 mVertexIDAdded = true;
279 }
280 return;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700281 case EvqPosition:
282 if (!mPositionAdded)
283 {
284 Varying info;
285 const char kName[] = "gl_Position";
286 info.name = kName;
287 info.mappedName = kName;
288 info.type = GL_FLOAT_VEC4;
289 info.arraySize = 0;
290 info.precision = GL_HIGH_FLOAT; // Defined by spec.
291 info.staticUse = true;
292 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
293 mVaryings->push_back(info);
294 mPositionAdded = true;
295 }
296 return;
297 case EvqPointSize:
298 if (!mPointSizeAdded)
299 {
300 Varying info;
301 const char kName[] = "gl_PointSize";
302 info.name = kName;
303 info.mappedName = kName;
304 info.type = GL_FLOAT;
305 info.arraySize = 0;
306 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
307 info.staticUse = true;
308 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
309 mVaryings->push_back(info);
310 mPointSizeAdded = true;
311 }
312 return;
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100313 case EvqLastFragData:
314 if (!mLastFragDataAdded)
315 {
316 Varying info;
317 const char kName[] = "gl_LastFragData";
318 info.name = kName;
319 info.mappedName = kName;
320 info.type = GL_FLOAT_VEC4;
321 info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
322 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
323 info.staticUse = true;
324 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
325 mVaryings->push_back(info);
326 mLastFragDataAdded = true;
327 }
328 return;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300329 case EvqFragColor:
330 if (!mFragColorAdded)
331 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400332 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300333 const char kName[] = "gl_FragColor";
334 info.name = kName;
335 info.mappedName = kName;
336 info.type = GL_FLOAT_VEC4;
337 info.arraySize = 0;
338 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
339 info.staticUse = true;
340 mOutputVariables->push_back(info);
341 mFragColorAdded = true;
342 }
343 return;
344 case EvqFragData:
345 if (!mFragDataAdded)
346 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400347 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300348 const char kName[] = "gl_FragData";
349 info.name = kName;
350 info.mappedName = kName;
351 info.type = GL_FLOAT_VEC4;
352 info.arraySize = static_cast<const TVariable *>(
353 mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
354 ->getConstPointer()
355 ->getIConst();
356 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
357 info.staticUse = true;
358 mOutputVariables->push_back(info);
359 mFragDataAdded = true;
360 }
361 return;
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300362 case EvqFragDepthEXT:
363 if (!mFragDepthEXTAdded)
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300364 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400365 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300366 const char kName[] = "gl_FragDepthEXT";
367 info.name = kName;
368 info.mappedName = kName;
369 info.type = GL_FLOAT;
370 info.arraySize = 0;
371 info.precision =
372 GLVariablePrecision(static_cast<const TVariable *>(
373 mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
374 ->getType());
375 info.staticUse = true;
376 mOutputVariables->push_back(info);
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300377 mFragDepthEXTAdded = true;
378 }
379 return;
380 case EvqFragDepth:
381 if (!mFragDepthAdded)
382 {
383 OutputVariable info;
384 const char kName[] = "gl_FragDepth";
385 info.name = kName;
386 info.mappedName = kName;
387 info.type = GL_FLOAT;
388 info.arraySize = 0;
389 info.precision = GL_HIGH_FLOAT;
390 info.staticUse = true;
391 mOutputVariables->push_back(info);
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300392 mFragDepthAdded = true;
393 }
394 return;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300395 case EvqSecondaryFragColorEXT:
396 if (!mSecondaryFragColorEXTAdded)
397 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400398 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300399 const char kName[] = "gl_SecondaryFragColorEXT";
400 info.name = kName;
401 info.mappedName = kName;
402 info.type = GL_FLOAT_VEC4;
403 info.arraySize = 0;
404 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
405 info.staticUse = true;
406 mOutputVariables->push_back(info);
407 mSecondaryFragColorEXTAdded = true;
408 }
409 return;
410 case EvqSecondaryFragDataEXT:
411 if (!mSecondaryFragDataEXTAdded)
412 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400413 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300414 const char kName[] = "gl_SecondaryFragDataEXT";
415 info.name = kName;
416 info.mappedName = kName;
417 info.type = GL_FLOAT_VEC4;
418
419 const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
420 mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
421 info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
422 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
423 info.staticUse = true;
424 mOutputVariables->push_back(info);
425 mSecondaryFragDataEXTAdded = true;
426 }
427 return;
Jamie Madill4667c452014-07-08 15:02:36 -0400428 default:
429 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400430 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400431 }
432 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400433 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400434 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400435 }
436}
437
Jamie Madilla2fbb842014-09-03 09:40:47 -0400438class NameHashingTraverser : public GetVariableTraverser
Jamie Madill23a8a432014-07-09 13:27:42 -0400439{
440 public:
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700441 NameHashingTraverser(ShHashFunction64 hashFunction,
442 const TSymbolTable &symbolTable)
443 : GetVariableTraverser(symbolTable),
444 mHashFunction(hashFunction)
Jamie Madill23a8a432014-07-09 13:27:42 -0400445 {}
446
447 private:
Corentin Walleze5a1f272015-08-21 02:58:25 +0200448 void visitVariable(ShaderVariable *variable) override
Jamie Madill23a8a432014-07-09 13:27:42 -0400449 {
450 TString stringName = TString(variable->name.c_str());
451 variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
452 }
453
454 ShHashFunction64 mHashFunction;
455};
456
457// Attributes, which cannot have struct fields, are a special case
458template <>
459void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400460 std::vector<Attribute> *infoList) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400461{
462 ASSERT(variable);
463 const TType &type = variable->getType();
464 ASSERT(!type.getStruct());
465
Jamie Madilla2fbb842014-09-03 09:40:47 -0400466 Attribute attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400467
Jamie Madilla2fbb842014-09-03 09:40:47 -0400468 attribute.type = GLVariableType(type);
469 attribute.precision = GLVariablePrecision(type);
Jamie Madill23a8a432014-07-09 13:27:42 -0400470 attribute.name = variable->getSymbol().c_str();
471 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
472 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
473 attribute.location = variable->getType().getLayoutQualifier().location;
474
475 infoList->push_back(attribute);
476}
477
Jamie Madilld5512cd2014-07-10 17:50:08 -0400478template <>
479void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla0a9e122015-09-02 15:54:30 -0400480 std::vector<OutputVariable> *infoList) const
481{
482 ASSERT(variable);
483 const TType &type = variable->getType();
484 ASSERT(!type.getStruct());
485
486 OutputVariable attribute;
487
488 attribute.type = GLVariableType(type);
489 attribute.precision = GLVariablePrecision(type);
490 attribute.name = variable->getSymbol().c_str();
491 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
492 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
493 attribute.location = variable->getType().getLayoutQualifier().location;
494
495 infoList->push_back(attribute);
496}
497
498template <>
499void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400500 std::vector<InterfaceBlock> *infoList) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400501{
Jamie Madilla2fbb842014-09-03 09:40:47 -0400502 InterfaceBlock interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400503 const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400504 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400505
506 interfaceBlock.name = blockType->name().c_str();
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500507 interfaceBlock.mappedName =
508 TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
Jamie Madill42bcf322014-08-25 16:20:46 -0400509 interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
Jamie Madilld5512cd2014-07-10 17:50:08 -0400510 interfaceBlock.arraySize = variable->getArraySize();
Jamie Madill42bcf322014-08-25 16:20:46 -0400511 interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400512 interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400513
Jamie Madilla6f267f2014-08-27 11:44:15 -0400514 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500515 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400516 {
Jamie Madill39046162016-02-08 15:05:17 -0500517 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400518
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500519 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill39046162016-02-08 15:05:17 -0500520 traverser.traverse(fieldType, field->name(), &interfaceBlock.fields);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400521
522 interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
523 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400524
525 infoList->push_back(interfaceBlock);
526}
527
Jamie Madill23a8a432014-07-09 13:27:42 -0400528template <typename VarT>
Jamie Madill4667c452014-07-08 15:02:36 -0400529void CollectVariables::visitVariable(const TIntermSymbol *variable,
530 std::vector<VarT> *infoList) const
531{
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700532 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill42bcf322014-08-25 16:20:46 -0400533 traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
Jamie Madill4667c452014-07-08 15:02:36 -0400534}
535
536template <typename VarT>
537void CollectVariables::visitInfoList(const TIntermSequence &sequence,
538 std::vector<VarT> *infoList) const
Jamie Madilla718c1e2014-07-02 15:31:22 -0400539{
540 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
541 {
Jamie Madill4667c452014-07-08 15:02:36 -0400542 const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
Jamie Madilla718c1e2014-07-02 15:31:22 -0400543 // The only case in which the sequence will not contain a
544 // TIntermSymbol node is initialization. It will contain a
545 // TInterBinary node in that case. Since attributes, uniforms,
546 // and varyings cannot be initialized in a shader, we must have
547 // only TIntermSymbol nodes in the sequence.
548 ASSERT(variable != NULL);
Jamie Madill4667c452014-07-08 15:02:36 -0400549 visitVariable(variable, infoList);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400550 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000551}
552
Jamie Madill4667c452014-07-08 15:02:36 -0400553bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000554{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400555 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000556
557 switch (node->getOp())
558 {
Jamie Madill4667c452014-07-08 15:02:36 -0400559 case EOpDeclaration:
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000560 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700561 const TIntermSequence &sequence = *(node->getSequence());
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400562 ASSERT(!sequence.empty());
563
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700564 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400565 TQualifier qualifier = typedNode.getQualifier();
566
567 if (typedNode.getBasicType() == EbtInterfaceBlock)
568 {
569 visitInfoList(sequence, mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400570 visitChildren = false;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400571 }
572 else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
573 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
Jamie Madilla2fbb842014-09-03 09:40:47 -0400574 IsVarying(qualifier))
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400575 {
Jamie Madill4667c452014-07-08 15:02:36 -0400576 switch (qualifier)
577 {
578 case EvqAttribute:
579 case EvqVertexIn:
580 visitInfoList(sequence, mAttribs);
581 break;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400582 case EvqFragmentOut:
583 visitInfoList(sequence, mOutputVariables);
584 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400585 case EvqUniform:
586 visitInfoList(sequence, mUniforms);
587 break;
588 default:
Jamie Madill3b5c2da2014-08-19 15:23:32 -0400589 visitInfoList(sequence, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400590 break;
591 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400592
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400593 visitChildren = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000594 }
Jamie Madill4667c452014-07-08 15:02:36 -0400595 break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000596 }
Jamie Madill4667c452014-07-08 15:02:36 -0400597 default: break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000598 }
599
600 return visitChildren;
601}
Jamie Madill23a8a432014-07-09 13:27:42 -0400602
Jamie Madillb547ddf2014-08-25 16:20:46 -0400603bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
604{
605 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
606 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400607 // NOTE: we do not determine static use for individual blocks of an array
608 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
609 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400610
611 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
612 ASSERT(constantUnion);
613
Jamie Madilla6f267f2014-08-27 11:44:15 -0400614 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jamie Madilla2fbb842014-09-03 09:40:47 -0400615 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400616 ASSERT(namedBlock);
617 namedBlock->staticUse = true;
618
619 unsigned int fieldIndex = constantUnion->getUConst(0);
620 ASSERT(fieldIndex < namedBlock->fields.size());
621 namedBlock->fields[fieldIndex].staticUse = true;
622 return false;
623 }
624
625 return true;
626}
627
Corentin Walleze58e1412016-07-18 16:40:46 -0400628void ExpandVariable(const ShaderVariable &variable,
629 const std::string &name,
630 const std::string &mappedName,
631 bool markStaticUse,
632 std::vector<ShaderVariable> *expanded)
633{
634 if (variable.isStruct())
635 {
636 if (variable.isArray())
637 {
638 for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
639 elementIndex++)
640 {
641 std::string lname = name + ::ArrayString(elementIndex);
642 std::string lmappedName = mappedName + ::ArrayString(elementIndex);
643 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
644 }
645 }
646 else
647 {
648 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
649 }
650 }
651 else
652 {
653 ShaderVariable expandedVar = variable;
654
655 expandedVar.name = name;
656 expandedVar.mappedName = mappedName;
657
658 // Mark all expanded fields as used if the parent is used
659 if (markStaticUse)
660 {
661 expandedVar.staticUse = true;
662 }
663
664 if (expandedVar.isArray())
665 {
666 expandedVar.name += "[0]";
667 expandedVar.mappedName += "[0]";
668 }
669
670 expanded->push_back(expandedVar);
671 }
672}
673
Zhenyao Mo409078f2014-10-28 13:23:18 -0700674void ExpandUniforms(const std::vector<Uniform> &compact,
675 std::vector<ShaderVariable> *expanded)
Jamie Madill23a8a432014-07-09 13:27:42 -0400676{
677 for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
678 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400679 const ShaderVariable &variable = compact[variableIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -0400680 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
681 }
682}
683
Jamie Madilla2fbb842014-09-03 09:40:47 -0400684}