blob: eb2a2d8d07269f12b3dc9a712971045d2f48ada4 [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 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070058 for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
59 elementIndex++)
Jamie Madill23a8a432014-07-09 13:27:42 -040060 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040061 std::string lname = name + ::ArrayString(elementIndex);
62 std::string lmappedName = mappedName + ::ArrayString(elementIndex);
Jamie Madill23a8a432014-07-09 13:27:42 -040063 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
64 }
65 }
66 else
67 {
68 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
69 }
Jamie Madill4667c452014-07-08 15:02:36 -040070 }
71 else
72 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040073 ShaderVariable expandedVar = variable;
Jamie Madill23a8a432014-07-09 13:27:42 -040074
75 expandedVar.name = name;
76 expandedVar.mappedName = mappedName;
77
78 // Mark all expanded fields as used if the parent is used
79 if (markStaticUse)
80 {
81 expandedVar.staticUse = true;
82 }
83
84 if (expandedVar.isArray())
85 {
86 expandedVar.name += "[0]";
87 expandedVar.mappedName += "[0]";
88 }
89
90 expanded->push_back(expandedVar);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000091 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000092}
93
Jamie Madilla2fbb842014-09-03 09:40:47 -040094void ExpandUserDefinedVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040095 const std::string &name,
96 const std::string &mappedName,
97 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040098 std::vector<ShaderVariable> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000099{
Jamie Madill23a8a432014-07-09 13:27:42 -0400100 ASSERT(variable.isStruct());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000101
Jamie Madilla2fbb842014-09-03 09:40:47 -0400102 const std::vector<ShaderVariable> &fields = variable.fields;
Jamie Madill23a8a432014-07-09 13:27:42 -0400103
104 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
Jamie Madill4667c452014-07-08 15:02:36 -0400105 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400106 const ShaderVariable &field = fields[fieldIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -0400107 ExpandVariable(field,
108 name + "." + field.name,
109 mappedName + "." + field.mappedName,
110 markStaticUse,
111 expanded);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000112 }
113}
114
Jamie Madilla718c1e2014-07-02 15:31:22 -0400115template <class VarT>
Jamie Madill54ad4f82014-09-03 09:40:46 -0400116VarT *FindVariable(const TString &name,
117 std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400118{
119 // TODO(zmo): optimize this function.
Jamie Madilla718c1e2014-07-02 15:31:22 -0400120 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400121 {
Jamie Madill23a8a432014-07-09 13:27:42 -0400122 if ((*infoList)[ii].name.c_str() == name)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400123 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400124 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400125
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400126 return NULL;
127}
128
Jamie Madill54ad4f82014-09-03 09:40:46 -0400129}
130
Jamie Madilla718c1e2014-07-02 15:31:22 -0400131CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
Jamie Madilla0a9e122015-09-02 15:54:30 -0400132 std::vector<sh::OutputVariable> *outputVariables,
Jamie Madilla718c1e2014-07-02 15:31:22 -0400133 std::vector<sh::Uniform> *uniforms,
134 std::vector<sh::Varying> *varyings,
Jamie Madilld5512cd2014-07-10 17:50:08 -0400135 std::vector<sh::InterfaceBlock> *interfaceBlocks,
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700136 ShHashFunction64 hashFunction,
137 const TSymbolTable &symbolTable)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300138 : TIntermTraverser(true, false, false),
139 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400140 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000141 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400142 mVaryings(varyings),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400143 mInterfaceBlocks(interfaceBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400144 mDepthRangeAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400145 mPointCoordAdded(false),
146 mFrontFacingAdded(false),
147 mFragCoordAdded(false),
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000148 mInstanceIDAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700149 mPositionAdded(false),
150 mPointSizeAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100151 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300152 mFragColorAdded(false),
153 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300154 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300155 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300156 mSecondaryFragColorEXTAdded(false),
157 mSecondaryFragDataEXTAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700158 mHashFunction(hashFunction),
159 mSymbolTable(symbolTable)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000160{
161}
162
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400163// We want to check whether a uniform/varying is statically used
164// because we only count the used ones in packing computing.
165// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
166// toward varying counting if they are statically used in a fragment
167// shader.
Jamie Madill4667c452014-07-08 15:02:36 -0400168void CollectVariables::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000169{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400170 ASSERT(symbol != NULL);
Jamie Madilla2fbb842014-09-03 09:40:47 -0400171 ShaderVariable *var = NULL;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400172 const TString &symbolName = symbol->getSymbol();
Jamie Madill4667c452014-07-08 15:02:36 -0400173
Jamie Madilla2fbb842014-09-03 09:40:47 -0400174 if (IsVarying(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400175 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400176 var = FindVariable(symbolName, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400177 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400178 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
179 {
180 UNREACHABLE();
181 }
Jamie Madill55def582015-05-04 11:24:57 -0400182 else if (symbolName == "gl_DepthRange")
183 {
184 ASSERT(symbol->getQualifier() == EvqUniform);
185
186 if (!mDepthRangeAdded)
187 {
188 Uniform info;
189 const char kName[] = "gl_DepthRange";
190 info.name = kName;
191 info.mappedName = kName;
192 info.type = GL_STRUCT_ANGLEX;
193 info.arraySize = 0;
194 info.precision = GL_NONE;
195 info.staticUse = true;
196
197 ShaderVariable nearInfo;
198 const char kNearName[] = "near";
199 nearInfo.name = kNearName;
200 nearInfo.mappedName = kNearName;
201 nearInfo.type = GL_FLOAT;
202 nearInfo.arraySize = 0;
203 nearInfo.precision = GL_HIGH_FLOAT;
204 nearInfo.staticUse = true;
205
206 ShaderVariable farInfo;
207 const char kFarName[] = "far";
208 farInfo.name = kFarName;
209 farInfo.mappedName = kFarName;
210 farInfo.type = GL_FLOAT;
211 farInfo.arraySize = 0;
212 farInfo.precision = GL_HIGH_FLOAT;
213 farInfo.staticUse = true;
214
215 ShaderVariable diffInfo;
216 const char kDiffName[] = "diff";
217 diffInfo.name = kDiffName;
218 diffInfo.mappedName = kDiffName;
219 diffInfo.type = GL_FLOAT;
220 diffInfo.arraySize = 0;
221 diffInfo.precision = GL_HIGH_FLOAT;
222 diffInfo.staticUse = true;
223
224 info.fields.push_back(nearInfo);
225 info.fields.push_back(farInfo);
226 info.fields.push_back(diffInfo);
227
228 mUniforms->push_back(info);
229 mDepthRangeAdded = true;
230 }
231 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400232 else
Jamie Madill4667c452014-07-08 15:02:36 -0400233 {
234 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400235 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400236 case EvqAttribute:
237 case EvqVertexIn:
238 var = FindVariable(symbolName, mAttribs);
239 break;
240 case EvqFragmentOut:
241 var = FindVariable(symbolName, mOutputVariables);
242 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400243 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400244 {
245 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
246 if (interfaceBlock)
247 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400248 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400249 ASSERT(namedBlock);
250 var = FindVariable(symbolName, &namedBlock->fields);
251
252 // Set static use on the parent interface block here
253 namedBlock->staticUse = true;
254 }
255 else
256 {
257 var = FindVariable(symbolName, mUniforms);
258 }
259
260 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400261 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400262 }
Jamie Madill4667c452014-07-08 15:02:36 -0400263 break;
264 case EvqFragCoord:
265 if (!mFragCoordAdded)
266 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400267 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700268 const char kName[] = "gl_FragCoord";
269 info.name = kName;
270 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400271 info.type = GL_FLOAT_VEC4;
272 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700273 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400274 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700275 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400276 mVaryings->push_back(info);
277 mFragCoordAdded = true;
278 }
279 return;
280 case EvqFrontFacing:
281 if (!mFrontFacingAdded)
282 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400283 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700284 const char kName[] = "gl_FrontFacing";
285 info.name = kName;
286 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400287 info.type = GL_BOOL;
288 info.arraySize = 0;
289 info.precision = GL_NONE;
290 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700291 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400292 mVaryings->push_back(info);
293 mFrontFacingAdded = true;
294 }
295 return;
296 case EvqPointCoord:
297 if (!mPointCoordAdded)
298 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400299 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700300 const char kName[] = "gl_PointCoord";
301 info.name = kName;
302 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400303 info.type = GL_FLOAT_VEC2;
304 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700305 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400306 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700307 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400308 mVaryings->push_back(info);
309 mPointCoordAdded = true;
310 }
311 return;
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000312 case EvqInstanceID:
313 if (!mInstanceIDAdded)
314 {
315 Attribute info;
316 const char kName[] = "gl_InstanceID";
317 info.name = kName;
318 info.mappedName = kName;
319 info.type = GL_INT;
320 info.arraySize = 0;
321 info.precision = GL_HIGH_INT; // Defined by spec.
322 info.staticUse = true;
323 info.location = -1;
324 mAttribs->push_back(info);
325 mInstanceIDAdded = true;
326 }
327 return;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700328 case EvqPosition:
329 if (!mPositionAdded)
330 {
331 Varying info;
332 const char kName[] = "gl_Position";
333 info.name = kName;
334 info.mappedName = kName;
335 info.type = GL_FLOAT_VEC4;
336 info.arraySize = 0;
337 info.precision = GL_HIGH_FLOAT; // Defined by spec.
338 info.staticUse = true;
339 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
340 mVaryings->push_back(info);
341 mPositionAdded = true;
342 }
343 return;
344 case EvqPointSize:
345 if (!mPointSizeAdded)
346 {
347 Varying info;
348 const char kName[] = "gl_PointSize";
349 info.name = kName;
350 info.mappedName = kName;
351 info.type = GL_FLOAT;
352 info.arraySize = 0;
353 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
354 info.staticUse = true;
355 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
356 mVaryings->push_back(info);
357 mPointSizeAdded = true;
358 }
359 return;
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100360 case EvqLastFragData:
361 if (!mLastFragDataAdded)
362 {
363 Varying info;
364 const char kName[] = "gl_LastFragData";
365 info.name = kName;
366 info.mappedName = kName;
367 info.type = GL_FLOAT_VEC4;
368 info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
369 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
370 info.staticUse = true;
371 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
372 mVaryings->push_back(info);
373 mLastFragDataAdded = true;
374 }
375 return;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300376 case EvqFragColor:
377 if (!mFragColorAdded)
378 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400379 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300380 const char kName[] = "gl_FragColor";
381 info.name = kName;
382 info.mappedName = kName;
383 info.type = GL_FLOAT_VEC4;
384 info.arraySize = 0;
385 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
386 info.staticUse = true;
387 mOutputVariables->push_back(info);
388 mFragColorAdded = true;
389 }
390 return;
391 case EvqFragData:
392 if (!mFragDataAdded)
393 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400394 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300395 const char kName[] = "gl_FragData";
396 info.name = kName;
397 info.mappedName = kName;
398 info.type = GL_FLOAT_VEC4;
399 info.arraySize = static_cast<const TVariable *>(
400 mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
401 ->getConstPointer()
402 ->getIConst();
403 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
404 info.staticUse = true;
405 mOutputVariables->push_back(info);
406 mFragDataAdded = true;
407 }
408 return;
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300409 case EvqFragDepthEXT:
410 if (!mFragDepthEXTAdded)
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300411 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400412 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300413 const char kName[] = "gl_FragDepthEXT";
414 info.name = kName;
415 info.mappedName = kName;
416 info.type = GL_FLOAT;
417 info.arraySize = 0;
418 info.precision =
419 GLVariablePrecision(static_cast<const TVariable *>(
420 mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
421 ->getType());
422 info.staticUse = true;
423 mOutputVariables->push_back(info);
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300424 mFragDepthEXTAdded = true;
425 }
426 return;
427 case EvqFragDepth:
428 if (!mFragDepthAdded)
429 {
430 OutputVariable info;
431 const char kName[] = "gl_FragDepth";
432 info.name = kName;
433 info.mappedName = kName;
434 info.type = GL_FLOAT;
435 info.arraySize = 0;
436 info.precision = GL_HIGH_FLOAT;
437 info.staticUse = true;
438 mOutputVariables->push_back(info);
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300439 mFragDepthAdded = true;
440 }
441 return;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300442 case EvqSecondaryFragColorEXT:
443 if (!mSecondaryFragColorEXTAdded)
444 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400445 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300446 const char kName[] = "gl_SecondaryFragColorEXT";
447 info.name = kName;
448 info.mappedName = kName;
449 info.type = GL_FLOAT_VEC4;
450 info.arraySize = 0;
451 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
452 info.staticUse = true;
453 mOutputVariables->push_back(info);
454 mSecondaryFragColorEXTAdded = true;
455 }
456 return;
457 case EvqSecondaryFragDataEXT:
458 if (!mSecondaryFragDataEXTAdded)
459 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400460 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300461 const char kName[] = "gl_SecondaryFragDataEXT";
462 info.name = kName;
463 info.mappedName = kName;
464 info.type = GL_FLOAT_VEC4;
465
466 const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
467 mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
468 info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
469 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
470 info.staticUse = true;
471 mOutputVariables->push_back(info);
472 mSecondaryFragDataEXTAdded = true;
473 }
474 return;
Jamie Madill4667c452014-07-08 15:02:36 -0400475 default:
476 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400477 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400478 }
479 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400480 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400481 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400482 }
483}
484
Jamie Madilla2fbb842014-09-03 09:40:47 -0400485class NameHashingTraverser : public GetVariableTraverser
Jamie Madill23a8a432014-07-09 13:27:42 -0400486{
487 public:
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700488 NameHashingTraverser(ShHashFunction64 hashFunction,
489 const TSymbolTable &symbolTable)
490 : GetVariableTraverser(symbolTable),
491 mHashFunction(hashFunction)
Jamie Madill23a8a432014-07-09 13:27:42 -0400492 {}
493
494 private:
Corentin Walleze5a1f272015-08-21 02:58:25 +0200495 void visitVariable(ShaderVariable *variable) override
Jamie Madill23a8a432014-07-09 13:27:42 -0400496 {
497 TString stringName = TString(variable->name.c_str());
498 variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
499 }
500
501 ShHashFunction64 mHashFunction;
502};
503
504// Attributes, which cannot have struct fields, are a special case
505template <>
506void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400507 std::vector<Attribute> *infoList) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400508{
509 ASSERT(variable);
510 const TType &type = variable->getType();
511 ASSERT(!type.getStruct());
512
Jamie Madilla2fbb842014-09-03 09:40:47 -0400513 Attribute attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400514
Jamie Madilla2fbb842014-09-03 09:40:47 -0400515 attribute.type = GLVariableType(type);
516 attribute.precision = GLVariablePrecision(type);
Jamie Madill23a8a432014-07-09 13:27:42 -0400517 attribute.name = variable->getSymbol().c_str();
518 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
519 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
520 attribute.location = variable->getType().getLayoutQualifier().location;
521
522 infoList->push_back(attribute);
523}
524
Jamie Madilld5512cd2014-07-10 17:50:08 -0400525template <>
526void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla0a9e122015-09-02 15:54:30 -0400527 std::vector<OutputVariable> *infoList) const
528{
529 ASSERT(variable);
530 const TType &type = variable->getType();
531 ASSERT(!type.getStruct());
532
533 OutputVariable attribute;
534
535 attribute.type = GLVariableType(type);
536 attribute.precision = GLVariablePrecision(type);
537 attribute.name = variable->getSymbol().c_str();
538 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
539 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
540 attribute.location = variable->getType().getLayoutQualifier().location;
541
542 infoList->push_back(attribute);
543}
544
545template <>
546void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400547 std::vector<InterfaceBlock> *infoList) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400548{
Jamie Madilla2fbb842014-09-03 09:40:47 -0400549 InterfaceBlock interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400550 const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400551 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400552
553 interfaceBlock.name = blockType->name().c_str();
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500554 interfaceBlock.mappedName =
555 TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
Jamie Madill42bcf322014-08-25 16:20:46 -0400556 interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
Jamie Madilld5512cd2014-07-10 17:50:08 -0400557 interfaceBlock.arraySize = variable->getArraySize();
Jamie Madill42bcf322014-08-25 16:20:46 -0400558 interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400559 interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400560
Jamie Madilla6f267f2014-08-27 11:44:15 -0400561 // Gather field information
Jamie Madill54ad4f82014-09-03 09:40:46 -0400562 const TFieldList &fieldList = blockType->fields();
563
564 for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex)
565 {
566 const TField &field = *fieldList[fieldIndex];
567 const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
568 const TType &fieldType = *field.type();
569
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500570 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400571 traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
572
573 interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
574 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400575
576 infoList->push_back(interfaceBlock);
577}
578
Jamie Madill23a8a432014-07-09 13:27:42 -0400579template <typename VarT>
Jamie Madill4667c452014-07-08 15:02:36 -0400580void CollectVariables::visitVariable(const TIntermSymbol *variable,
581 std::vector<VarT> *infoList) const
582{
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700583 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill42bcf322014-08-25 16:20:46 -0400584 traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
Jamie Madill4667c452014-07-08 15:02:36 -0400585}
586
587template <typename VarT>
588void CollectVariables::visitInfoList(const TIntermSequence &sequence,
589 std::vector<VarT> *infoList) const
Jamie Madilla718c1e2014-07-02 15:31:22 -0400590{
591 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
592 {
Jamie Madill4667c452014-07-08 15:02:36 -0400593 const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
Jamie Madilla718c1e2014-07-02 15:31:22 -0400594 // The only case in which the sequence will not contain a
595 // TIntermSymbol node is initialization. It will contain a
596 // TInterBinary node in that case. Since attributes, uniforms,
597 // and varyings cannot be initialized in a shader, we must have
598 // only TIntermSymbol nodes in the sequence.
599 ASSERT(variable != NULL);
Jamie Madill4667c452014-07-08 15:02:36 -0400600 visitVariable(variable, infoList);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400601 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000602}
603
Jamie Madill4667c452014-07-08 15:02:36 -0400604bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000605{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400606 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000607
608 switch (node->getOp())
609 {
Jamie Madill4667c452014-07-08 15:02:36 -0400610 case EOpDeclaration:
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000611 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700612 const TIntermSequence &sequence = *(node->getSequence());
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400613 ASSERT(!sequence.empty());
614
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700615 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400616 TQualifier qualifier = typedNode.getQualifier();
617
618 if (typedNode.getBasicType() == EbtInterfaceBlock)
619 {
620 visitInfoList(sequence, mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400621 visitChildren = false;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400622 }
623 else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
624 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
Jamie Madilla2fbb842014-09-03 09:40:47 -0400625 IsVarying(qualifier))
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400626 {
Jamie Madill4667c452014-07-08 15:02:36 -0400627 switch (qualifier)
628 {
629 case EvqAttribute:
630 case EvqVertexIn:
631 visitInfoList(sequence, mAttribs);
632 break;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400633 case EvqFragmentOut:
634 visitInfoList(sequence, mOutputVariables);
635 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400636 case EvqUniform:
637 visitInfoList(sequence, mUniforms);
638 break;
639 default:
Jamie Madill3b5c2da2014-08-19 15:23:32 -0400640 visitInfoList(sequence, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400641 break;
642 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400643
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400644 visitChildren = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000645 }
Jamie Madill4667c452014-07-08 15:02:36 -0400646 break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000647 }
Jamie Madill4667c452014-07-08 15:02:36 -0400648 default: break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000649 }
650
651 return visitChildren;
652}
Jamie Madill23a8a432014-07-09 13:27:42 -0400653
Jamie Madillb547ddf2014-08-25 16:20:46 -0400654bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
655{
656 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
657 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400658 // NOTE: we do not determine static use for individual blocks of an array
659 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
660 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400661
662 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
663 ASSERT(constantUnion);
664
Jamie Madilla6f267f2014-08-27 11:44:15 -0400665 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jamie Madilla2fbb842014-09-03 09:40:47 -0400666 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400667 ASSERT(namedBlock);
668 namedBlock->staticUse = true;
669
670 unsigned int fieldIndex = constantUnion->getUConst(0);
671 ASSERT(fieldIndex < namedBlock->fields.size());
672 namedBlock->fields[fieldIndex].staticUse = true;
673 return false;
674 }
675
676 return true;
677}
678
Zhenyao Mo409078f2014-10-28 13:23:18 -0700679void ExpandUniforms(const std::vector<Uniform> &compact,
680 std::vector<ShaderVariable> *expanded)
Jamie Madill23a8a432014-07-09 13:27:42 -0400681{
682 for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
683 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400684 const ShaderVariable &variable = compact[variableIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -0400685 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
686 }
687}
688
Jamie Madilla2fbb842014-09-03 09:40:47 -0400689}