blob: aa00fdb1ce3c420fdb5e8dea173654bb9945c5fc [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"
Olli Etuaho19515012017-06-26 18:00:17 +030013#include "compiler/translator/SymbolTable.h"
Olli Etuahoc26214d2018-03-16 10:43:11 +020014#include "compiler/translator/tree_util/IntermTraverse.h"
Olli Etuaho19515012017-06-26 18:00:17 +030015#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>
Olli Etuahofbb1c792018-01-19 16:26:59 +020059VarT *FindVariable(const ImmutableString &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 {
Olli Etuahofbb1c792018-01-19 16:26:59 +020064 if (name == (*infoList)[ii].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 Etuaho94bbed12018-03-20 14:44:53 +020071// Note that this shouldn't be called for interface blocks - active information is collected for
Olli Etuaho06a06f52017-07-12 12:22:15 +030072// individual fields in case of interface blocks.
Olli Etuaho94bbed12018-03-20 14:44:53 +020073void MarkActive(ShaderVariable *variable)
Olli Etuaho06a06f52017-07-12 12:22:15 +030074{
Olli Etuaho94bbed12018-03-20 14:44:53 +020075 if (!variable->active)
Olli Etuaho06a06f52017-07-12 12:22:15 +030076 {
77 if (variable->isStruct())
78 {
79 // Conservatively assume all fields are statically used as well.
80 for (auto &field : variable->fields)
81 {
Olli Etuaho94bbed12018-03-20 14:44:53 +020082 MarkActive(&field);
Olli Etuaho06a06f52017-07-12 12:22:15 +030083 }
84 }
Olli Etuaho94bbed12018-03-20 14:44:53 +020085 ASSERT(variable->staticUse);
Olli Etuaho107c7242018-03-20 15:45:35 +020086 variable->active = true;
Olli Etuaho06a06f52017-07-12 12:22:15 +030087 }
88}
89
Olli Etuahofbb1c792018-01-19 16:26:59 +020090ShaderVariable *FindVariableInInterfaceBlock(const ImmutableString &name,
Jiajia Qin3a9090f2017-09-27 14:37:04 +080091 const TInterfaceBlock *interfaceBlock,
92 std::vector<InterfaceBlock> *infoList)
93{
94 ASSERT(interfaceBlock);
Olli Etuahobed35d72017-12-20 16:36:26 +020095 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
Jiajia Qin3a9090f2017-09-27 14:37:04 +080096 ASSERT(namedBlock);
97
98 // Set static use on the parent interface block here
99 namedBlock->staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200100 namedBlock->active = true;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800101 return FindVariable(name, &namedBlock->fields);
102}
103
Olli Etuaho19515012017-06-26 18:00:17 +0300104// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
105// and interface blocks.
106class CollectVariablesTraverser : public TIntermTraverser
107{
108 public:
109 CollectVariablesTraverser(std::vector<Attribute> *attribs,
110 std::vector<OutputVariable> *outputVariables,
111 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800112 std::vector<Varying> *inputVaryings,
113 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800114 std::vector<InterfaceBlock> *uniformBlocks,
115 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800116 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300117 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300118 TSymbolTable *symbolTable,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800119 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300120 const TExtensionBehavior &extensionBehavior);
121
Olli Etuahobb52c522018-04-06 10:22:22 +0300122 bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
Olli Etuaho19515012017-06-26 18:00:17 +0300123 void visitSymbol(TIntermSymbol *symbol) override;
124 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
125 bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
126
127 private:
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200128 std::string getMappedName(const TSymbol *symbol) const;
Olli Etuaho855d9642017-05-17 14:05:06 +0300129
Olli Etuaho94bbed12018-03-20 14:44:53 +0200130 void setFieldOrVariableProperties(const TType &type,
131 bool staticUse,
132 ShaderVariable *variableOut) const;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200133 void setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200134 const ImmutableString &name,
Olli Etuaho94bbed12018-03-20 14:44:53 +0200135 bool staticUse,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200136 ShaderVariable *variableOut) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300137 void setCommonVariableProperties(const TType &type,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200138 const TVariable &variable,
Olli Etuaho19515012017-06-26 18:00:17 +0300139 ShaderVariable *variableOut) const;
140
141 Attribute recordAttribute(const TIntermSymbol &variable) const;
142 OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
143 Varying recordVarying(const TIntermSymbol &variable) const;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200144 void recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200145 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800146 InterfaceBlock *interfaceBlock) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300147 Uniform recordUniform(const TIntermSymbol &variable) const;
148
Olli Etuaho822a84b2018-03-23 12:30:18 +0200149 void setBuiltInInfoFromSymbol(const TVariable &variable, ShaderVariable *info);
Olli Etuaho19515012017-06-26 18:00:17 +0300150
Olli Etuaho822a84b2018-03-23 12:30:18 +0200151 void recordBuiltInVaryingUsed(const TVariable &variable,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800152 bool *addedFlag,
153 std::vector<Varying> *varyings);
Olli Etuaho822a84b2018-03-23 12:30:18 +0200154 void recordBuiltInFragmentOutputUsed(const TVariable &variable, bool *addedFlag);
155 void recordBuiltInAttributeUsed(const TVariable &variable, bool *addedFlag);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800156 InterfaceBlock *recordGLInUsed(const TType &glInType);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200157 InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300158
159 std::vector<Attribute> *mAttribs;
160 std::vector<OutputVariable> *mOutputVariables;
161 std::vector<Uniform> *mUniforms;
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800162 std::vector<Varying> *mInputVaryings;
163 std::vector<Varying> *mOutputVaryings;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800164 std::vector<InterfaceBlock> *mUniformBlocks;
165 std::vector<InterfaceBlock> *mShaderStorageBlocks;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800166 std::vector<InterfaceBlock> *mInBlocks;
Olli Etuaho19515012017-06-26 18:00:17 +0300167
168 std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
169
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800170 // Shader uniforms
Olli Etuaho19515012017-06-26 18:00:17 +0300171 bool mDepthRangeAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800172
173 // Vertex Shader builtins
174 bool mInstanceIDAdded;
175 bool mVertexIDAdded;
176 bool mPointSizeAdded;
177
178 // Vertex Shader and Geometry Shader builtins
179 bool mPositionAdded;
180
181 // Fragment Shader builtins
Olli Etuaho19515012017-06-26 18:00:17 +0300182 bool mPointCoordAdded;
183 bool mFrontFacingAdded;
184 bool mFragCoordAdded;
Olli Etuaho19515012017-06-26 18:00:17 +0300185 bool mLastFragDataAdded;
186 bool mFragColorAdded;
187 bool mFragDataAdded;
188 bool mFragDepthEXTAdded;
189 bool mFragDepthAdded;
190 bool mSecondaryFragColorEXTAdded;
191 bool mSecondaryFragDataEXTAdded;
192
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800193 // Geometry Shader builtins
Jiawei Shaod8105a02017-08-08 09:54:36 +0800194 bool mPerVertexInAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800195 bool mPrimitiveIDInAdded;
196 bool mInvocationIDAdded;
197
198 // Geometry Shader and Fragment Shader builtins
199 bool mPrimitiveIDAdded;
200 bool mLayerAdded;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800201
Olli Etuaho19515012017-06-26 18:00:17 +0300202 ShHashFunction64 mHashFunction;
203
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800204 GLenum mShaderType;
Olli Etuaho19515012017-06-26 18:00:17 +0300205 const TExtensionBehavior &mExtensionBehavior;
206};
207
208CollectVariablesTraverser::CollectVariablesTraverser(
209 std::vector<sh::Attribute> *attribs,
210 std::vector<sh::OutputVariable> *outputVariables,
211 std::vector<sh::Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800212 std::vector<sh::Varying> *inputVaryings,
213 std::vector<sh::Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800214 std::vector<sh::InterfaceBlock> *uniformBlocks,
215 std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800216 std::vector<sh::InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300217 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300218 TSymbolTable *symbolTable,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800219 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300220 const TExtensionBehavior &extensionBehavior)
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300221 : TIntermTraverser(true, false, false, symbolTable),
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300222 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400223 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000224 mUniforms(uniforms),
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800225 mInputVaryings(inputVaryings),
226 mOutputVaryings(outputVaryings),
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800227 mUniformBlocks(uniformBlocks),
228 mShaderStorageBlocks(shaderStorageBlocks),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800229 mInBlocks(inBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400230 mDepthRangeAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800231 mInstanceIDAdded(false),
232 mVertexIDAdded(false),
233 mPointSizeAdded(false),
234 mPositionAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400235 mPointCoordAdded(false),
236 mFrontFacingAdded(false),
237 mFragCoordAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100238 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300239 mFragColorAdded(false),
240 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300241 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300242 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300243 mSecondaryFragColorEXTAdded(false),
244 mSecondaryFragDataEXTAdded(false),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800245 mPerVertexInAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800246 mPrimitiveIDInAdded(false),
247 mInvocationIDAdded(false),
248 mPrimitiveIDAdded(false),
249 mLayerAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700250 mHashFunction(hashFunction),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800251 mShaderType(shaderType),
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700252 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000253{
254}
255
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200256std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const
Olli Etuaho855d9642017-05-17 14:05:06 +0300257{
Olli Etuahofbb1c792018-01-19 16:26:59 +0200258 return HashName(symbol, mHashFunction, nullptr).data();
Olli Etuaho855d9642017-05-17 14:05:06 +0300259}
260
Olli Etuaho822a84b2018-03-23 12:30:18 +0200261void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable,
262 ShaderVariable *info)
Olli Etuaho19515012017-06-26 18:00:17 +0300263{
Olli Etuaho822a84b2018-03-23 12:30:18 +0200264 const TType &type = variable.getType();
Olli Etuaho19515012017-06-26 18:00:17 +0300265
Olli Etuaho822a84b2018-03-23 12:30:18 +0200266 info->name = variable.name().data();
267 info->mappedName = variable.name().data();
Olli Etuaho19515012017-06-26 18:00:17 +0300268 info->type = GLVariableType(type);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300269 info->precision = GLVariablePrecision(type);
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800270 if (auto *arraySizes = type.getArraySizes())
271 {
272 info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
273 }
Olli Etuaho19515012017-06-26 18:00:17 +0300274}
275
Olli Etuaho822a84b2018-03-23 12:30:18 +0200276void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800277 bool *addedFlag,
278 std::vector<Varying> *varyings)
Olli Etuaho19515012017-06-26 18:00:17 +0300279{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800280 ASSERT(varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300281 if (!(*addedFlag))
282 {
283 Varying info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200284 setBuiltInInfoFromSymbol(variable, &info);
Olli Etuaho19515012017-06-26 18:00:17 +0300285 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200286 info.active = true;
Olli Etuaho76b2c382018-03-19 15:51:29 +0200287 info.isInvariant = mSymbolTable->isVaryingInvariant(variable);
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800288 varyings->push_back(info);
Olli Etuaho19515012017-06-26 18:00:17 +0300289 (*addedFlag) = true;
290 }
291}
292
Olli Etuaho822a84b2018-03-23 12:30:18 +0200293void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const TVariable &variable,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200294 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300295{
296 if (!(*addedFlag))
297 {
298 OutputVariable info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200299 setBuiltInInfoFromSymbol(variable, &info);
Olli Etuaho19515012017-06-26 18:00:17 +0300300 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200301 info.active = true;
Olli Etuaho19515012017-06-26 18:00:17 +0300302 mOutputVariables->push_back(info);
303 (*addedFlag) = true;
304 }
305}
306
Olli Etuaho822a84b2018-03-23 12:30:18 +0200307void CollectVariablesTraverser::recordBuiltInAttributeUsed(const TVariable &variable,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200308 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300309{
310 if (!(*addedFlag))
311 {
312 Attribute info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200313 setBuiltInInfoFromSymbol(variable, &info);
Olli Etuaho19515012017-06-26 18:00:17 +0300314 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200315 info.active = true;
Olli Etuaho19515012017-06-26 18:00:17 +0300316 info.location = -1;
317 mAttribs->push_back(info);
318 (*addedFlag) = true;
319 }
320}
321
Jiawei Shaod8105a02017-08-08 09:54:36 +0800322InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
323{
324 if (!mPerVertexInAdded)
325 {
326 ASSERT(glInType.getQualifier() == EvqPerVertexIn);
327 InterfaceBlock info;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200328 recordInterfaceBlock("gl_in", glInType, &info);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800329
330 mPerVertexInAdded = true;
331 mInBlocks->push_back(info);
332 return &mInBlocks->back();
333 }
334 else
335 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200336 return FindVariable(ImmutableString("gl_PerVertex"), mInBlocks);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800337 }
338}
339
Olli Etuahobb52c522018-04-06 10:22:22 +0300340bool CollectVariablesTraverser::visitInvariantDeclaration(Visit visit,
341 TIntermInvariantDeclaration *node)
342{
343 // We should not mark variables as active just based on an invariant declaration, so we don't
344 // traverse the symbols declared invariant.
345 return false;
346}
347
348// We want to check whether a uniform/varying is active because we need to skip updating inactive
349// ones. We also only count the active ones in packing computing. Also, gl_FragCoord, gl_PointCoord,
350// and gl_FrontFacing count toward varying counting if they are active in a fragment shader.
Olli Etuaho19515012017-06-26 18:00:17 +0300351void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000352{
Yunchao He4f285442017-04-21 12:15:49 +0800353 ASSERT(symbol != nullptr);
Olli Etuaho34d20072017-07-18 20:07:18 +0300354
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200355 if (symbol->variable().symbolType() == SymbolType::AngleInternal ||
356 symbol->variable().symbolType() == SymbolType::Empty)
Olli Etuaho34d20072017-07-18 20:07:18 +0300357 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200358 // Internal variables or nameless variables are not collected.
Olli Etuaho34d20072017-07-18 20:07:18 +0300359 return;
360 }
361
Yunchao Hed7297bf2017-04-19 15:27:10 +0800362 ShaderVariable *var = nullptr;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200363
Olli Etuahofbb1c792018-01-19 16:26:59 +0200364 const ImmutableString &symbolName = symbol->getName();
Jamie Madill4667c452014-07-08 15:02:36 -0400365
Olli Etuahob8cb9392017-12-20 14:23:19 +0200366 // Check the qualifier from the variable, not from the symbol node. The node may have a
367 // different qualifier if it's the result of a folded ternary node.
368 TQualifier qualifier = symbol->variable().getType().getQualifier();
369
370 if (IsVaryingIn(qualifier))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400371 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800372 var = FindVariable(symbolName, mInputVaryings);
373 }
Olli Etuahob8cb9392017-12-20 14:23:19 +0200374 else if (IsVaryingOut(qualifier))
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800375 {
376 var = FindVariable(symbolName, mOutputVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400377 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400378 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
379 {
380 UNREACHABLE();
381 }
Jamie Madill55def582015-05-04 11:24:57 -0400382 else if (symbolName == "gl_DepthRange")
383 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200384 ASSERT(qualifier == EvqUniform);
Jamie Madill55def582015-05-04 11:24:57 -0400385
386 if (!mDepthRangeAdded)
387 {
388 Uniform info;
389 const char kName[] = "gl_DepthRange";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500390 info.name = kName;
391 info.mappedName = kName;
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400392 info.type = GL_NONE;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500393 info.precision = GL_NONE;
394 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200395 info.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400396
Olli Etuahoe7c28572017-10-23 16:29:33 +0300397 ShaderVariable nearInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400398 const char kNearName[] = "near";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500399 nearInfo.name = kNearName;
400 nearInfo.mappedName = kNearName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500401 nearInfo.precision = GL_HIGH_FLOAT;
402 nearInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200403 nearInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400404
Olli Etuahoe7c28572017-10-23 16:29:33 +0300405 ShaderVariable farInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400406 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500407 farInfo.name = kFarName;
408 farInfo.mappedName = kFarName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500409 farInfo.precision = GL_HIGH_FLOAT;
410 farInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200411 farInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400412
Olli Etuahoe7c28572017-10-23 16:29:33 +0300413 ShaderVariable diffInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400414 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500415 diffInfo.name = kDiffName;
416 diffInfo.mappedName = kDiffName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500417 diffInfo.precision = GL_HIGH_FLOAT;
418 diffInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200419 diffInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400420
421 info.fields.push_back(nearInfo);
422 info.fields.push_back(farInfo);
423 info.fields.push_back(diffInfo);
424
425 mUniforms->push_back(info);
426 mDepthRangeAdded = true;
427 }
428 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400429 else
Jamie Madill4667c452014-07-08 15:02:36 -0400430 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200431 switch (qualifier)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400432 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500433 case EvqAttribute:
434 case EvqVertexIn:
435 var = FindVariable(symbolName, mAttribs);
436 break;
437 case EvqFragmentOut:
438 var = FindVariable(symbolName, mOutputVariables);
439 break;
440 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400441 {
442 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
443 if (interfaceBlock)
444 {
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800445 var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400446 }
447 else
448 {
449 var = FindVariable(symbolName, mUniforms);
450 }
451
452 // It's an internal error to reference an undefined user uniform
Olli Etuahofbb1c792018-01-19 16:26:59 +0200453 ASSERT(!symbolName.beginsWith("gl_") || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400454 }
Jamie Madill4667c452014-07-08 15:02:36 -0400455 break;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800456 case EvqBuffer:
457 {
458 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
459 var =
460 FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
461 }
462 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500463 case EvqFragCoord:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200464 recordBuiltInVaryingUsed(symbol->variable(), &mFragCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500465 return;
466 case EvqFrontFacing:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200467 recordBuiltInVaryingUsed(symbol->variable(), &mFrontFacingAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500468 return;
469 case EvqPointCoord:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200470 recordBuiltInVaryingUsed(symbol->variable(), &mPointCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500471 return;
472 case EvqInstanceID:
Martin Radev115fc552017-07-05 17:11:06 +0300473 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
474 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
Olli Etuaho822a84b2018-03-23 12:30:18 +0200475 // InstanceID. Note that gl_InstanceID is not added to the symbol table for ESSL1
476 // shaders.
477 recordBuiltInAttributeUsed(symbol->variable(), &mInstanceIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500478 return;
479 case EvqVertexID:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200480 recordBuiltInAttributeUsed(symbol->variable(), &mVertexIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500481 return;
482 case EvqPosition:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200483 recordBuiltInVaryingUsed(symbol->variable(), &mPositionAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500484 return;
485 case EvqPointSize:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200486 recordBuiltInVaryingUsed(symbol->variable(), &mPointSizeAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500487 return;
488 case EvqLastFragData:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200489 recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500490 return;
491 case EvqFragColor:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200492 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragColorAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500493 return;
494 case EvqFragData:
495 if (!mFragDataAdded)
496 {
497 OutputVariable info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200498 setBuiltInInfoFromSymbol(symbol->variable(), &info);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300499 if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500500 {
Olli Etuaho465835d2017-09-26 13:34:10 +0300501 ASSERT(info.arraySizes.size() == 1u);
502 info.arraySizes.back() = 1u;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500503 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500504 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200505 info.active = true;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500506 mOutputVariables->push_back(info);
507 mFragDataAdded = true;
508 }
509 return;
510 case EvqFragDepthEXT:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200511 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500512 return;
513 case EvqFragDepth:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200514 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500515 return;
516 case EvqSecondaryFragColorEXT:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200517 recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragColorEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500518 return;
519 case EvqSecondaryFragDataEXT:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200520 recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragDataEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500521 return;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800522 case EvqInvocationID:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200523 recordBuiltInVaryingUsed(symbol->variable(), &mInvocationIDAdded, mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800524 break;
525 case EvqPrimitiveIDIn:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200526 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDInAdded, mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800527 break;
528 case EvqPrimitiveID:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800529 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800530 {
Olli Etuaho822a84b2018-03-23 12:30:18 +0200531 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200532 mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800533 }
534 else
535 {
536 ASSERT(mShaderType == GL_FRAGMENT_SHADER);
Olli Etuaho822a84b2018-03-23 12:30:18 +0200537 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200538 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800539 }
540 break;
541 case EvqLayer:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800542 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800543 {
Olli Etuaho822a84b2018-03-23 12:30:18 +0200544 recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800545 }
546 else if (mShaderType == GL_FRAGMENT_SHADER)
547 {
Olli Etuaho822a84b2018-03-23 12:30:18 +0200548 recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800549 }
550 else
551 {
552 ASSERT(mShaderType == GL_VERTEX_SHADER &&
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300553 IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800554 }
555 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500556 default:
557 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400558 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400559 }
560 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400561 {
Olli Etuaho94bbed12018-03-20 14:44:53 +0200562 MarkActive(var);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400563 }
564}
565
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200566void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
Olli Etuaho94bbed12018-03-20 14:44:53 +0200567 bool staticUse,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200568 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400569{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000570 ASSERT(variableOut);
571
Olli Etuaho94bbed12018-03-20 14:44:53 +0200572 variableOut->staticUse = staticUse;
573
Olli Etuahoa55102c2017-02-24 12:36:50 +0000574 const TStructure *structure = type.getStruct();
Olli Etuahoa55102c2017-02-24 12:36:50 +0000575 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500576 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000577 variableOut->type = GLVariableType(type);
578 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500579 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000580 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400581 {
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400582 // Structures use a NONE type that isn't exposed outside ANGLE.
583 variableOut->type = GL_NONE;
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100584 if (structure->symbolType() != SymbolType::Empty)
585 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200586 variableOut->structName = structure->name().data();
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100587 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000588
589 const TFieldList &fields = structure->fields();
590
Olli Etuaho378c3a52017-12-04 11:32:13 +0200591 for (const TField *field : fields)
Olli Etuahoa55102c2017-02-24 12:36:50 +0000592 {
593 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
594 // ShaderVariable objects.
595 ShaderVariable fieldVariable;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200596 setFieldProperties(*field->type(), field->name(), staticUse, &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000597 variableOut->fields.push_back(fieldVariable);
598 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400599 }
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800600 if (auto *arraySizes = type.getArraySizes())
601 {
602 variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
603 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000604}
Jamie Madill23a8a432014-07-09 13:27:42 -0400605
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200606void CollectVariablesTraverser::setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200607 const ImmutableString &name,
Olli Etuaho94bbed12018-03-20 14:44:53 +0200608 bool staticUse,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200609 ShaderVariable *variableOut) const
610{
611 ASSERT(variableOut);
Olli Etuaho94bbed12018-03-20 14:44:53 +0200612 setFieldOrVariableProperties(type, staticUse, variableOut);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200613 variableOut->name.assign(name.data(), name.length());
614 variableOut->mappedName = HashName(name, mHashFunction, nullptr).data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200615}
616
617void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
618 const TVariable &variable,
619 ShaderVariable *variableOut) const
620{
621 ASSERT(variableOut);
622
Olli Etuaho94bbed12018-03-20 14:44:53 +0200623 variableOut->staticUse = mSymbolTable->isStaticallyUsed(variable);
624 setFieldOrVariableProperties(type, variableOut->staticUse, variableOut);
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200625 ASSERT(variable.symbolType() != SymbolType::Empty);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200626 variableOut->name.assign(variable.name().data(), variable.name().length());
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200627 variableOut->mappedName = getMappedName(&variable);
628}
629
Olli Etuaho19515012017-06-26 18:00:17 +0300630Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400631{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000632 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400633 ASSERT(!type.getStruct());
634
Jamie Madilla2fbb842014-09-03 09:40:47 -0400635 Attribute attribute;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200636 setCommonVariableProperties(type, variable.variable(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400637
Olli Etuahoa55102c2017-02-24 12:36:50 +0000638 attribute.location = type.getLayoutQualifier().location;
639 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400640}
641
Olli Etuaho19515012017-06-26 18:00:17 +0300642OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400643{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000644 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400645 ASSERT(!type.getStruct());
646
Olli Etuahoa55102c2017-02-24 12:36:50 +0000647 OutputVariable outputVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200648 setCommonVariableProperties(type, variable.variable(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400649
Olli Etuahoa55102c2017-02-24 12:36:50 +0000650 outputVariable.location = type.getLayoutQualifier().location;
Olli Etuahoa78092c2018-09-26 14:16:13 +0300651 outputVariable.index = type.getLayoutQualifier().index;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000652 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400653}
654
Olli Etuaho19515012017-06-26 18:00:17 +0300655Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400656{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000657 const TType &type = variable.getType();
658
659 Varying varying;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200660 setCommonVariableProperties(type, variable.variable(), &varying);
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800661 varying.location = type.getLayoutQualifier().location;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000662
663 switch (type.getQualifier())
664 {
665 case EvqVaryingIn:
666 case EvqVaryingOut:
667 case EvqVertexOut:
668 case EvqSmoothOut:
669 case EvqFlatOut:
670 case EvqCentroidOut:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800671 case EvqGeometryOut:
Olli Etuaho76b2c382018-03-19 15:51:29 +0200672 if (mSymbolTable->isVaryingInvariant(variable.variable()) || type.isInvariant())
Olli Etuahoa55102c2017-02-24 12:36:50 +0000673 {
674 varying.isInvariant = true;
675 }
676 break;
677 default:
678 break;
679 }
680
681 varying.interpolation = GetInterpolationType(type.getQualifier());
682 return varying;
683}
684
Jiawei Shaobd924af2017-11-16 15:28:04 +0800685// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200686void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200687 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800688 InterfaceBlock *interfaceBlock) const
Olli Etuahoa55102c2017-02-24 12:36:50 +0000689{
Jiawei Shaod8105a02017-08-08 09:54:36 +0800690 ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
691 ASSERT(interfaceBlock);
692
693 const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400694 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400695
Olli Etuahofbb1c792018-01-19 16:26:59 +0200696 interfaceBlock->name = blockType->name().data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200697 interfaceBlock->mappedName = getMappedName(blockType);
698 if (instanceName != nullptr)
699 {
700 interfaceBlock->instanceName = instanceName;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200701 const TSymbol *blockSymbol = nullptr;
702 if (strncmp(instanceName, "gl_in", 5u) == 0)
703 {
704 blockSymbol = mSymbolTable->getGlInVariableWithArraySize();
705 }
706 else
707 {
708 blockSymbol = mSymbolTable->findGlobal(ImmutableString(instanceName));
709 }
710 ASSERT(blockSymbol && blockSymbol->isVariable());
711 interfaceBlock->staticUse =
712 mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(blockSymbol));
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200713 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300714 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
715 interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800716
717 interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
718 if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
719 interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
720 {
Olli Etuaho3de27032017-11-30 12:16:47 +0200721 // TODO(oetuaho): Remove setting isRowMajorLayout.
722 interfaceBlock->isRowMajorLayout = false;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800723 interfaceBlock->binding = blockType->blockBinding();
724 interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
725 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400726
Jamie Madilla6f267f2014-08-27 11:44:15 -0400727 // Gather field information
Olli Etuaho94bbed12018-03-20 14:44:53 +0200728 bool anyFieldStaticallyUsed = false;
Jamie Madill39046162016-02-08 15:05:17 -0500729 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400730 {
Jamie Madill39046162016-02-08 15:05:17 -0500731 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400732
Olli Etuaho94bbed12018-03-20 14:44:53 +0200733 bool staticUse = false;
734 if (instanceName == nullptr)
735 {
736 // Static use of individual fields has been recorded, since they are present in the
737 // symbol table as variables.
738 const TSymbol *fieldSymbol = mSymbolTable->findGlobal(field->name());
739 ASSERT(fieldSymbol && fieldSymbol->isVariable());
740 staticUse =
741 mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(fieldSymbol));
742 if (staticUse)
743 {
744 anyFieldStaticallyUsed = true;
745 }
746 }
747
Olli Etuahoa55102c2017-02-24 12:36:50 +0000748 InterfaceBlockField fieldVariable;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200749 setFieldProperties(fieldType, field->name(), staticUse, &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000750 fieldVariable.isRowMajorLayout =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500751 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800752 interfaceBlock->fields.push_back(fieldVariable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400753 }
Olli Etuaho94bbed12018-03-20 14:44:53 +0200754 if (anyFieldStaticallyUsed)
755 {
756 interfaceBlock->staticUse = true;
757 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400758}
759
Olli Etuaho19515012017-06-26 18:00:17 +0300760Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400761{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000762 Uniform uniform;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200763 setCommonVariableProperties(variable.getType(), variable.variable(), &uniform);
Olli Etuaho78ed6cd2017-08-09 16:19:00 +0300764 uniform.binding = variable.getType().getLayoutQualifier().binding;
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000765 uniform.location = variable.getType().getLayoutQualifier().location;
jchen104cdac9e2017-05-08 11:01:20 +0800766 uniform.offset = variable.getType().getLayoutQualifier().offset;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800767 uniform.readonly = variable.getType().getMemoryQualifier().readonly;
768 uniform.writeonly = variable.getType().getMemoryQualifier().writeonly;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000769 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000770}
771
Olli Etuaho19515012017-06-26 18:00:17 +0300772bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000773{
Olli Etuaho13389b62016-10-16 11:48:18 +0100774 const TIntermSequence &sequence = *(node->getSequence());
775 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000776
Olli Etuaho13389b62016-10-16 11:48:18 +0100777 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
778 TQualifier qualifier = typedNode.getQualifier();
779
Olli Etuahoa55102c2017-02-24 12:36:50 +0000780 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
781 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
782 IsVarying(qualifier);
783
784 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000785 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000786 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100787 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000788
789 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100790 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000791 // The only case in which the sequence will not contain a TIntermSymbol node is
792 // initialization. It will contain a TInterBinary node in that case. Since attributes,
793 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
794 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
795 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200796 if (variable.variable().symbolType() == SymbolType::AngleInternal)
Olli Etuaho34d20072017-07-18 20:07:18 +0300797 {
798 // Internal variables are not collected.
799 continue;
800 }
801
Jiawei Shaobd924af2017-11-16 15:28:04 +0800802 // TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuahoa55102c2017-02-24 12:36:50 +0000803 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000804 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800805 InterfaceBlock interfaceBlock;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200806 recordInterfaceBlock(variable.variable().symbolType() != SymbolType::Empty
Olli Etuahofbb1c792018-01-19 16:26:59 +0200807 ? variable.getName().data()
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200808 : nullptr,
809 variable.getType(), &interfaceBlock);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800810
811 switch (qualifier)
Jiajia Qinbc585152017-06-23 15:42:17 +0800812 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800813 case EvqUniform:
814 mUniformBlocks->push_back(interfaceBlock);
815 break;
816 case EvqBuffer:
817 mShaderStorageBlocks->push_back(interfaceBlock);
818 break;
819 default:
820 UNREACHABLE();
Jiajia Qinbc585152017-06-23 15:42:17 +0800821 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000822 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000823 else
824 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200825 ASSERT(variable.variable().symbolType() != SymbolType::Empty);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000826 switch (qualifier)
827 {
828 case EvqAttribute:
829 case EvqVertexIn:
830 mAttribs->push_back(recordAttribute(variable));
831 break;
832 case EvqFragmentOut:
833 mOutputVariables->push_back(recordOutputVariable(variable));
834 break;
835 case EvqUniform:
836 mUniforms->push_back(recordUniform(variable));
837 break;
838 default:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800839 if (IsVaryingIn(qualifier))
840 {
841 mInputVaryings->push_back(recordVarying(variable));
842 }
843 else
844 {
845 ASSERT(IsVaryingOut(qualifier));
846 mOutputVaryings->push_back(recordVarying(variable));
847 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000848 break;
849 }
850 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000851 }
852
Olli Etuahoa55102c2017-02-24 12:36:50 +0000853 // None of the recorded variables can have initializers, so we don't need to traverse the
854 // declarators.
855 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000856}
Jamie Madill23a8a432014-07-09 13:27:42 -0400857
Jiawei Shaod8105a02017-08-08 09:54:36 +0800858// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
Jiawei Shaobd924af2017-11-16 15:28:04 +0800859// GL_EXT_shader_io_blocks.
Olli Etuahofbb1c792018-01-19 16:26:59 +0200860InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(
861 const ImmutableString &blockName) const
Jiawei Shaod8105a02017-08-08 09:54:36 +0800862{
863 InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
864 if (!namedBlock)
865 {
866 namedBlock = FindVariable(blockName, mShaderStorageBlocks);
867 }
868 return namedBlock;
869}
870
Olli Etuaho19515012017-06-26 18:00:17 +0300871bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
Jamie Madillb547ddf2014-08-25 16:20:46 -0400872{
873 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
874 {
Olli Etuaho94bbed12018-03-20 14:44:53 +0200875 // NOTE: we do not determine static use / activeness for individual blocks of an array.
Jamie Madilla6f267f2014-08-27 11:44:15 -0400876 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
877 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400878
879 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
880 ASSERT(constantUnion);
881
Jiawei Shaod8105a02017-08-08 09:54:36 +0800882 InterfaceBlock *namedBlock = nullptr;
883
884 bool traverseIndexExpression = false;
885 TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
886 if (interfaceIndexingNode)
887 {
888 TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
889 ASSERT(interfaceNode);
890
891 const TType &interfaceType = interfaceNode->getType();
892 if (interfaceType.getQualifier() == EvqPerVertexIn)
893 {
894 namedBlock = recordGLInUsed(interfaceType);
895 ASSERT(namedBlock);
896
897 // We need to continue traversing to collect useful variables in the index
898 // expression of gl_in.
899 traverseIndexExpression = true;
900 }
901 }
902
Jamie Madilla6f267f2014-08-27 11:44:15 -0400903 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800904 if (!namedBlock)
Jiajia Qinbc585152017-06-23 15:42:17 +0800905 {
Olli Etuahobed35d72017-12-20 16:36:26 +0200906 namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
Jiajia Qinbc585152017-06-23 15:42:17 +0800907 }
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800908 ASSERT(namedBlock);
Olli Etuaho94bbed12018-03-20 14:44:53 +0200909 ASSERT(namedBlock->staticUse);
Olli Etuaho107c7242018-03-20 15:45:35 +0200910 namedBlock->active = true;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800911 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
912 ASSERT(fieldIndex < namedBlock->fields.size());
Olli Etuaho94bbed12018-03-20 14:44:53 +0200913 // TODO(oetuaho): Would be nicer to record static use of fields of named interface blocks
914 // more accurately at parse time - now we only mark the fields statically used if they are
915 // active. http://anglebug.com/2440
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800916 namedBlock->fields[fieldIndex].staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200917 namedBlock->fields[fieldIndex].active = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800918
919 if (traverseIndexExpression)
920 {
921 ASSERT(interfaceIndexingNode);
922 interfaceIndexingNode->getRight()->traverse(this);
923 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400924 return false;
925 }
926
927 return true;
928}
929
Olli Etuaho19515012017-06-26 18:00:17 +0300930} // anonymous namespace
931
932void CollectVariables(TIntermBlock *root,
933 std::vector<Attribute> *attributes,
934 std::vector<OutputVariable> *outputVariables,
935 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800936 std::vector<Varying> *inputVaryings,
937 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800938 std::vector<InterfaceBlock> *uniformBlocks,
939 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800940 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300941 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300942 TSymbolTable *symbolTable,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800943 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300944 const TExtensionBehavior &extensionBehavior)
945{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800946 CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800947 outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
Olli Etuaho822a84b2018-03-23 12:30:18 +0200948 hashFunction, symbolTable, shaderType, extensionBehavior);
Olli Etuaho19515012017-06-26 18:00:17 +0300949 root->traverse(&collect);
950}
951
Olli Etuaho19515012017-06-26 18:00:17 +0300952} // namespace sh