blob: bd8cbc971ab8cf62c9427bef9a2e9da07ca56595 [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//
Olli Etuaho78ed6cd2017-08-09 16:19:00 +03006// CollectVariables.cpp: Collect lists of shader interface variables based on the AST.
alokp@chromium.org07620a52010-09-23 17:53:56 +00007
Olli Etuaho78ed6cd2017-08-09 16:19:00 +03008#include "compiler/translator/CollectVariables.h"
Olli Etuaho19515012017-06-26 18:00:17 +03009
10#include "angle_gl.h"
Jamie Madilld5512cd2014-07-10 17:50:08 -040011#include "common/utilities.h"
Olli Etuahocccf2b02017-07-05 14:50:54 +030012#include "compiler/translator/HashNames.h"
13#include "compiler/translator/IntermTraverse.h"
Olli Etuaho19515012017-06-26 18:00:17 +030014#include "compiler/translator/SymbolTable.h"
15#include "compiler/translator/util.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000016
Jamie Madilla2fbb842014-09-03 09:40:47 -040017namespace sh
18{
19
Jamie Madill54ad4f82014-09-03 09:40:46 -040020namespace
21{
Zhenyao Mod2d340b2013-09-23 14:57:05 -040022
Jamie Madilla2fbb842014-09-03 09:40:47 -040023BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
Jamie Madill54ad4f82014-09-03 09:40:46 -040024{
25 switch (blockStorage)
26 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -050027 case EbsPacked:
28 return BLOCKLAYOUT_PACKED;
29 case EbsShared:
30 return BLOCKLAYOUT_SHARED;
31 case EbsStd140:
Qin Jiajiaca68d982017-09-18 16:41:56 +080032 return BLOCKLAYOUT_STD140;
33 case EbsStd430:
34 return BLOCKLAYOUT_STD430;
Jamie Madilld7b1ab52016-12-12 14:42:19 -050035 default:
36 UNREACHABLE();
37 return BLOCKLAYOUT_SHARED;
Jamie Madill54ad4f82014-09-03 09:40:46 -040038 }
39}
40
Jiawei Shaod8105a02017-08-08 09:54:36 +080041// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
Jiajia Qin9b11ea42017-07-11 16:50:08 +080042BlockType GetBlockType(TQualifier qualifier)
43{
44 switch (qualifier)
45 {
46 case EvqUniform:
47 return BlockType::BLOCK_UNIFORM;
48 case EvqBuffer:
49 return BlockType::BLOCK_BUFFER;
Jiawei Shaod8105a02017-08-08 09:54:36 +080050 case EvqPerVertexIn:
51 return BlockType::BLOCK_IN;
Jiajia Qin9b11ea42017-07-11 16:50:08 +080052 default:
53 UNREACHABLE();
54 return BlockType::BLOCK_UNIFORM;
55 }
56}
57
Jamie Madilla718c1e2014-07-02 15:31:22 -040058template <class VarT>
Jamie Madilld7b1ab52016-12-12 14:42:19 -050059VarT *FindVariable(const TString &name, std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040060{
61 // TODO(zmo): optimize this function.
Jamie Madilla718c1e2014-07-02 15:31:22 -040062 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040063 {
Jamie Madill23a8a432014-07-09 13:27:42 -040064 if ((*infoList)[ii].name.c_str() == name)
Jamie Madilla718c1e2014-07-02 15:31:22 -040065 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -040066 }
Jamie Madilld5512cd2014-07-10 17:50:08 -040067
Yunchao Hef81ce4a2017-04-24 10:49:17 +080068 return nullptr;
Zhenyao Mod2d340b2013-09-23 14:57:05 -040069}
Jamie Madill54ad4f82014-09-03 09:40:46 -040070
Olli Etuaho06a06f52017-07-12 12:22:15 +030071// Note that this shouldn't be called for interface blocks - static use information is collected for
72// individual fields in case of interface blocks.
73void MarkStaticallyUsed(ShaderVariable *variable)
74{
75 if (!variable->staticUse)
76 {
77 if (variable->isStruct())
78 {
79 // Conservatively assume all fields are statically used as well.
80 for (auto &field : variable->fields)
81 {
82 MarkStaticallyUsed(&field);
83 }
84 }
85 variable->staticUse = true;
86 }
87}
88
Jiajia Qin3a9090f2017-09-27 14:37:04 +080089ShaderVariable *FindVariableInInterfaceBlock(const TString &name,
90 const TInterfaceBlock *interfaceBlock,
91 std::vector<InterfaceBlock> *infoList)
92{
93 ASSERT(interfaceBlock);
94 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
95 ASSERT(namedBlock);
96
97 // Set static use on the parent interface block here
98 namedBlock->staticUse = true;
99 return FindVariable(name, &namedBlock->fields);
100}
101
Olli Etuaho19515012017-06-26 18:00:17 +0300102// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
103// and interface blocks.
104class CollectVariablesTraverser : public TIntermTraverser
105{
106 public:
107 CollectVariablesTraverser(std::vector<Attribute> *attribs,
108 std::vector<OutputVariable> *outputVariables,
109 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800110 std::vector<Varying> *inputVaryings,
111 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800112 std::vector<InterfaceBlock> *uniformBlocks,
113 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800114 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300115 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300116 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300117 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800118 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300119 const TExtensionBehavior &extensionBehavior);
120
121 void visitSymbol(TIntermSymbol *symbol) override;
122 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
123 bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
124
125 private:
Olli Etuaho855d9642017-05-17 14:05:06 +0300126 std::string getMappedName(const TName &name) const;
127
Olli Etuaho19515012017-06-26 18:00:17 +0300128 void setCommonVariableProperties(const TType &type,
Olli Etuaho855d9642017-05-17 14:05:06 +0300129 const TName &name,
Olli Etuaho19515012017-06-26 18:00:17 +0300130 ShaderVariable *variableOut) const;
131
132 Attribute recordAttribute(const TIntermSymbol &variable) const;
133 OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
134 Varying recordVarying(const TIntermSymbol &variable) const;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800135 void recordInterfaceBlock(const TType &interfaceBlockType,
136 InterfaceBlock *interfaceBlock) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300137 Uniform recordUniform(const TIntermSymbol &variable) const;
138
139 void setBuiltInInfoFromSymbolTable(const char *name, ShaderVariable *info);
140
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800141 void recordBuiltInVaryingUsed(const char *name,
142 bool *addedFlag,
143 std::vector<Varying> *varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300144 void recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag);
145 void recordBuiltInAttributeUsed(const char *name, bool *addedFlag);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800146 InterfaceBlock *recordGLInUsed(const TType &glInType);
147 InterfaceBlock *findNamedInterfaceBlock(const TString &name) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300148
149 std::vector<Attribute> *mAttribs;
150 std::vector<OutputVariable> *mOutputVariables;
151 std::vector<Uniform> *mUniforms;
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800152 std::vector<Varying> *mInputVaryings;
153 std::vector<Varying> *mOutputVaryings;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800154 std::vector<InterfaceBlock> *mUniformBlocks;
155 std::vector<InterfaceBlock> *mShaderStorageBlocks;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800156 std::vector<InterfaceBlock> *mInBlocks;
Olli Etuaho19515012017-06-26 18:00:17 +0300157
158 std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
159
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800160 // Shader uniforms
Olli Etuaho19515012017-06-26 18:00:17 +0300161 bool mDepthRangeAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800162
163 // Vertex Shader builtins
164 bool mInstanceIDAdded;
165 bool mVertexIDAdded;
166 bool mPointSizeAdded;
167
168 // Vertex Shader and Geometry Shader builtins
169 bool mPositionAdded;
170
171 // Fragment Shader builtins
Olli Etuaho19515012017-06-26 18:00:17 +0300172 bool mPointCoordAdded;
173 bool mFrontFacingAdded;
174 bool mFragCoordAdded;
Olli Etuaho19515012017-06-26 18:00:17 +0300175 bool mLastFragDataAdded;
176 bool mFragColorAdded;
177 bool mFragDataAdded;
178 bool mFragDepthEXTAdded;
179 bool mFragDepthAdded;
180 bool mSecondaryFragColorEXTAdded;
181 bool mSecondaryFragDataEXTAdded;
182
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800183 // Geometry Shader builtins
Jiawei Shaod8105a02017-08-08 09:54:36 +0800184 bool mPerVertexInAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800185 bool mPrimitiveIDInAdded;
186 bool mInvocationIDAdded;
187
188 // Geometry Shader and Fragment Shader builtins
189 bool mPrimitiveIDAdded;
190 bool mLayerAdded;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800191
Olli Etuaho19515012017-06-26 18:00:17 +0300192 ShHashFunction64 mHashFunction;
193
Olli Etuaho19515012017-06-26 18:00:17 +0300194 int mShaderVersion;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800195 GLenum mShaderType;
Olli Etuaho19515012017-06-26 18:00:17 +0300196 const TExtensionBehavior &mExtensionBehavior;
197};
198
199CollectVariablesTraverser::CollectVariablesTraverser(
200 std::vector<sh::Attribute> *attribs,
201 std::vector<sh::OutputVariable> *outputVariables,
202 std::vector<sh::Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800203 std::vector<sh::Varying> *inputVaryings,
204 std::vector<sh::Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800205 std::vector<sh::InterfaceBlock> *uniformBlocks,
206 std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800207 std::vector<sh::InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300208 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300209 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300210 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800211 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300212 const TExtensionBehavior &extensionBehavior)
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300213 : TIntermTraverser(true, false, false, symbolTable),
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300214 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400215 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000216 mUniforms(uniforms),
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800217 mInputVaryings(inputVaryings),
218 mOutputVaryings(outputVaryings),
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800219 mUniformBlocks(uniformBlocks),
220 mShaderStorageBlocks(shaderStorageBlocks),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800221 mInBlocks(inBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400222 mDepthRangeAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800223 mInstanceIDAdded(false),
224 mVertexIDAdded(false),
225 mPointSizeAdded(false),
226 mPositionAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400227 mPointCoordAdded(false),
228 mFrontFacingAdded(false),
229 mFragCoordAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100230 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300231 mFragColorAdded(false),
232 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300233 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300234 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300235 mSecondaryFragColorEXTAdded(false),
236 mSecondaryFragDataEXTAdded(false),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800237 mPerVertexInAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800238 mPrimitiveIDInAdded(false),
239 mInvocationIDAdded(false),
240 mPrimitiveIDAdded(false),
241 mLayerAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700242 mHashFunction(hashFunction),
Olli Etuaho19515012017-06-26 18:00:17 +0300243 mShaderVersion(shaderVersion),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800244 mShaderType(shaderType),
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700245 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000246{
247}
248
Olli Etuaho855d9642017-05-17 14:05:06 +0300249std::string CollectVariablesTraverser::getMappedName(const TName &name) const
250{
251 return HashName(name, mHashFunction, nullptr).c_str();
252}
253
Olli Etuaho19515012017-06-26 18:00:17 +0300254void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
255 ShaderVariable *info)
256{
257 TVariable *symbolTableVar =
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300258 reinterpret_cast<TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
Olli Etuaho19515012017-06-26 18:00:17 +0300259 ASSERT(symbolTableVar);
260 const TType &type = symbolTableVar->getType();
261
262 info->name = name;
263 info->mappedName = name;
264 info->type = GLVariableType(type);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300265 info->precision = GLVariablePrecision(type);
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800266 if (auto *arraySizes = type.getArraySizes())
267 {
268 info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
269 }
Olli Etuaho19515012017-06-26 18:00:17 +0300270}
271
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800272void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name,
273 bool *addedFlag,
274 std::vector<Varying> *varyings)
Olli Etuaho19515012017-06-26 18:00:17 +0300275{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800276 ASSERT(varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300277 if (!(*addedFlag))
278 {
279 Varying info;
280 setBuiltInInfoFromSymbolTable(name, &info);
281 info.staticUse = true;
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300282 info.isInvariant = mSymbolTable->isVaryingInvariant(name);
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800283 varyings->push_back(info);
Olli Etuaho19515012017-06-26 18:00:17 +0300284 (*addedFlag) = true;
285 }
286}
287
288void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag)
289{
290 if (!(*addedFlag))
291 {
292 OutputVariable info;
293 setBuiltInInfoFromSymbolTable(name, &info);
294 info.staticUse = true;
295 mOutputVariables->push_back(info);
296 (*addedFlag) = true;
297 }
298}
299
300void CollectVariablesTraverser::recordBuiltInAttributeUsed(const char *name, bool *addedFlag)
301{
302 if (!(*addedFlag))
303 {
304 Attribute info;
305 setBuiltInInfoFromSymbolTable(name, &info);
306 info.staticUse = true;
307 info.location = -1;
308 mAttribs->push_back(info);
309 (*addedFlag) = true;
310 }
311}
312
Jiawei Shaod8105a02017-08-08 09:54:36 +0800313InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
314{
315 if (!mPerVertexInAdded)
316 {
317 ASSERT(glInType.getQualifier() == EvqPerVertexIn);
318 InterfaceBlock info;
319 recordInterfaceBlock(glInType, &info);
320 info.staticUse = true;
321
322 mPerVertexInAdded = true;
323 mInBlocks->push_back(info);
324 return &mInBlocks->back();
325 }
326 else
327 {
328 return FindVariable("gl_PerVertex", mInBlocks);
329 }
330}
331
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400332// We want to check whether a uniform/varying is statically used
333// because we only count the used ones in packing computing.
334// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
335// toward varying counting if they are statically used in a fragment
336// shader.
Olli Etuaho19515012017-06-26 18:00:17 +0300337void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000338{
Yunchao He4f285442017-04-21 12:15:49 +0800339 ASSERT(symbol != nullptr);
Olli Etuaho34d20072017-07-18 20:07:18 +0300340
341 if (symbol->getName().isInternal())
342 {
343 // Internal variables are not collected.
344 return;
345 }
346
Yunchao Hed7297bf2017-04-19 15:27:10 +0800347 ShaderVariable *var = nullptr;
Olli Etuaho34d20072017-07-18 20:07:18 +0300348 const TString &symbolName = symbol->getName().getString();
Jamie Madill4667c452014-07-08 15:02:36 -0400349
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800350 if (IsVaryingIn(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400351 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800352 var = FindVariable(symbolName, mInputVaryings);
353 }
354 else if (IsVaryingOut(symbol->getQualifier()))
355 {
356 var = FindVariable(symbolName, mOutputVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400357 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400358 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
359 {
360 UNREACHABLE();
361 }
Jamie Madill55def582015-05-04 11:24:57 -0400362 else if (symbolName == "gl_DepthRange")
363 {
364 ASSERT(symbol->getQualifier() == EvqUniform);
365
366 if (!mDepthRangeAdded)
367 {
368 Uniform info;
369 const char kName[] = "gl_DepthRange";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500370 info.name = kName;
371 info.mappedName = kName;
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400372 info.type = GL_NONE;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500373 info.precision = GL_NONE;
374 info.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400375
Olli Etuahoe7c28572017-10-23 16:29:33 +0300376 ShaderVariable nearInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400377 const char kNearName[] = "near";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500378 nearInfo.name = kNearName;
379 nearInfo.mappedName = kNearName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500380 nearInfo.precision = GL_HIGH_FLOAT;
381 nearInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400382
Olli Etuahoe7c28572017-10-23 16:29:33 +0300383 ShaderVariable farInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400384 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500385 farInfo.name = kFarName;
386 farInfo.mappedName = kFarName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500387 farInfo.precision = GL_HIGH_FLOAT;
388 farInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400389
Olli Etuahoe7c28572017-10-23 16:29:33 +0300390 ShaderVariable diffInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400391 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500392 diffInfo.name = kDiffName;
393 diffInfo.mappedName = kDiffName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500394 diffInfo.precision = GL_HIGH_FLOAT;
395 diffInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400396
397 info.fields.push_back(nearInfo);
398 info.fields.push_back(farInfo);
399 info.fields.push_back(diffInfo);
400
401 mUniforms->push_back(info);
402 mDepthRangeAdded = true;
403 }
404 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400405 else
Jamie Madill4667c452014-07-08 15:02:36 -0400406 {
407 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400408 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500409 case EvqAttribute:
410 case EvqVertexIn:
411 var = FindVariable(symbolName, mAttribs);
412 break;
413 case EvqFragmentOut:
414 var = FindVariable(symbolName, mOutputVariables);
415 break;
416 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400417 {
418 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
419 if (interfaceBlock)
420 {
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800421 var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400422 }
423 else
424 {
425 var = FindVariable(symbolName, mUniforms);
426 }
427
428 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400429 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400430 }
Jamie Madill4667c452014-07-08 15:02:36 -0400431 break;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800432 case EvqBuffer:
433 {
434 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
435 var =
436 FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
437 }
438 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500439 case EvqFragCoord:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800440 recordBuiltInVaryingUsed("gl_FragCoord", &mFragCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500441 return;
442 case EvqFrontFacing:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800443 recordBuiltInVaryingUsed("gl_FrontFacing", &mFrontFacingAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500444 return;
445 case EvqPointCoord:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800446 recordBuiltInVaryingUsed("gl_PointCoord", &mPointCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500447 return;
448 case EvqInstanceID:
Martin Radev115fc552017-07-05 17:11:06 +0300449 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
450 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
451 // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
452 // which makes it necessary to populate the type information explicitly instead of
453 // extracting it from the symbol table.
454 if (!mInstanceIDAdded)
455 {
456 Attribute info;
457 const char kName[] = "gl_InstanceID";
458 info.name = kName;
459 info.mappedName = kName;
460 info.type = GL_INT;
Martin Radev115fc552017-07-05 17:11:06 +0300461 info.precision = GL_HIGH_INT; // Defined by spec.
462 info.staticUse = true;
463 info.location = -1;
464 mAttribs->push_back(info);
465 mInstanceIDAdded = true;
466 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500467 return;
468 case EvqVertexID:
Olli Etuaho19515012017-06-26 18:00:17 +0300469 recordBuiltInAttributeUsed("gl_VertexID", &mVertexIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500470 return;
471 case EvqPosition:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800472 recordBuiltInVaryingUsed("gl_Position", &mPositionAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500473 return;
474 case EvqPointSize:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800475 recordBuiltInVaryingUsed("gl_PointSize", &mPointSizeAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500476 return;
477 case EvqLastFragData:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800478 recordBuiltInVaryingUsed("gl_LastFragData", &mLastFragDataAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500479 return;
480 case EvqFragColor:
Olli Etuaho19515012017-06-26 18:00:17 +0300481 recordBuiltInFragmentOutputUsed("gl_FragColor", &mFragColorAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500482 return;
483 case EvqFragData:
484 if (!mFragDataAdded)
485 {
486 OutputVariable info;
Olli Etuaho19515012017-06-26 18:00:17 +0300487 setBuiltInInfoFromSymbolTable("gl_FragData", &info);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300488 if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500489 {
Olli Etuaho465835d2017-09-26 13:34:10 +0300490 ASSERT(info.arraySizes.size() == 1u);
491 info.arraySizes.back() = 1u;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500492 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500493 info.staticUse = true;
494 mOutputVariables->push_back(info);
495 mFragDataAdded = true;
496 }
497 return;
498 case EvqFragDepthEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300499 recordBuiltInFragmentOutputUsed("gl_FragDepthEXT", &mFragDepthEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500500 return;
501 case EvqFragDepth:
Olli Etuaho19515012017-06-26 18:00:17 +0300502 recordBuiltInFragmentOutputUsed("gl_FragDepth", &mFragDepthAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500503 return;
504 case EvqSecondaryFragColorEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300505 recordBuiltInFragmentOutputUsed("gl_SecondaryFragColorEXT",
506 &mSecondaryFragColorEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500507 return;
508 case EvqSecondaryFragDataEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300509 recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT",
510 &mSecondaryFragDataEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500511 return;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800512 case EvqInvocationID:
513 recordBuiltInVaryingUsed("gl_InvocationID", &mInvocationIDAdded, mInputVaryings);
514 break;
515 case EvqPrimitiveIDIn:
516 recordBuiltInVaryingUsed("gl_PrimitiveIDIn", &mPrimitiveIDInAdded, mInputVaryings);
517 break;
518 case EvqPrimitiveID:
519 if (mShaderType == GL_GEOMETRY_SHADER_OES)
520 {
521 recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mOutputVaryings);
522 }
523 else
524 {
525 ASSERT(mShaderType == GL_FRAGMENT_SHADER);
526 recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mInputVaryings);
527 }
528 break;
529 case EvqLayer:
530 if (mShaderType == GL_GEOMETRY_SHADER_OES)
531 {
532 recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mOutputVaryings);
533 }
534 else if (mShaderType == GL_FRAGMENT_SHADER)
535 {
536 recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mInputVaryings);
537 }
538 else
539 {
540 ASSERT(mShaderType == GL_VERTEX_SHADER &&
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300541 IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800542 }
543 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500544 default:
545 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400546 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400547 }
548 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400549 {
Olli Etuaho06a06f52017-07-12 12:22:15 +0300550 MarkStaticallyUsed(var);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400551 }
552}
553
Olli Etuaho19515012017-06-26 18:00:17 +0300554void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
Olli Etuaho855d9642017-05-17 14:05:06 +0300555 const TName &name,
Olli Etuaho19515012017-06-26 18:00:17 +0300556 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400557{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000558 ASSERT(variableOut);
559
560 const TStructure *structure = type.getStruct();
561
562 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500563 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000564 variableOut->type = GLVariableType(type);
565 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500566 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000567 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400568 {
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400569 // Structures use a NONE type that isn't exposed outside ANGLE.
570 variableOut->type = GL_NONE;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000571 variableOut->structName = structure->name().c_str();
572
573 const TFieldList &fields = structure->fields();
574
575 for (TField *field : fields)
576 {
577 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
578 // ShaderVariable objects.
579 ShaderVariable fieldVariable;
Olli Etuaho855d9642017-05-17 14:05:06 +0300580 setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000581 variableOut->fields.push_back(fieldVariable);
582 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400583 }
Olli Etuaho855d9642017-05-17 14:05:06 +0300584 variableOut->name = name.getString().c_str();
585 variableOut->mappedName = getMappedName(name);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300586
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800587 if (auto *arraySizes = type.getArraySizes())
588 {
589 variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
590 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000591}
Jamie Madill23a8a432014-07-09 13:27:42 -0400592
Olli Etuaho19515012017-06-26 18:00:17 +0300593Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400594{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000595 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400596 ASSERT(!type.getStruct());
597
Jamie Madilla2fbb842014-09-03 09:40:47 -0400598 Attribute attribute;
Olli Etuaho855d9642017-05-17 14:05:06 +0300599 setCommonVariableProperties(type, variable.getName(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400600
Olli Etuahoa55102c2017-02-24 12:36:50 +0000601 attribute.location = type.getLayoutQualifier().location;
602 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400603}
604
Olli Etuaho19515012017-06-26 18:00:17 +0300605OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400606{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000607 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400608 ASSERT(!type.getStruct());
609
Olli Etuahoa55102c2017-02-24 12:36:50 +0000610 OutputVariable outputVariable;
Olli Etuaho855d9642017-05-17 14:05:06 +0300611 setCommonVariableProperties(type, variable.getName(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400612
Olli Etuahoa55102c2017-02-24 12:36:50 +0000613 outputVariable.location = type.getLayoutQualifier().location;
614 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400615}
616
Olli Etuaho19515012017-06-26 18:00:17 +0300617Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400618{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000619 const TType &type = variable.getType();
620
621 Varying varying;
Olli Etuaho855d9642017-05-17 14:05:06 +0300622 setCommonVariableProperties(type, variable.getName(), &varying);
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800623 varying.location = type.getLayoutQualifier().location;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000624
625 switch (type.getQualifier())
626 {
627 case EvqVaryingIn:
628 case EvqVaryingOut:
629 case EvqVertexOut:
630 case EvqSmoothOut:
631 case EvqFlatOut:
632 case EvqCentroidOut:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800633 case EvqGeometryOut:
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300634 if (mSymbolTable->isVaryingInvariant(std::string(variable.getSymbol().c_str())) ||
Olli Etuahoa55102c2017-02-24 12:36:50 +0000635 type.isInvariant())
636 {
637 varying.isInvariant = true;
638 }
639 break;
640 default:
641 break;
642 }
643
644 varying.interpolation = GetInterpolationType(type.getQualifier());
645 return varying;
646}
647
Jiawei Shaod8105a02017-08-08 09:54:36 +0800648// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
649void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlockType,
650 InterfaceBlock *interfaceBlock) const
Olli Etuahoa55102c2017-02-24 12:36:50 +0000651{
Jiawei Shaod8105a02017-08-08 09:54:36 +0800652 ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
653 ASSERT(interfaceBlock);
654
655 const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400656 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400657
Jiawei Shaod8105a02017-08-08 09:54:36 +0800658 interfaceBlock->name = blockType->name().c_str();
Olli Etuaho855d9642017-05-17 14:05:06 +0300659 interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
Jiawei Shaod8105a02017-08-08 09:54:36 +0800660 interfaceBlock->instanceName =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500661 (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300662 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
663 interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800664
665 interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
666 if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
667 interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
668 {
669 interfaceBlock->isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
670 interfaceBlock->binding = blockType->blockBinding();
671 interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
672 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400673
Jamie Madilla6f267f2014-08-27 11:44:15 -0400674 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500675 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400676 {
Jamie Madill39046162016-02-08 15:05:17 -0500677 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400678
Olli Etuahoa55102c2017-02-24 12:36:50 +0000679 InterfaceBlockField fieldVariable;
Olli Etuaho855d9642017-05-17 14:05:06 +0300680 setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000681 fieldVariable.isRowMajorLayout =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500682 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800683 interfaceBlock->fields.push_back(fieldVariable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400684 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400685}
686
Olli Etuaho19515012017-06-26 18:00:17 +0300687Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400688{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000689 Uniform uniform;
Olli Etuaho855d9642017-05-17 14:05:06 +0300690 setCommonVariableProperties(variable.getType(), variable.getName(), &uniform);
Olli Etuaho78ed6cd2017-08-09 16:19:00 +0300691 uniform.binding = variable.getType().getLayoutQualifier().binding;
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000692 uniform.location = variable.getType().getLayoutQualifier().location;
jchen104cdac9e2017-05-08 11:01:20 +0800693 uniform.offset = variable.getType().getLayoutQualifier().offset;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000694 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000695}
696
Olli Etuaho19515012017-06-26 18:00:17 +0300697bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000698{
Olli Etuaho13389b62016-10-16 11:48:18 +0100699 const TIntermSequence &sequence = *(node->getSequence());
700 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000701
Olli Etuaho13389b62016-10-16 11:48:18 +0100702 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
703 TQualifier qualifier = typedNode.getQualifier();
704
Olli Etuahoa55102c2017-02-24 12:36:50 +0000705 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
706 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
707 IsVarying(qualifier);
708
709 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000710 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000711 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100712 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000713
714 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100715 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000716 // The only case in which the sequence will not contain a TIntermSymbol node is
717 // initialization. It will contain a TInterBinary node in that case. Since attributes,
718 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
719 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
720 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
Olli Etuaho34d20072017-07-18 20:07:18 +0300721 if (variable.getName().isInternal())
722 {
723 // Internal variables are not collected.
724 continue;
725 }
726
Jiawei Shaod8105a02017-08-08 09:54:36 +0800727 // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
Olli Etuahoa55102c2017-02-24 12:36:50 +0000728 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000729 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800730 InterfaceBlock interfaceBlock;
731 recordInterfaceBlock(variable.getType(), &interfaceBlock);
732
733 switch (qualifier)
Jiajia Qinbc585152017-06-23 15:42:17 +0800734 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800735 case EvqUniform:
736 mUniformBlocks->push_back(interfaceBlock);
737 break;
738 case EvqBuffer:
739 mShaderStorageBlocks->push_back(interfaceBlock);
740 break;
741 default:
742 UNREACHABLE();
Jiajia Qinbc585152017-06-23 15:42:17 +0800743 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000744 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000745 else
746 {
747 switch (qualifier)
748 {
749 case EvqAttribute:
750 case EvqVertexIn:
751 mAttribs->push_back(recordAttribute(variable));
752 break;
753 case EvqFragmentOut:
754 mOutputVariables->push_back(recordOutputVariable(variable));
755 break;
756 case EvqUniform:
757 mUniforms->push_back(recordUniform(variable));
758 break;
759 default:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800760 if (IsVaryingIn(qualifier))
761 {
762 mInputVaryings->push_back(recordVarying(variable));
763 }
764 else
765 {
766 ASSERT(IsVaryingOut(qualifier));
767 mOutputVaryings->push_back(recordVarying(variable));
768 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000769 break;
770 }
771 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000772 }
773
Olli Etuahoa55102c2017-02-24 12:36:50 +0000774 // None of the recorded variables can have initializers, so we don't need to traverse the
775 // declarators.
776 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000777}
Jamie Madill23a8a432014-07-09 13:27:42 -0400778
Jiawei Shaod8105a02017-08-08 09:54:36 +0800779// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
780// GL_OES_shader_io_blocks.
781InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(const TString &blockName) const
782{
783 InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
784 if (!namedBlock)
785 {
786 namedBlock = FindVariable(blockName, mShaderStorageBlocks);
787 }
788 return namedBlock;
789}
790
Olli Etuaho19515012017-06-26 18:00:17 +0300791bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
Jamie Madillb547ddf2014-08-25 16:20:46 -0400792{
793 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
794 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400795 // NOTE: we do not determine static use for individual blocks of an array
796 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
797 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400798
799 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
800 ASSERT(constantUnion);
801
Jiawei Shaod8105a02017-08-08 09:54:36 +0800802 InterfaceBlock *namedBlock = nullptr;
803
804 bool traverseIndexExpression = false;
805 TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
806 if (interfaceIndexingNode)
807 {
808 TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
809 ASSERT(interfaceNode);
810
811 const TType &interfaceType = interfaceNode->getType();
812 if (interfaceType.getQualifier() == EvqPerVertexIn)
813 {
814 namedBlock = recordGLInUsed(interfaceType);
815 ASSERT(namedBlock);
816
817 // We need to continue traversing to collect useful variables in the index
818 // expression of gl_in.
819 traverseIndexExpression = true;
820 }
821 }
822
Jamie Madilla6f267f2014-08-27 11:44:15 -0400823 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800824 if (!namedBlock)
Jiajia Qinbc585152017-06-23 15:42:17 +0800825 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800826 namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
Jiajia Qinbc585152017-06-23 15:42:17 +0800827 }
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800828 ASSERT(namedBlock);
829 namedBlock->staticUse = true;
830 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
831 ASSERT(fieldIndex < namedBlock->fields.size());
832 namedBlock->fields[fieldIndex].staticUse = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800833
834 if (traverseIndexExpression)
835 {
836 ASSERT(interfaceIndexingNode);
837 interfaceIndexingNode->getRight()->traverse(this);
838 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400839 return false;
840 }
841
842 return true;
843}
844
Olli Etuaho19515012017-06-26 18:00:17 +0300845} // anonymous namespace
846
847void CollectVariables(TIntermBlock *root,
848 std::vector<Attribute> *attributes,
849 std::vector<OutputVariable> *outputVariables,
850 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800851 std::vector<Varying> *inputVaryings,
852 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800853 std::vector<InterfaceBlock> *uniformBlocks,
854 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800855 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300856 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300857 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300858 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800859 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300860 const TExtensionBehavior &extensionBehavior)
861{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800862 CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800863 outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800864 hashFunction, symbolTable, shaderVersion, shaderType,
865 extensionBehavior);
Olli Etuaho19515012017-06-26 18:00:17 +0300866 root->traverse(&collect);
867}
868
Olli Etuaho19515012017-06-26 18:00:17 +0300869} // namespace sh