blob: 3b6aa6a68eb5ae954f9e8e6c300a0b852d894df3 [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);
Jamie Madill54ad4f82014-09-03 09:40:46 -040035
Jamie Madilla2fbb842014-09-03 09:40:47 -040036void ExpandVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040037 const std::string &name,
38 const std::string &mappedName,
39 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040040 std::vector<ShaderVariable> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000041{
Jamie Madill23a8a432014-07-09 13:27:42 -040042 if (variable.isStruct())
Jamie Madill4667c452014-07-08 15:02:36 -040043 {
Jamie Madill23a8a432014-07-09 13:27:42 -040044 if (variable.isArray())
45 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -070046 for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
47 elementIndex++)
Jamie Madill23a8a432014-07-09 13:27:42 -040048 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040049 std::string lname = name + ::ArrayString(elementIndex);
50 std::string lmappedName = mappedName + ::ArrayString(elementIndex);
Jamie Madill23a8a432014-07-09 13:27:42 -040051 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
52 }
53 }
54 else
55 {
56 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
57 }
Jamie Madill4667c452014-07-08 15:02:36 -040058 }
59 else
60 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040061 ShaderVariable expandedVar = variable;
Jamie Madill23a8a432014-07-09 13:27:42 -040062
63 expandedVar.name = name;
64 expandedVar.mappedName = mappedName;
65
66 // Mark all expanded fields as used if the parent is used
67 if (markStaticUse)
68 {
69 expandedVar.staticUse = true;
70 }
71
72 if (expandedVar.isArray())
73 {
74 expandedVar.name += "[0]";
75 expandedVar.mappedName += "[0]";
76 }
77
78 expanded->push_back(expandedVar);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000079 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000080}
81
Jamie Madilla2fbb842014-09-03 09:40:47 -040082void ExpandUserDefinedVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040083 const std::string &name,
84 const std::string &mappedName,
85 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040086 std::vector<ShaderVariable> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000087{
Jamie Madill23a8a432014-07-09 13:27:42 -040088 ASSERT(variable.isStruct());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000089
Jamie Madilla2fbb842014-09-03 09:40:47 -040090 const std::vector<ShaderVariable> &fields = variable.fields;
Jamie Madill23a8a432014-07-09 13:27:42 -040091
92 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
Jamie Madill4667c452014-07-08 15:02:36 -040093 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040094 const ShaderVariable &field = fields[fieldIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -040095 ExpandVariable(field,
96 name + "." + field.name,
97 mappedName + "." + field.mappedName,
98 markStaticUse,
99 expanded);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000100 }
101}
102
Jamie Madilla718c1e2014-07-02 15:31:22 -0400103template <class VarT>
Jamie Madill54ad4f82014-09-03 09:40:46 -0400104VarT *FindVariable(const TString &name,
105 std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400106{
107 // TODO(zmo): optimize this function.
Jamie Madilla718c1e2014-07-02 15:31:22 -0400108 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400109 {
Jamie Madill23a8a432014-07-09 13:27:42 -0400110 if ((*infoList)[ii].name.c_str() == name)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400111 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400112 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400113
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400114 return NULL;
115}
116
Jamie Madill54ad4f82014-09-03 09:40:46 -0400117}
118
Jamie Madilla718c1e2014-07-02 15:31:22 -0400119CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
Jamie Madilla0a9e122015-09-02 15:54:30 -0400120 std::vector<sh::OutputVariable> *outputVariables,
Jamie Madilla718c1e2014-07-02 15:31:22 -0400121 std::vector<sh::Uniform> *uniforms,
122 std::vector<sh::Varying> *varyings,
Jamie Madilld5512cd2014-07-10 17:50:08 -0400123 std::vector<sh::InterfaceBlock> *interfaceBlocks,
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700124 ShHashFunction64 hashFunction,
125 const TSymbolTable &symbolTable)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300126 : TIntermTraverser(true, false, false),
127 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400128 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000129 mUniforms(uniforms),
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400130 mVaryings(varyings),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400131 mInterfaceBlocks(interfaceBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400132 mDepthRangeAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400133 mPointCoordAdded(false),
134 mFrontFacingAdded(false),
135 mFragCoordAdded(false),
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000136 mInstanceIDAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700137 mPositionAdded(false),
138 mPointSizeAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100139 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300140 mFragColorAdded(false),
141 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300142 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300143 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300144 mSecondaryFragColorEXTAdded(false),
145 mSecondaryFragDataEXTAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700146 mHashFunction(hashFunction),
147 mSymbolTable(symbolTable)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000148{
149}
150
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400151// We want to check whether a uniform/varying is statically used
152// because we only count the used ones in packing computing.
153// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
154// toward varying counting if they are statically used in a fragment
155// shader.
Jamie Madill4667c452014-07-08 15:02:36 -0400156void CollectVariables::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000157{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400158 ASSERT(symbol != NULL);
Jamie Madilla2fbb842014-09-03 09:40:47 -0400159 ShaderVariable *var = NULL;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400160 const TString &symbolName = symbol->getSymbol();
Jamie Madill4667c452014-07-08 15:02:36 -0400161
Jamie Madilla2fbb842014-09-03 09:40:47 -0400162 if (IsVarying(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400163 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400164 var = FindVariable(symbolName, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400165 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400166 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
167 {
168 UNREACHABLE();
169 }
Jamie Madill55def582015-05-04 11:24:57 -0400170 else if (symbolName == "gl_DepthRange")
171 {
172 ASSERT(symbol->getQualifier() == EvqUniform);
173
174 if (!mDepthRangeAdded)
175 {
176 Uniform info;
177 const char kName[] = "gl_DepthRange";
178 info.name = kName;
179 info.mappedName = kName;
180 info.type = GL_STRUCT_ANGLEX;
181 info.arraySize = 0;
182 info.precision = GL_NONE;
183 info.staticUse = true;
184
185 ShaderVariable nearInfo;
186 const char kNearName[] = "near";
187 nearInfo.name = kNearName;
188 nearInfo.mappedName = kNearName;
189 nearInfo.type = GL_FLOAT;
190 nearInfo.arraySize = 0;
191 nearInfo.precision = GL_HIGH_FLOAT;
192 nearInfo.staticUse = true;
193
194 ShaderVariable farInfo;
195 const char kFarName[] = "far";
196 farInfo.name = kFarName;
197 farInfo.mappedName = kFarName;
198 farInfo.type = GL_FLOAT;
199 farInfo.arraySize = 0;
200 farInfo.precision = GL_HIGH_FLOAT;
201 farInfo.staticUse = true;
202
203 ShaderVariable diffInfo;
204 const char kDiffName[] = "diff";
205 diffInfo.name = kDiffName;
206 diffInfo.mappedName = kDiffName;
207 diffInfo.type = GL_FLOAT;
208 diffInfo.arraySize = 0;
209 diffInfo.precision = GL_HIGH_FLOAT;
210 diffInfo.staticUse = true;
211
212 info.fields.push_back(nearInfo);
213 info.fields.push_back(farInfo);
214 info.fields.push_back(diffInfo);
215
216 mUniforms->push_back(info);
217 mDepthRangeAdded = true;
218 }
219 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400220 else
Jamie Madill4667c452014-07-08 15:02:36 -0400221 {
222 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400223 {
Jamie Madilld5512cd2014-07-10 17:50:08 -0400224 case EvqAttribute:
225 case EvqVertexIn:
226 var = FindVariable(symbolName, mAttribs);
227 break;
228 case EvqFragmentOut:
229 var = FindVariable(symbolName, mOutputVariables);
230 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400231 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400232 {
233 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
234 if (interfaceBlock)
235 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400236 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400237 ASSERT(namedBlock);
238 var = FindVariable(symbolName, &namedBlock->fields);
239
240 // Set static use on the parent interface block here
241 namedBlock->staticUse = true;
242 }
243 else
244 {
245 var = FindVariable(symbolName, mUniforms);
246 }
247
248 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400249 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400250 }
Jamie Madill4667c452014-07-08 15:02:36 -0400251 break;
252 case EvqFragCoord:
253 if (!mFragCoordAdded)
254 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400255 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700256 const char kName[] = "gl_FragCoord";
257 info.name = kName;
258 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400259 info.type = GL_FLOAT_VEC4;
260 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700261 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400262 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700263 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400264 mVaryings->push_back(info);
265 mFragCoordAdded = true;
266 }
267 return;
268 case EvqFrontFacing:
269 if (!mFrontFacingAdded)
270 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400271 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700272 const char kName[] = "gl_FrontFacing";
273 info.name = kName;
274 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400275 info.type = GL_BOOL;
276 info.arraySize = 0;
277 info.precision = GL_NONE;
278 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700279 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400280 mVaryings->push_back(info);
281 mFrontFacingAdded = true;
282 }
283 return;
284 case EvqPointCoord:
285 if (!mPointCoordAdded)
286 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400287 Varying info;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700288 const char kName[] = "gl_PointCoord";
289 info.name = kName;
290 info.mappedName = kName;
Jamie Madill4667c452014-07-08 15:02:36 -0400291 info.type = GL_FLOAT_VEC2;
292 info.arraySize = 0;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700293 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
Jamie Madill4667c452014-07-08 15:02:36 -0400294 info.staticUse = true;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700295 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
Jamie Madill4667c452014-07-08 15:02:36 -0400296 mVaryings->push_back(info);
297 mPointCoordAdded = true;
298 }
299 return;
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000300 case EvqInstanceID:
301 if (!mInstanceIDAdded)
302 {
303 Attribute info;
304 const char kName[] = "gl_InstanceID";
305 info.name = kName;
306 info.mappedName = kName;
307 info.type = GL_INT;
308 info.arraySize = 0;
309 info.precision = GL_HIGH_INT; // Defined by spec.
310 info.staticUse = true;
311 info.location = -1;
312 mAttribs->push_back(info);
313 mInstanceIDAdded = true;
314 }
315 return;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700316 case EvqPosition:
317 if (!mPositionAdded)
318 {
319 Varying info;
320 const char kName[] = "gl_Position";
321 info.name = kName;
322 info.mappedName = kName;
323 info.type = GL_FLOAT_VEC4;
324 info.arraySize = 0;
325 info.precision = GL_HIGH_FLOAT; // Defined by spec.
326 info.staticUse = true;
327 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
328 mVaryings->push_back(info);
329 mPositionAdded = true;
330 }
331 return;
332 case EvqPointSize:
333 if (!mPointSizeAdded)
334 {
335 Varying info;
336 const char kName[] = "gl_PointSize";
337 info.name = kName;
338 info.mappedName = kName;
339 info.type = GL_FLOAT;
340 info.arraySize = 0;
341 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
342 info.staticUse = true;
343 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
344 mVaryings->push_back(info);
345 mPointSizeAdded = true;
346 }
347 return;
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100348 case EvqLastFragData:
349 if (!mLastFragDataAdded)
350 {
351 Varying info;
352 const char kName[] = "gl_LastFragData";
353 info.name = kName;
354 info.mappedName = kName;
355 info.type = GL_FLOAT_VEC4;
356 info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
357 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
358 info.staticUse = true;
359 info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
360 mVaryings->push_back(info);
361 mLastFragDataAdded = true;
362 }
363 return;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300364 case EvqFragColor:
365 if (!mFragColorAdded)
366 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400367 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300368 const char kName[] = "gl_FragColor";
369 info.name = kName;
370 info.mappedName = kName;
371 info.type = GL_FLOAT_VEC4;
372 info.arraySize = 0;
373 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
374 info.staticUse = true;
375 mOutputVariables->push_back(info);
376 mFragColorAdded = true;
377 }
378 return;
379 case EvqFragData:
380 if (!mFragDataAdded)
381 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400382 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300383 const char kName[] = "gl_FragData";
384 info.name = kName;
385 info.mappedName = kName;
386 info.type = GL_FLOAT_VEC4;
387 info.arraySize = static_cast<const TVariable *>(
388 mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
389 ->getConstPointer()
390 ->getIConst();
391 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
392 info.staticUse = true;
393 mOutputVariables->push_back(info);
394 mFragDataAdded = true;
395 }
396 return;
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300397 case EvqFragDepthEXT:
398 if (!mFragDepthEXTAdded)
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300399 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400400 OutputVariable info;
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300401 const char kName[] = "gl_FragDepthEXT";
402 info.name = kName;
403 info.mappedName = kName;
404 info.type = GL_FLOAT;
405 info.arraySize = 0;
406 info.precision =
407 GLVariablePrecision(static_cast<const TVariable *>(
408 mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
409 ->getType());
410 info.staticUse = true;
411 mOutputVariables->push_back(info);
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300412 mFragDepthEXTAdded = true;
413 }
414 return;
415 case EvqFragDepth:
416 if (!mFragDepthAdded)
417 {
418 OutputVariable info;
419 const char kName[] = "gl_FragDepth";
420 info.name = kName;
421 info.mappedName = kName;
422 info.type = GL_FLOAT;
423 info.arraySize = 0;
424 info.precision = GL_HIGH_FLOAT;
425 info.staticUse = true;
426 mOutputVariables->push_back(info);
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300427 mFragDepthAdded = true;
428 }
429 return;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300430 case EvqSecondaryFragColorEXT:
431 if (!mSecondaryFragColorEXTAdded)
432 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400433 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300434 const char kName[] = "gl_SecondaryFragColorEXT";
435 info.name = kName;
436 info.mappedName = kName;
437 info.type = GL_FLOAT_VEC4;
438 info.arraySize = 0;
439 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
440 info.staticUse = true;
441 mOutputVariables->push_back(info);
442 mSecondaryFragColorEXTAdded = true;
443 }
444 return;
445 case EvqSecondaryFragDataEXT:
446 if (!mSecondaryFragDataEXTAdded)
447 {
Jamie Madilla0a9e122015-09-02 15:54:30 -0400448 OutputVariable info;
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300449 const char kName[] = "gl_SecondaryFragDataEXT";
450 info.name = kName;
451 info.mappedName = kName;
452 info.type = GL_FLOAT_VEC4;
453
454 const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
455 mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
456 info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
457 info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
458 info.staticUse = true;
459 mOutputVariables->push_back(info);
460 mSecondaryFragDataEXTAdded = true;
461 }
462 return;
Jamie Madill4667c452014-07-08 15:02:36 -0400463 default:
464 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400465 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400466 }
467 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400468 {
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400469 var->staticUse = true;
Jamie Madilla718c1e2014-07-02 15:31:22 -0400470 }
471}
472
Jamie Madilla2fbb842014-09-03 09:40:47 -0400473class NameHashingTraverser : public GetVariableTraverser
Jamie Madill23a8a432014-07-09 13:27:42 -0400474{
475 public:
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700476 NameHashingTraverser(ShHashFunction64 hashFunction,
477 const TSymbolTable &symbolTable)
478 : GetVariableTraverser(symbolTable),
479 mHashFunction(hashFunction)
Jamie Madill23a8a432014-07-09 13:27:42 -0400480 {}
481
482 private:
Corentin Walleze5a1f272015-08-21 02:58:25 +0200483 void visitVariable(ShaderVariable *variable) override
Jamie Madill23a8a432014-07-09 13:27:42 -0400484 {
485 TString stringName = TString(variable->name.c_str());
486 variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
487 }
488
489 ShHashFunction64 mHashFunction;
490};
491
492// Attributes, which cannot have struct fields, are a special case
493template <>
494void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400495 std::vector<Attribute> *infoList) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400496{
497 ASSERT(variable);
498 const TType &type = variable->getType();
499 ASSERT(!type.getStruct());
500
Jamie Madilla2fbb842014-09-03 09:40:47 -0400501 Attribute attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400502
Jamie Madilla2fbb842014-09-03 09:40:47 -0400503 attribute.type = GLVariableType(type);
504 attribute.precision = GLVariablePrecision(type);
Jamie Madill23a8a432014-07-09 13:27:42 -0400505 attribute.name = variable->getSymbol().c_str();
506 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
507 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
508 attribute.location = variable->getType().getLayoutQualifier().location;
509
510 infoList->push_back(attribute);
511}
512
Jamie Madilld5512cd2014-07-10 17:50:08 -0400513template <>
514void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla0a9e122015-09-02 15:54:30 -0400515 std::vector<OutputVariable> *infoList) const
516{
517 ASSERT(variable);
518 const TType &type = variable->getType();
519 ASSERT(!type.getStruct());
520
521 OutputVariable attribute;
522
523 attribute.type = GLVariableType(type);
524 attribute.precision = GLVariablePrecision(type);
525 attribute.name = variable->getSymbol().c_str();
526 attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
527 attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
528 attribute.location = variable->getType().getLayoutQualifier().location;
529
530 infoList->push_back(attribute);
531}
532
533template <>
534void CollectVariables::visitVariable(const TIntermSymbol *variable,
Jamie Madilla2fbb842014-09-03 09:40:47 -0400535 std::vector<InterfaceBlock> *infoList) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400536{
Jamie Madilla2fbb842014-09-03 09:40:47 -0400537 InterfaceBlock interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400538 const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400539 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400540
541 interfaceBlock.name = blockType->name().c_str();
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500542 interfaceBlock.mappedName =
543 TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
Jamie Madill42bcf322014-08-25 16:20:46 -0400544 interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
Jamie Madilld5512cd2014-07-10 17:50:08 -0400545 interfaceBlock.arraySize = variable->getArraySize();
Jamie Madill42bcf322014-08-25 16:20:46 -0400546 interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400547 interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400548
Jamie Madilla6f267f2014-08-27 11:44:15 -0400549 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500550 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400551 {
Jamie Madill39046162016-02-08 15:05:17 -0500552 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400553
Jeff Muizelaardbfdca82015-11-06 12:46:30 -0500554 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill39046162016-02-08 15:05:17 -0500555 traverser.traverse(fieldType, field->name(), &interfaceBlock.fields);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400556
557 interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
558 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400559
560 infoList->push_back(interfaceBlock);
561}
562
Jamie Madill23a8a432014-07-09 13:27:42 -0400563template <typename VarT>
Jamie Madill4667c452014-07-08 15:02:36 -0400564void CollectVariables::visitVariable(const TIntermSymbol *variable,
565 std::vector<VarT> *infoList) const
566{
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700567 NameHashingTraverser traverser(mHashFunction, mSymbolTable);
Jamie Madill42bcf322014-08-25 16:20:46 -0400568 traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
Jamie Madill4667c452014-07-08 15:02:36 -0400569}
570
571template <typename VarT>
572void CollectVariables::visitInfoList(const TIntermSequence &sequence,
573 std::vector<VarT> *infoList) const
Jamie Madilla718c1e2014-07-02 15:31:22 -0400574{
575 for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
576 {
Jamie Madill4667c452014-07-08 15:02:36 -0400577 const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
Jamie Madilla718c1e2014-07-02 15:31:22 -0400578 // The only case in which the sequence will not contain a
579 // TIntermSymbol node is initialization. It will contain a
580 // TInterBinary node in that case. Since attributes, uniforms,
581 // and varyings cannot be initialized in a shader, we must have
582 // only TIntermSymbol nodes in the sequence.
583 ASSERT(variable != NULL);
Jamie Madill4667c452014-07-08 15:02:36 -0400584 visitVariable(variable, infoList);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400585 }
alokp@chromium.org07620a52010-09-23 17:53:56 +0000586}
587
Jamie Madill4667c452014-07-08 15:02:36 -0400588bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000589{
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400590 bool visitChildren = true;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000591
592 switch (node->getOp())
593 {
Jamie Madill4667c452014-07-08 15:02:36 -0400594 case EOpDeclaration:
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000595 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700596 const TIntermSequence &sequence = *(node->getSequence());
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400597 ASSERT(!sequence.empty());
598
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700599 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400600 TQualifier qualifier = typedNode.getQualifier();
601
602 if (typedNode.getBasicType() == EbtInterfaceBlock)
603 {
604 visitInfoList(sequence, mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400605 visitChildren = false;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400606 }
607 else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
608 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
Jamie Madilla2fbb842014-09-03 09:40:47 -0400609 IsVarying(qualifier))
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400610 {
Jamie Madill4667c452014-07-08 15:02:36 -0400611 switch (qualifier)
612 {
613 case EvqAttribute:
614 case EvqVertexIn:
615 visitInfoList(sequence, mAttribs);
616 break;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400617 case EvqFragmentOut:
618 visitInfoList(sequence, mOutputVariables);
619 break;
Jamie Madill4667c452014-07-08 15:02:36 -0400620 case EvqUniform:
621 visitInfoList(sequence, mUniforms);
622 break;
623 default:
Jamie Madill3b5c2da2014-08-19 15:23:32 -0400624 visitInfoList(sequence, mVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400625 break;
626 }
Zhenyao Mo74da9f22013-09-23 14:57:01 -0400627
Jamie Madill1c28e1f2014-08-04 11:37:54 -0400628 visitChildren = false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000629 }
Jamie Madill4667c452014-07-08 15:02:36 -0400630 break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000631 }
Jamie Madill4667c452014-07-08 15:02:36 -0400632 default: break;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000633 }
634
635 return visitChildren;
636}
Jamie Madill23a8a432014-07-09 13:27:42 -0400637
Jamie Madillb547ddf2014-08-25 16:20:46 -0400638bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
639{
640 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
641 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400642 // NOTE: we do not determine static use for individual blocks of an array
643 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
644 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400645
646 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
647 ASSERT(constantUnion);
648
Jamie Madilla6f267f2014-08-27 11:44:15 -0400649 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jamie Madilla2fbb842014-09-03 09:40:47 -0400650 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400651 ASSERT(namedBlock);
652 namedBlock->staticUse = true;
653
654 unsigned int fieldIndex = constantUnion->getUConst(0);
655 ASSERT(fieldIndex < namedBlock->fields.size());
656 namedBlock->fields[fieldIndex].staticUse = true;
657 return false;
658 }
659
660 return true;
661}
662
Zhenyao Mo409078f2014-10-28 13:23:18 -0700663void ExpandUniforms(const std::vector<Uniform> &compact,
664 std::vector<ShaderVariable> *expanded)
Jamie Madill23a8a432014-07-09 13:27:42 -0400665{
666 for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
667 {
Jamie Madilla2fbb842014-09-03 09:40:47 -0400668 const ShaderVariable &variable = compact[variableIndex];
Jamie Madill23a8a432014-07-09 13:27:42 -0400669 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
670 }
671}
672
Jamie Madilla2fbb842014-09-03 09:40:47 -0400673}