blob: 0c0dba2f5e711763caeaa3713e8f8d559e1a3c0c [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 Shaobd924af2017-11-16 15:28:04 +080041// TODO(jiawei.shao@intel.com): implement GL_EXT_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);
Olli Etuahobed35d72017-12-20 16:36:26 +020094 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
Jiajia Qin3a9090f2017-09-27 14:37:04 +080095 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;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200135 void recordInterfaceBlock(const TString &instanceName,
136 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800137 InterfaceBlock *interfaceBlock) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300138 Uniform recordUniform(const TIntermSymbol &variable) const;
139
140 void setBuiltInInfoFromSymbolTable(const char *name, ShaderVariable *info);
141
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800142 void recordBuiltInVaryingUsed(const char *name,
143 bool *addedFlag,
144 std::vector<Varying> *varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300145 void recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag);
146 void recordBuiltInAttributeUsed(const char *name, bool *addedFlag);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800147 InterfaceBlock *recordGLInUsed(const TType &glInType);
148 InterfaceBlock *findNamedInterfaceBlock(const TString &name) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300149
150 std::vector<Attribute> *mAttribs;
151 std::vector<OutputVariable> *mOutputVariables;
152 std::vector<Uniform> *mUniforms;
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800153 std::vector<Varying> *mInputVaryings;
154 std::vector<Varying> *mOutputVaryings;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800155 std::vector<InterfaceBlock> *mUniformBlocks;
156 std::vector<InterfaceBlock> *mShaderStorageBlocks;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800157 std::vector<InterfaceBlock> *mInBlocks;
Olli Etuaho19515012017-06-26 18:00:17 +0300158
159 std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
160
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800161 // Shader uniforms
Olli Etuaho19515012017-06-26 18:00:17 +0300162 bool mDepthRangeAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800163
164 // Vertex Shader builtins
165 bool mInstanceIDAdded;
166 bool mVertexIDAdded;
167 bool mPointSizeAdded;
168
169 // Vertex Shader and Geometry Shader builtins
170 bool mPositionAdded;
171
172 // Fragment Shader builtins
Olli Etuaho19515012017-06-26 18:00:17 +0300173 bool mPointCoordAdded;
174 bool mFrontFacingAdded;
175 bool mFragCoordAdded;
Olli Etuaho19515012017-06-26 18:00:17 +0300176 bool mLastFragDataAdded;
177 bool mFragColorAdded;
178 bool mFragDataAdded;
179 bool mFragDepthEXTAdded;
180 bool mFragDepthAdded;
181 bool mSecondaryFragColorEXTAdded;
182 bool mSecondaryFragDataEXTAdded;
183
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800184 // Geometry Shader builtins
Jiawei Shaod8105a02017-08-08 09:54:36 +0800185 bool mPerVertexInAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800186 bool mPrimitiveIDInAdded;
187 bool mInvocationIDAdded;
188
189 // Geometry Shader and Fragment Shader builtins
190 bool mPrimitiveIDAdded;
191 bool mLayerAdded;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800192
Olli Etuaho19515012017-06-26 18:00:17 +0300193 ShHashFunction64 mHashFunction;
194
Olli Etuaho19515012017-06-26 18:00:17 +0300195 int mShaderVersion;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800196 GLenum mShaderType;
Olli Etuaho19515012017-06-26 18:00:17 +0300197 const TExtensionBehavior &mExtensionBehavior;
198};
199
200CollectVariablesTraverser::CollectVariablesTraverser(
201 std::vector<sh::Attribute> *attribs,
202 std::vector<sh::OutputVariable> *outputVariables,
203 std::vector<sh::Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800204 std::vector<sh::Varying> *inputVaryings,
205 std::vector<sh::Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800206 std::vector<sh::InterfaceBlock> *uniformBlocks,
207 std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800208 std::vector<sh::InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300209 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300210 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300211 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800212 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300213 const TExtensionBehavior &extensionBehavior)
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300214 : TIntermTraverser(true, false, false, symbolTable),
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300215 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400216 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000217 mUniforms(uniforms),
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800218 mInputVaryings(inputVaryings),
219 mOutputVaryings(outputVaryings),
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800220 mUniformBlocks(uniformBlocks),
221 mShaderStorageBlocks(shaderStorageBlocks),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800222 mInBlocks(inBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400223 mDepthRangeAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800224 mInstanceIDAdded(false),
225 mVertexIDAdded(false),
226 mPointSizeAdded(false),
227 mPositionAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400228 mPointCoordAdded(false),
229 mFrontFacingAdded(false),
230 mFragCoordAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100231 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300232 mFragColorAdded(false),
233 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300234 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300235 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300236 mSecondaryFragColorEXTAdded(false),
237 mSecondaryFragDataEXTAdded(false),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800238 mPerVertexInAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800239 mPrimitiveIDInAdded(false),
240 mInvocationIDAdded(false),
241 mPrimitiveIDAdded(false),
242 mLayerAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700243 mHashFunction(hashFunction),
Olli Etuaho19515012017-06-26 18:00:17 +0300244 mShaderVersion(shaderVersion),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800245 mShaderType(shaderType),
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700246 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000247{
248}
249
Olli Etuaho855d9642017-05-17 14:05:06 +0300250std::string CollectVariablesTraverser::getMappedName(const TName &name) const
251{
252 return HashName(name, mHashFunction, nullptr).c_str();
253}
254
Olli Etuaho19515012017-06-26 18:00:17 +0300255void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
256 ShaderVariable *info)
257{
258 TVariable *symbolTableVar =
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300259 reinterpret_cast<TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
Olli Etuaho19515012017-06-26 18:00:17 +0300260 ASSERT(symbolTableVar);
261 const TType &type = symbolTableVar->getType();
262
263 info->name = name;
264 info->mappedName = name;
265 info->type = GLVariableType(type);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300266 info->precision = GLVariablePrecision(type);
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800267 if (auto *arraySizes = type.getArraySizes())
268 {
269 info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
270 }
Olli Etuaho19515012017-06-26 18:00:17 +0300271}
272
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800273void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name,
274 bool *addedFlag,
275 std::vector<Varying> *varyings)
Olli Etuaho19515012017-06-26 18:00:17 +0300276{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800277 ASSERT(varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300278 if (!(*addedFlag))
279 {
280 Varying info;
281 setBuiltInInfoFromSymbolTable(name, &info);
282 info.staticUse = true;
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300283 info.isInvariant = mSymbolTable->isVaryingInvariant(name);
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800284 varyings->push_back(info);
Olli Etuaho19515012017-06-26 18:00:17 +0300285 (*addedFlag) = true;
286 }
287}
288
289void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag)
290{
291 if (!(*addedFlag))
292 {
293 OutputVariable info;
294 setBuiltInInfoFromSymbolTable(name, &info);
295 info.staticUse = true;
296 mOutputVariables->push_back(info);
297 (*addedFlag) = true;
298 }
299}
300
301void CollectVariablesTraverser::recordBuiltInAttributeUsed(const char *name, bool *addedFlag)
302{
303 if (!(*addedFlag))
304 {
305 Attribute info;
306 setBuiltInInfoFromSymbolTable(name, &info);
307 info.staticUse = true;
308 info.location = -1;
309 mAttribs->push_back(info);
310 (*addedFlag) = true;
311 }
312}
313
Jiawei Shaod8105a02017-08-08 09:54:36 +0800314InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
315{
316 if (!mPerVertexInAdded)
317 {
318 ASSERT(glInType.getQualifier() == EvqPerVertexIn);
319 InterfaceBlock info;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200320 recordInterfaceBlock("gl_in", glInType, &info);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800321 info.staticUse = true;
322
323 mPerVertexInAdded = true;
324 mInBlocks->push_back(info);
325 return &mInBlocks->back();
326 }
327 else
328 {
329 return FindVariable("gl_PerVertex", mInBlocks);
330 }
331}
332
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400333// We want to check whether a uniform/varying is statically used
334// because we only count the used ones in packing computing.
335// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
336// toward varying counting if they are statically used in a fragment
337// shader.
Olli Etuaho19515012017-06-26 18:00:17 +0300338void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000339{
Yunchao He4f285442017-04-21 12:15:49 +0800340 ASSERT(symbol != nullptr);
Olli Etuaho34d20072017-07-18 20:07:18 +0300341
342 if (symbol->getName().isInternal())
343 {
344 // Internal variables are not collected.
345 return;
346 }
347
Yunchao Hed7297bf2017-04-19 15:27:10 +0800348 ShaderVariable *var = nullptr;
Olli Etuaho34d20072017-07-18 20:07:18 +0300349 const TString &symbolName = symbol->getName().getString();
Jamie Madill4667c452014-07-08 15:02:36 -0400350
Olli Etuahob8cb9392017-12-20 14:23:19 +0200351 // Check the qualifier from the variable, not from the symbol node. The node may have a
352 // different qualifier if it's the result of a folded ternary node.
353 TQualifier qualifier = symbol->variable().getType().getQualifier();
354
355 if (IsVaryingIn(qualifier))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400356 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800357 var = FindVariable(symbolName, mInputVaryings);
358 }
Olli Etuahob8cb9392017-12-20 14:23:19 +0200359 else if (IsVaryingOut(qualifier))
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800360 {
361 var = FindVariable(symbolName, mOutputVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400362 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400363 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
364 {
365 UNREACHABLE();
366 }
Jamie Madill55def582015-05-04 11:24:57 -0400367 else if (symbolName == "gl_DepthRange")
368 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200369 ASSERT(qualifier == EvqUniform);
Jamie Madill55def582015-05-04 11:24:57 -0400370
371 if (!mDepthRangeAdded)
372 {
373 Uniform info;
374 const char kName[] = "gl_DepthRange";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500375 info.name = kName;
376 info.mappedName = kName;
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400377 info.type = GL_NONE;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500378 info.precision = GL_NONE;
379 info.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400380
Olli Etuahoe7c28572017-10-23 16:29:33 +0300381 ShaderVariable nearInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400382 const char kNearName[] = "near";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500383 nearInfo.name = kNearName;
384 nearInfo.mappedName = kNearName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500385 nearInfo.precision = GL_HIGH_FLOAT;
386 nearInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400387
Olli Etuahoe7c28572017-10-23 16:29:33 +0300388 ShaderVariable farInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400389 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500390 farInfo.name = kFarName;
391 farInfo.mappedName = kFarName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500392 farInfo.precision = GL_HIGH_FLOAT;
393 farInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400394
Olli Etuahoe7c28572017-10-23 16:29:33 +0300395 ShaderVariable diffInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400396 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500397 diffInfo.name = kDiffName;
398 diffInfo.mappedName = kDiffName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500399 diffInfo.precision = GL_HIGH_FLOAT;
400 diffInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400401
402 info.fields.push_back(nearInfo);
403 info.fields.push_back(farInfo);
404 info.fields.push_back(diffInfo);
405
406 mUniforms->push_back(info);
407 mDepthRangeAdded = true;
408 }
409 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400410 else
Jamie Madill4667c452014-07-08 15:02:36 -0400411 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200412 switch (qualifier)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400413 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500414 case EvqAttribute:
415 case EvqVertexIn:
416 var = FindVariable(symbolName, mAttribs);
417 break;
418 case EvqFragmentOut:
419 var = FindVariable(symbolName, mOutputVariables);
420 break;
421 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400422 {
423 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
424 if (interfaceBlock)
425 {
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800426 var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400427 }
428 else
429 {
430 var = FindVariable(symbolName, mUniforms);
431 }
432
433 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400434 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400435 }
Jamie Madill4667c452014-07-08 15:02:36 -0400436 break;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800437 case EvqBuffer:
438 {
439 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
440 var =
441 FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
442 }
443 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500444 case EvqFragCoord:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800445 recordBuiltInVaryingUsed("gl_FragCoord", &mFragCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500446 return;
447 case EvqFrontFacing:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800448 recordBuiltInVaryingUsed("gl_FrontFacing", &mFrontFacingAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500449 return;
450 case EvqPointCoord:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800451 recordBuiltInVaryingUsed("gl_PointCoord", &mPointCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500452 return;
453 case EvqInstanceID:
Martin Radev115fc552017-07-05 17:11:06 +0300454 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
455 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
456 // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
457 // which makes it necessary to populate the type information explicitly instead of
458 // extracting it from the symbol table.
459 if (!mInstanceIDAdded)
460 {
461 Attribute info;
462 const char kName[] = "gl_InstanceID";
463 info.name = kName;
464 info.mappedName = kName;
465 info.type = GL_INT;
Martin Radev115fc552017-07-05 17:11:06 +0300466 info.precision = GL_HIGH_INT; // Defined by spec.
467 info.staticUse = true;
468 info.location = -1;
469 mAttribs->push_back(info);
470 mInstanceIDAdded = true;
471 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500472 return;
473 case EvqVertexID:
Olli Etuaho19515012017-06-26 18:00:17 +0300474 recordBuiltInAttributeUsed("gl_VertexID", &mVertexIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500475 return;
476 case EvqPosition:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800477 recordBuiltInVaryingUsed("gl_Position", &mPositionAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500478 return;
479 case EvqPointSize:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800480 recordBuiltInVaryingUsed("gl_PointSize", &mPointSizeAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500481 return;
482 case EvqLastFragData:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800483 recordBuiltInVaryingUsed("gl_LastFragData", &mLastFragDataAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500484 return;
485 case EvqFragColor:
Olli Etuaho19515012017-06-26 18:00:17 +0300486 recordBuiltInFragmentOutputUsed("gl_FragColor", &mFragColorAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500487 return;
488 case EvqFragData:
489 if (!mFragDataAdded)
490 {
491 OutputVariable info;
Olli Etuaho19515012017-06-26 18:00:17 +0300492 setBuiltInInfoFromSymbolTable("gl_FragData", &info);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300493 if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500494 {
Olli Etuaho465835d2017-09-26 13:34:10 +0300495 ASSERT(info.arraySizes.size() == 1u);
496 info.arraySizes.back() = 1u;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500497 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500498 info.staticUse = true;
499 mOutputVariables->push_back(info);
500 mFragDataAdded = true;
501 }
502 return;
503 case EvqFragDepthEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300504 recordBuiltInFragmentOutputUsed("gl_FragDepthEXT", &mFragDepthEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500505 return;
506 case EvqFragDepth:
Olli Etuaho19515012017-06-26 18:00:17 +0300507 recordBuiltInFragmentOutputUsed("gl_FragDepth", &mFragDepthAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500508 return;
509 case EvqSecondaryFragColorEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300510 recordBuiltInFragmentOutputUsed("gl_SecondaryFragColorEXT",
511 &mSecondaryFragColorEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500512 return;
513 case EvqSecondaryFragDataEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300514 recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT",
515 &mSecondaryFragDataEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500516 return;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800517 case EvqInvocationID:
518 recordBuiltInVaryingUsed("gl_InvocationID", &mInvocationIDAdded, mInputVaryings);
519 break;
520 case EvqPrimitiveIDIn:
521 recordBuiltInVaryingUsed("gl_PrimitiveIDIn", &mPrimitiveIDInAdded, mInputVaryings);
522 break;
523 case EvqPrimitiveID:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800524 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800525 {
526 recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mOutputVaryings);
527 }
528 else
529 {
530 ASSERT(mShaderType == GL_FRAGMENT_SHADER);
531 recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mInputVaryings);
532 }
533 break;
534 case EvqLayer:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800535 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800536 {
537 recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mOutputVaryings);
538 }
539 else if (mShaderType == GL_FRAGMENT_SHADER)
540 {
541 recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mInputVaryings);
542 }
543 else
544 {
545 ASSERT(mShaderType == GL_VERTEX_SHADER &&
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300546 IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800547 }
548 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500549 default:
550 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400551 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400552 }
553 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400554 {
Olli Etuaho06a06f52017-07-12 12:22:15 +0300555 MarkStaticallyUsed(var);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400556 }
557}
558
Olli Etuaho19515012017-06-26 18:00:17 +0300559void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
Olli Etuaho855d9642017-05-17 14:05:06 +0300560 const TName &name,
Olli Etuaho19515012017-06-26 18:00:17 +0300561 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400562{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000563 ASSERT(variableOut);
564
565 const TStructure *structure = type.getStruct();
566
567 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500568 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000569 variableOut->type = GLVariableType(type);
570 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500571 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000572 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400573 {
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400574 // Structures use a NONE type that isn't exposed outside ANGLE.
575 variableOut->type = GL_NONE;
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100576 if (structure->symbolType() != SymbolType::Empty)
577 {
Olli Etuahobed35d72017-12-20 16:36:26 +0200578 variableOut->structName = structure->name().c_str();
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100579 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000580
581 const TFieldList &fields = structure->fields();
582
Olli Etuaho378c3a52017-12-04 11:32:13 +0200583 for (const TField *field : fields)
Olli Etuahoa55102c2017-02-24 12:36:50 +0000584 {
585 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
586 // ShaderVariable objects.
587 ShaderVariable fieldVariable;
Olli Etuahobed35d72017-12-20 16:36:26 +0200588 setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000589 variableOut->fields.push_back(fieldVariable);
590 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400591 }
Olli Etuaho855d9642017-05-17 14:05:06 +0300592 variableOut->name = name.getString().c_str();
593 variableOut->mappedName = getMappedName(name);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300594
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800595 if (auto *arraySizes = type.getArraySizes())
596 {
597 variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
598 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000599}
Jamie Madill23a8a432014-07-09 13:27:42 -0400600
Olli Etuaho19515012017-06-26 18:00:17 +0300601Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400602{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000603 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400604 ASSERT(!type.getStruct());
605
Jamie Madilla2fbb842014-09-03 09:40:47 -0400606 Attribute attribute;
Olli Etuaho855d9642017-05-17 14:05:06 +0300607 setCommonVariableProperties(type, variable.getName(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400608
Olli Etuahoa55102c2017-02-24 12:36:50 +0000609 attribute.location = type.getLayoutQualifier().location;
610 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400611}
612
Olli Etuaho19515012017-06-26 18:00:17 +0300613OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400614{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000615 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400616 ASSERT(!type.getStruct());
617
Olli Etuahoa55102c2017-02-24 12:36:50 +0000618 OutputVariable outputVariable;
Olli Etuaho855d9642017-05-17 14:05:06 +0300619 setCommonVariableProperties(type, variable.getName(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400620
Olli Etuahoa55102c2017-02-24 12:36:50 +0000621 outputVariable.location = type.getLayoutQualifier().location;
622 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400623}
624
Olli Etuaho19515012017-06-26 18:00:17 +0300625Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400626{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000627 const TType &type = variable.getType();
628
629 Varying varying;
Olli Etuaho855d9642017-05-17 14:05:06 +0300630 setCommonVariableProperties(type, variable.getName(), &varying);
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800631 varying.location = type.getLayoutQualifier().location;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000632
633 switch (type.getQualifier())
634 {
635 case EvqVaryingIn:
636 case EvqVaryingOut:
637 case EvqVertexOut:
638 case EvqSmoothOut:
639 case EvqFlatOut:
640 case EvqCentroidOut:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800641 case EvqGeometryOut:
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300642 if (mSymbolTable->isVaryingInvariant(std::string(variable.getSymbol().c_str())) ||
Olli Etuahoa55102c2017-02-24 12:36:50 +0000643 type.isInvariant())
644 {
645 varying.isInvariant = true;
646 }
647 break;
648 default:
649 break;
650 }
651
652 varying.interpolation = GetInterpolationType(type.getQualifier());
653 return varying;
654}
655
Jiawei Shaobd924af2017-11-16 15:28:04 +0800656// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200657void CollectVariablesTraverser::recordInterfaceBlock(const TString &instanceName,
658 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800659 InterfaceBlock *interfaceBlock) const
Olli Etuahoa55102c2017-02-24 12:36:50 +0000660{
Jiawei Shaod8105a02017-08-08 09:54:36 +0800661 ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
662 ASSERT(interfaceBlock);
663
664 const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400665 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400666
Olli Etuahobed35d72017-12-20 16:36:26 +0200667 interfaceBlock->name = blockType->name().c_str();
Olli Etuaho855d9642017-05-17 14:05:06 +0300668 interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200669 interfaceBlock->instanceName = instanceName.c_str();
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300670 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
671 interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800672
673 interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
674 if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
675 interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
676 {
Olli Etuaho3de27032017-11-30 12:16:47 +0200677 // TODO(oetuaho): Remove setting isRowMajorLayout.
678 interfaceBlock->isRowMajorLayout = false;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800679 interfaceBlock->binding = blockType->blockBinding();
680 interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
681 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400682
Jamie Madilla6f267f2014-08-27 11:44:15 -0400683 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500684 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400685 {
Jamie Madill39046162016-02-08 15:05:17 -0500686 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400687
Olli Etuahoa55102c2017-02-24 12:36:50 +0000688 InterfaceBlockField fieldVariable;
Olli Etuahobed35d72017-12-20 16:36:26 +0200689 setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000690 fieldVariable.isRowMajorLayout =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500691 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800692 interfaceBlock->fields.push_back(fieldVariable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400693 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400694}
695
Olli Etuaho19515012017-06-26 18:00:17 +0300696Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400697{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000698 Uniform uniform;
Olli Etuaho855d9642017-05-17 14:05:06 +0300699 setCommonVariableProperties(variable.getType(), variable.getName(), &uniform);
Olli Etuaho78ed6cd2017-08-09 16:19:00 +0300700 uniform.binding = variable.getType().getLayoutQualifier().binding;
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000701 uniform.location = variable.getType().getLayoutQualifier().location;
jchen104cdac9e2017-05-08 11:01:20 +0800702 uniform.offset = variable.getType().getLayoutQualifier().offset;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800703 uniform.readonly = variable.getType().getMemoryQualifier().readonly;
704 uniform.writeonly = variable.getType().getMemoryQualifier().writeonly;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000705 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000706}
707
Olli Etuaho19515012017-06-26 18:00:17 +0300708bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000709{
Olli Etuaho13389b62016-10-16 11:48:18 +0100710 const TIntermSequence &sequence = *(node->getSequence());
711 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000712
Olli Etuaho13389b62016-10-16 11:48:18 +0100713 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
714 TQualifier qualifier = typedNode.getQualifier();
715
Olli Etuahoa55102c2017-02-24 12:36:50 +0000716 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
717 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
718 IsVarying(qualifier);
719
720 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000721 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000722 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100723 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000724
725 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100726 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000727 // The only case in which the sequence will not contain a TIntermSymbol node is
728 // initialization. It will contain a TInterBinary node in that case. Since attributes,
729 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
730 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
731 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
Olli Etuaho34d20072017-07-18 20:07:18 +0300732 if (variable.getName().isInternal())
733 {
734 // Internal variables are not collected.
735 continue;
736 }
737
Jiawei Shaobd924af2017-11-16 15:28:04 +0800738 // TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuahoa55102c2017-02-24 12:36:50 +0000739 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000740 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800741 InterfaceBlock interfaceBlock;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200742 recordInterfaceBlock(variable.getSymbol(), variable.getType(), &interfaceBlock);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800743
744 switch (qualifier)
Jiajia Qinbc585152017-06-23 15:42:17 +0800745 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800746 case EvqUniform:
747 mUniformBlocks->push_back(interfaceBlock);
748 break;
749 case EvqBuffer:
750 mShaderStorageBlocks->push_back(interfaceBlock);
751 break;
752 default:
753 UNREACHABLE();
Jiajia Qinbc585152017-06-23 15:42:17 +0800754 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000755 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000756 else
757 {
758 switch (qualifier)
759 {
760 case EvqAttribute:
761 case EvqVertexIn:
762 mAttribs->push_back(recordAttribute(variable));
763 break;
764 case EvqFragmentOut:
765 mOutputVariables->push_back(recordOutputVariable(variable));
766 break;
767 case EvqUniform:
768 mUniforms->push_back(recordUniform(variable));
769 break;
770 default:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800771 if (IsVaryingIn(qualifier))
772 {
773 mInputVaryings->push_back(recordVarying(variable));
774 }
775 else
776 {
777 ASSERT(IsVaryingOut(qualifier));
778 mOutputVaryings->push_back(recordVarying(variable));
779 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000780 break;
781 }
782 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000783 }
784
Olli Etuahoa55102c2017-02-24 12:36:50 +0000785 // None of the recorded variables can have initializers, so we don't need to traverse the
786 // declarators.
787 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000788}
Jamie Madill23a8a432014-07-09 13:27:42 -0400789
Jiawei Shaod8105a02017-08-08 09:54:36 +0800790// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
Jiawei Shaobd924af2017-11-16 15:28:04 +0800791// GL_EXT_shader_io_blocks.
Jiawei Shaod8105a02017-08-08 09:54:36 +0800792InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(const TString &blockName) const
793{
794 InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
795 if (!namedBlock)
796 {
797 namedBlock = FindVariable(blockName, mShaderStorageBlocks);
798 }
799 return namedBlock;
800}
801
Olli Etuaho19515012017-06-26 18:00:17 +0300802bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
Jamie Madillb547ddf2014-08-25 16:20:46 -0400803{
804 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
805 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400806 // NOTE: we do not determine static use for individual blocks of an array
807 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
808 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400809
810 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
811 ASSERT(constantUnion);
812
Jiawei Shaod8105a02017-08-08 09:54:36 +0800813 InterfaceBlock *namedBlock = nullptr;
814
815 bool traverseIndexExpression = false;
816 TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
817 if (interfaceIndexingNode)
818 {
819 TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
820 ASSERT(interfaceNode);
821
822 const TType &interfaceType = interfaceNode->getType();
823 if (interfaceType.getQualifier() == EvqPerVertexIn)
824 {
825 namedBlock = recordGLInUsed(interfaceType);
826 ASSERT(namedBlock);
827
828 // We need to continue traversing to collect useful variables in the index
829 // expression of gl_in.
830 traverseIndexExpression = true;
831 }
832 }
833
Jamie Madilla6f267f2014-08-27 11:44:15 -0400834 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800835 if (!namedBlock)
Jiajia Qinbc585152017-06-23 15:42:17 +0800836 {
Olli Etuahobed35d72017-12-20 16:36:26 +0200837 namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
Jiajia Qinbc585152017-06-23 15:42:17 +0800838 }
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800839 ASSERT(namedBlock);
840 namedBlock->staticUse = true;
841 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
842 ASSERT(fieldIndex < namedBlock->fields.size());
843 namedBlock->fields[fieldIndex].staticUse = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800844
845 if (traverseIndexExpression)
846 {
847 ASSERT(interfaceIndexingNode);
848 interfaceIndexingNode->getRight()->traverse(this);
849 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400850 return false;
851 }
852
853 return true;
854}
855
Olli Etuaho19515012017-06-26 18:00:17 +0300856} // anonymous namespace
857
858void CollectVariables(TIntermBlock *root,
859 std::vector<Attribute> *attributes,
860 std::vector<OutputVariable> *outputVariables,
861 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800862 std::vector<Varying> *inputVaryings,
863 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800864 std::vector<InterfaceBlock> *uniformBlocks,
865 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800866 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300867 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300868 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300869 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800870 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300871 const TExtensionBehavior &extensionBehavior)
872{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800873 CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800874 outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800875 hashFunction, symbolTable, shaderVersion, shaderType,
876 extensionBehavior);
Olli Etuaho19515012017-06-26 18:00:17 +0300877 root->traverse(&collect);
878}
879
Olli Etuaho19515012017-06-26 18:00:17 +0300880} // namespace sh