blob: 05196fdb1b669ad4c4ffaaf362968c665237358d [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
122 void visitSymbol(TIntermSymbol *symbol) override;
123 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
124 bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
125
126 private:
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200127 std::string getMappedName(const TSymbol *symbol) const;
Olli Etuaho855d9642017-05-17 14:05:06 +0300128
Olli Etuaho94bbed12018-03-20 14:44:53 +0200129 void setFieldOrVariableProperties(const TType &type,
130 bool staticUse,
131 ShaderVariable *variableOut) const;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200132 void setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200133 const ImmutableString &name,
Olli Etuaho94bbed12018-03-20 14:44:53 +0200134 bool staticUse,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200135 ShaderVariable *variableOut) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300136 void setCommonVariableProperties(const TType &type,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200137 const TVariable &variable,
Olli Etuaho19515012017-06-26 18:00:17 +0300138 ShaderVariable *variableOut) const;
139
140 Attribute recordAttribute(const TIntermSymbol &variable) const;
141 OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
142 Varying recordVarying(const TIntermSymbol &variable) const;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200143 void recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200144 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800145 InterfaceBlock *interfaceBlock) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300146 Uniform recordUniform(const TIntermSymbol &variable) const;
147
Olli Etuaho822a84b2018-03-23 12:30:18 +0200148 void setBuiltInInfoFromSymbol(const TVariable &variable, ShaderVariable *info);
Olli Etuaho19515012017-06-26 18:00:17 +0300149
Olli Etuaho822a84b2018-03-23 12:30:18 +0200150 void recordBuiltInVaryingUsed(const TVariable &variable,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800151 bool *addedFlag,
152 std::vector<Varying> *varyings);
Olli Etuaho822a84b2018-03-23 12:30:18 +0200153 void recordBuiltInFragmentOutputUsed(const TVariable &variable, bool *addedFlag);
154 void recordBuiltInAttributeUsed(const TVariable &variable, bool *addedFlag);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800155 InterfaceBlock *recordGLInUsed(const TType &glInType);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200156 InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300157
158 std::vector<Attribute> *mAttribs;
159 std::vector<OutputVariable> *mOutputVariables;
160 std::vector<Uniform> *mUniforms;
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800161 std::vector<Varying> *mInputVaryings;
162 std::vector<Varying> *mOutputVaryings;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800163 std::vector<InterfaceBlock> *mUniformBlocks;
164 std::vector<InterfaceBlock> *mShaderStorageBlocks;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800165 std::vector<InterfaceBlock> *mInBlocks;
Olli Etuaho19515012017-06-26 18:00:17 +0300166
167 std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
168
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800169 // Shader uniforms
Olli Etuaho19515012017-06-26 18:00:17 +0300170 bool mDepthRangeAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800171
172 // Vertex Shader builtins
173 bool mInstanceIDAdded;
174 bool mVertexIDAdded;
175 bool mPointSizeAdded;
176
177 // Vertex Shader and Geometry Shader builtins
178 bool mPositionAdded;
179
180 // Fragment Shader builtins
Olli Etuaho19515012017-06-26 18:00:17 +0300181 bool mPointCoordAdded;
182 bool mFrontFacingAdded;
183 bool mFragCoordAdded;
Olli Etuaho19515012017-06-26 18:00:17 +0300184 bool mLastFragDataAdded;
185 bool mFragColorAdded;
186 bool mFragDataAdded;
187 bool mFragDepthEXTAdded;
188 bool mFragDepthAdded;
189 bool mSecondaryFragColorEXTAdded;
190 bool mSecondaryFragDataEXTAdded;
191
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800192 // Geometry Shader builtins
Jiawei Shaod8105a02017-08-08 09:54:36 +0800193 bool mPerVertexInAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800194 bool mPrimitiveIDInAdded;
195 bool mInvocationIDAdded;
196
197 // Geometry Shader and Fragment Shader builtins
198 bool mPrimitiveIDAdded;
199 bool mLayerAdded;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800200
Olli Etuaho19515012017-06-26 18:00:17 +0300201 ShHashFunction64 mHashFunction;
202
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800203 GLenum mShaderType;
Olli Etuaho19515012017-06-26 18:00:17 +0300204 const TExtensionBehavior &mExtensionBehavior;
205};
206
207CollectVariablesTraverser::CollectVariablesTraverser(
208 std::vector<sh::Attribute> *attribs,
209 std::vector<sh::OutputVariable> *outputVariables,
210 std::vector<sh::Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800211 std::vector<sh::Varying> *inputVaryings,
212 std::vector<sh::Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800213 std::vector<sh::InterfaceBlock> *uniformBlocks,
214 std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800215 std::vector<sh::InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300216 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300217 TSymbolTable *symbolTable,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800218 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300219 const TExtensionBehavior &extensionBehavior)
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300220 : TIntermTraverser(true, false, false, symbolTable),
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300221 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400222 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000223 mUniforms(uniforms),
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800224 mInputVaryings(inputVaryings),
225 mOutputVaryings(outputVaryings),
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800226 mUniformBlocks(uniformBlocks),
227 mShaderStorageBlocks(shaderStorageBlocks),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800228 mInBlocks(inBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400229 mDepthRangeAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800230 mInstanceIDAdded(false),
231 mVertexIDAdded(false),
232 mPointSizeAdded(false),
233 mPositionAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400234 mPointCoordAdded(false),
235 mFrontFacingAdded(false),
236 mFragCoordAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100237 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300238 mFragColorAdded(false),
239 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300240 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300241 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300242 mSecondaryFragColorEXTAdded(false),
243 mSecondaryFragDataEXTAdded(false),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800244 mPerVertexInAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800245 mPrimitiveIDInAdded(false),
246 mInvocationIDAdded(false),
247 mPrimitiveIDAdded(false),
248 mLayerAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700249 mHashFunction(hashFunction),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800250 mShaderType(shaderType),
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700251 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000252{
253}
254
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200255std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const
Olli Etuaho855d9642017-05-17 14:05:06 +0300256{
Olli Etuahofbb1c792018-01-19 16:26:59 +0200257 return HashName(symbol, mHashFunction, nullptr).data();
Olli Etuaho855d9642017-05-17 14:05:06 +0300258}
259
Olli Etuaho822a84b2018-03-23 12:30:18 +0200260void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable,
261 ShaderVariable *info)
Olli Etuaho19515012017-06-26 18:00:17 +0300262{
Olli Etuaho822a84b2018-03-23 12:30:18 +0200263 const TType &type = variable.getType();
Olli Etuaho19515012017-06-26 18:00:17 +0300264
Olli Etuaho822a84b2018-03-23 12:30:18 +0200265 info->name = variable.name().data();
266 info->mappedName = variable.name().data();
Olli Etuaho19515012017-06-26 18:00:17 +0300267 info->type = GLVariableType(type);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300268 info->precision = GLVariablePrecision(type);
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800269 if (auto *arraySizes = type.getArraySizes())
270 {
271 info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
272 }
Olli Etuaho19515012017-06-26 18:00:17 +0300273}
274
Olli Etuaho822a84b2018-03-23 12:30:18 +0200275void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800276 bool *addedFlag,
277 std::vector<Varying> *varyings)
Olli Etuaho19515012017-06-26 18:00:17 +0300278{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800279 ASSERT(varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300280 if (!(*addedFlag))
281 {
282 Varying info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200283 setBuiltInInfoFromSymbol(variable, &info);
Olli Etuaho19515012017-06-26 18:00:17 +0300284 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200285 info.active = true;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200286 info.isInvariant = mSymbolTable->isVaryingInvariant(variable.name());
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800287 varyings->push_back(info);
Olli Etuaho19515012017-06-26 18:00:17 +0300288 (*addedFlag) = true;
289 }
290}
291
Olli Etuaho822a84b2018-03-23 12:30:18 +0200292void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const TVariable &variable,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200293 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300294{
295 if (!(*addedFlag))
296 {
297 OutputVariable info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200298 setBuiltInInfoFromSymbol(variable, &info);
Olli Etuaho19515012017-06-26 18:00:17 +0300299 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200300 info.active = true;
Olli Etuaho19515012017-06-26 18:00:17 +0300301 mOutputVariables->push_back(info);
302 (*addedFlag) = true;
303 }
304}
305
Olli Etuaho822a84b2018-03-23 12:30:18 +0200306void CollectVariablesTraverser::recordBuiltInAttributeUsed(const TVariable &variable,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200307 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300308{
309 if (!(*addedFlag))
310 {
311 Attribute info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200312 setBuiltInInfoFromSymbol(variable, &info);
Olli Etuaho19515012017-06-26 18:00:17 +0300313 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200314 info.active = true;
Olli Etuaho19515012017-06-26 18:00:17 +0300315 info.location = -1;
316 mAttribs->push_back(info);
317 (*addedFlag) = true;
318 }
319}
320
Jiawei Shaod8105a02017-08-08 09:54:36 +0800321InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
322{
323 if (!mPerVertexInAdded)
324 {
325 ASSERT(glInType.getQualifier() == EvqPerVertexIn);
326 InterfaceBlock info;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200327 recordInterfaceBlock("gl_in", glInType, &info);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800328
329 mPerVertexInAdded = true;
330 mInBlocks->push_back(info);
331 return &mInBlocks->back();
332 }
333 else
334 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200335 return FindVariable(ImmutableString("gl_PerVertex"), mInBlocks);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800336 }
337}
338
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400339// We want to check whether a uniform/varying is statically used
340// because we only count the used ones in packing computing.
341// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
342// toward varying counting if they are statically used in a fragment
343// shader.
Olli Etuaho19515012017-06-26 18:00:17 +0300344void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000345{
Yunchao He4f285442017-04-21 12:15:49 +0800346 ASSERT(symbol != nullptr);
Olli Etuaho34d20072017-07-18 20:07:18 +0300347
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200348 if (symbol->variable().symbolType() == SymbolType::AngleInternal ||
349 symbol->variable().symbolType() == SymbolType::Empty)
Olli Etuaho34d20072017-07-18 20:07:18 +0300350 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200351 // Internal variables or nameless variables are not collected.
Olli Etuaho34d20072017-07-18 20:07:18 +0300352 return;
353 }
354
Yunchao Hed7297bf2017-04-19 15:27:10 +0800355 ShaderVariable *var = nullptr;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200356
Olli Etuahofbb1c792018-01-19 16:26:59 +0200357 const ImmutableString &symbolName = symbol->getName();
Jamie Madill4667c452014-07-08 15:02:36 -0400358
Olli Etuahob8cb9392017-12-20 14:23:19 +0200359 // Check the qualifier from the variable, not from the symbol node. The node may have a
360 // different qualifier if it's the result of a folded ternary node.
361 TQualifier qualifier = symbol->variable().getType().getQualifier();
362
363 if (IsVaryingIn(qualifier))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400364 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800365 var = FindVariable(symbolName, mInputVaryings);
366 }
Olli Etuahob8cb9392017-12-20 14:23:19 +0200367 else if (IsVaryingOut(qualifier))
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800368 {
369 var = FindVariable(symbolName, mOutputVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400370 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400371 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
372 {
373 UNREACHABLE();
374 }
Jamie Madill55def582015-05-04 11:24:57 -0400375 else if (symbolName == "gl_DepthRange")
376 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200377 ASSERT(qualifier == EvqUniform);
Jamie Madill55def582015-05-04 11:24:57 -0400378
379 if (!mDepthRangeAdded)
380 {
381 Uniform info;
382 const char kName[] = "gl_DepthRange";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500383 info.name = kName;
384 info.mappedName = kName;
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400385 info.type = GL_NONE;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500386 info.precision = GL_NONE;
387 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200388 info.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400389
Olli Etuahoe7c28572017-10-23 16:29:33 +0300390 ShaderVariable nearInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400391 const char kNearName[] = "near";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500392 nearInfo.name = kNearName;
393 nearInfo.mappedName = kNearName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500394 nearInfo.precision = GL_HIGH_FLOAT;
395 nearInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200396 nearInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400397
Olli Etuahoe7c28572017-10-23 16:29:33 +0300398 ShaderVariable farInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400399 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500400 farInfo.name = kFarName;
401 farInfo.mappedName = kFarName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500402 farInfo.precision = GL_HIGH_FLOAT;
403 farInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200404 farInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400405
Olli Etuahoe7c28572017-10-23 16:29:33 +0300406 ShaderVariable diffInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400407 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500408 diffInfo.name = kDiffName;
409 diffInfo.mappedName = kDiffName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500410 diffInfo.precision = GL_HIGH_FLOAT;
411 diffInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200412 diffInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400413
414 info.fields.push_back(nearInfo);
415 info.fields.push_back(farInfo);
416 info.fields.push_back(diffInfo);
417
418 mUniforms->push_back(info);
419 mDepthRangeAdded = true;
420 }
421 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400422 else
Jamie Madill4667c452014-07-08 15:02:36 -0400423 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200424 switch (qualifier)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400425 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500426 case EvqAttribute:
427 case EvqVertexIn:
428 var = FindVariable(symbolName, mAttribs);
429 break;
430 case EvqFragmentOut:
431 var = FindVariable(symbolName, mOutputVariables);
432 break;
433 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400434 {
435 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
436 if (interfaceBlock)
437 {
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800438 var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400439 }
440 else
441 {
442 var = FindVariable(symbolName, mUniforms);
443 }
444
445 // It's an internal error to reference an undefined user uniform
Olli Etuahofbb1c792018-01-19 16:26:59 +0200446 ASSERT(!symbolName.beginsWith("gl_") || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400447 }
Jamie Madill4667c452014-07-08 15:02:36 -0400448 break;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800449 case EvqBuffer:
450 {
451 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
452 var =
453 FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
454 }
455 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500456 case EvqFragCoord:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200457 recordBuiltInVaryingUsed(symbol->variable(), &mFragCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500458 return;
459 case EvqFrontFacing:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200460 recordBuiltInVaryingUsed(symbol->variable(), &mFrontFacingAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500461 return;
462 case EvqPointCoord:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200463 recordBuiltInVaryingUsed(symbol->variable(), &mPointCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500464 return;
465 case EvqInstanceID:
Martin Radev115fc552017-07-05 17:11:06 +0300466 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
467 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
Olli Etuaho822a84b2018-03-23 12:30:18 +0200468 // InstanceID. Note that gl_InstanceID is not added to the symbol table for ESSL1
469 // shaders.
470 recordBuiltInAttributeUsed(symbol->variable(), &mInstanceIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500471 return;
472 case EvqVertexID:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200473 recordBuiltInAttributeUsed(symbol->variable(), &mVertexIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500474 return;
475 case EvqPosition:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200476 recordBuiltInVaryingUsed(symbol->variable(), &mPositionAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500477 return;
478 case EvqPointSize:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200479 recordBuiltInVaryingUsed(symbol->variable(), &mPointSizeAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500480 return;
481 case EvqLastFragData:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200482 recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500483 return;
484 case EvqFragColor:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200485 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragColorAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500486 return;
487 case EvqFragData:
488 if (!mFragDataAdded)
489 {
490 OutputVariable info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200491 setBuiltInInfoFromSymbol(symbol->variable(), &info);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300492 if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500493 {
Olli Etuaho465835d2017-09-26 13:34:10 +0300494 ASSERT(info.arraySizes.size() == 1u);
495 info.arraySizes.back() = 1u;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500496 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500497 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200498 info.active = true;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500499 mOutputVariables->push_back(info);
500 mFragDataAdded = true;
501 }
502 return;
503 case EvqFragDepthEXT:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200504 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500505 return;
506 case EvqFragDepth:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200507 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500508 return;
509 case EvqSecondaryFragColorEXT:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200510 recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragColorEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500511 return;
512 case EvqSecondaryFragDataEXT:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200513 recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragDataEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500514 return;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800515 case EvqInvocationID:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200516 recordBuiltInVaryingUsed(symbol->variable(), &mInvocationIDAdded, mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800517 break;
518 case EvqPrimitiveIDIn:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200519 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDInAdded, mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800520 break;
521 case EvqPrimitiveID:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800522 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800523 {
Olli Etuaho822a84b2018-03-23 12:30:18 +0200524 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200525 mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800526 }
527 else
528 {
529 ASSERT(mShaderType == GL_FRAGMENT_SHADER);
Olli Etuaho822a84b2018-03-23 12:30:18 +0200530 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200531 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800532 }
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 {
Olli Etuaho822a84b2018-03-23 12:30:18 +0200537 recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800538 }
539 else if (mShaderType == GL_FRAGMENT_SHADER)
540 {
Olli Etuaho822a84b2018-03-23 12:30:18 +0200541 recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800542 }
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 Etuaho94bbed12018-03-20 14:44:53 +0200555 MarkActive(var);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400556 }
557}
558
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200559void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
Olli Etuaho94bbed12018-03-20 14:44:53 +0200560 bool staticUse,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200561 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400562{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000563 ASSERT(variableOut);
564
Olli Etuaho94bbed12018-03-20 14:44:53 +0200565 variableOut->staticUse = staticUse;
566
Olli Etuahoa55102c2017-02-24 12:36:50 +0000567 const TStructure *structure = type.getStruct();
Olli Etuahoa55102c2017-02-24 12:36:50 +0000568 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500569 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000570 variableOut->type = GLVariableType(type);
571 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500572 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000573 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400574 {
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400575 // Structures use a NONE type that isn't exposed outside ANGLE.
576 variableOut->type = GL_NONE;
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100577 if (structure->symbolType() != SymbolType::Empty)
578 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200579 variableOut->structName = structure->name().data();
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100580 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000581
582 const TFieldList &fields = structure->fields();
583
Olli Etuaho378c3a52017-12-04 11:32:13 +0200584 for (const TField *field : fields)
Olli Etuahoa55102c2017-02-24 12:36:50 +0000585 {
586 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
587 // ShaderVariable objects.
588 ShaderVariable fieldVariable;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200589 setFieldProperties(*field->type(), field->name(), staticUse, &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000590 variableOut->fields.push_back(fieldVariable);
591 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400592 }
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800593 if (auto *arraySizes = type.getArraySizes())
594 {
595 variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
596 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000597}
Jamie Madill23a8a432014-07-09 13:27:42 -0400598
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200599void CollectVariablesTraverser::setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200600 const ImmutableString &name,
Olli Etuaho94bbed12018-03-20 14:44:53 +0200601 bool staticUse,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200602 ShaderVariable *variableOut) const
603{
604 ASSERT(variableOut);
Olli Etuaho94bbed12018-03-20 14:44:53 +0200605 setFieldOrVariableProperties(type, staticUse, variableOut);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200606 variableOut->name.assign(name.data(), name.length());
607 variableOut->mappedName = HashName(name, mHashFunction, nullptr).data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200608}
609
610void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
611 const TVariable &variable,
612 ShaderVariable *variableOut) const
613{
614 ASSERT(variableOut);
615
Olli Etuaho94bbed12018-03-20 14:44:53 +0200616 variableOut->staticUse = mSymbolTable->isStaticallyUsed(variable);
617 setFieldOrVariableProperties(type, variableOut->staticUse, variableOut);
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200618 ASSERT(variable.symbolType() != SymbolType::Empty);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200619 variableOut->name.assign(variable.name().data(), variable.name().length());
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200620 variableOut->mappedName = getMappedName(&variable);
621}
622
Olli Etuaho19515012017-06-26 18:00:17 +0300623Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400624{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000625 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400626 ASSERT(!type.getStruct());
627
Jamie Madilla2fbb842014-09-03 09:40:47 -0400628 Attribute attribute;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200629 setCommonVariableProperties(type, variable.variable(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400630
Olli Etuahoa55102c2017-02-24 12:36:50 +0000631 attribute.location = type.getLayoutQualifier().location;
632 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400633}
634
Olli Etuaho19515012017-06-26 18:00:17 +0300635OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400636{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000637 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400638 ASSERT(!type.getStruct());
639
Olli Etuahoa55102c2017-02-24 12:36:50 +0000640 OutputVariable outputVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200641 setCommonVariableProperties(type, variable.variable(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400642
Olli Etuahoa55102c2017-02-24 12:36:50 +0000643 outputVariable.location = type.getLayoutQualifier().location;
644 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400645}
646
Olli Etuaho19515012017-06-26 18:00:17 +0300647Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400648{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000649 const TType &type = variable.getType();
650
651 Varying varying;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200652 setCommonVariableProperties(type, variable.variable(), &varying);
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800653 varying.location = type.getLayoutQualifier().location;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000654
655 switch (type.getQualifier())
656 {
657 case EvqVaryingIn:
658 case EvqVaryingOut:
659 case EvqVertexOut:
660 case EvqSmoothOut:
661 case EvqFlatOut:
662 case EvqCentroidOut:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800663 case EvqGeometryOut:
Olli Etuahodefe3932018-02-13 11:56:09 +0200664 if (mSymbolTable->isVaryingInvariant(variable.getName()) || type.isInvariant())
Olli Etuahoa55102c2017-02-24 12:36:50 +0000665 {
666 varying.isInvariant = true;
667 }
668 break;
669 default:
670 break;
671 }
672
673 varying.interpolation = GetInterpolationType(type.getQualifier());
674 return varying;
675}
676
Jiawei Shaobd924af2017-11-16 15:28:04 +0800677// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200678void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200679 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800680 InterfaceBlock *interfaceBlock) const
Olli Etuahoa55102c2017-02-24 12:36:50 +0000681{
Jiawei Shaod8105a02017-08-08 09:54:36 +0800682 ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
683 ASSERT(interfaceBlock);
684
685 const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400686 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400687
Olli Etuahofbb1c792018-01-19 16:26:59 +0200688 interfaceBlock->name = blockType->name().data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200689 interfaceBlock->mappedName = getMappedName(blockType);
690 if (instanceName != nullptr)
691 {
692 interfaceBlock->instanceName = instanceName;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200693 const TSymbol *blockSymbol = nullptr;
694 if (strncmp(instanceName, "gl_in", 5u) == 0)
695 {
696 blockSymbol = mSymbolTable->getGlInVariableWithArraySize();
697 }
698 else
699 {
700 blockSymbol = mSymbolTable->findGlobal(ImmutableString(instanceName));
701 }
702 ASSERT(blockSymbol && blockSymbol->isVariable());
703 interfaceBlock->staticUse =
704 mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(blockSymbol));
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200705 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300706 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
707 interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800708
709 interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
710 if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
711 interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
712 {
Olli Etuaho3de27032017-11-30 12:16:47 +0200713 // TODO(oetuaho): Remove setting isRowMajorLayout.
714 interfaceBlock->isRowMajorLayout = false;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800715 interfaceBlock->binding = blockType->blockBinding();
716 interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
717 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400718
Jamie Madilla6f267f2014-08-27 11:44:15 -0400719 // Gather field information
Olli Etuaho94bbed12018-03-20 14:44:53 +0200720 bool anyFieldStaticallyUsed = false;
Jamie Madill39046162016-02-08 15:05:17 -0500721 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400722 {
Jamie Madill39046162016-02-08 15:05:17 -0500723 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400724
Olli Etuaho94bbed12018-03-20 14:44:53 +0200725 bool staticUse = false;
726 if (instanceName == nullptr)
727 {
728 // Static use of individual fields has been recorded, since they are present in the
729 // symbol table as variables.
730 const TSymbol *fieldSymbol = mSymbolTable->findGlobal(field->name());
731 ASSERT(fieldSymbol && fieldSymbol->isVariable());
732 staticUse =
733 mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(fieldSymbol));
734 if (staticUse)
735 {
736 anyFieldStaticallyUsed = true;
737 }
738 }
739
Olli Etuahoa55102c2017-02-24 12:36:50 +0000740 InterfaceBlockField fieldVariable;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200741 setFieldProperties(fieldType, field->name(), staticUse, &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000742 fieldVariable.isRowMajorLayout =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500743 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800744 interfaceBlock->fields.push_back(fieldVariable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400745 }
Olli Etuaho94bbed12018-03-20 14:44:53 +0200746 if (anyFieldStaticallyUsed)
747 {
748 interfaceBlock->staticUse = true;
749 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400750}
751
Olli Etuaho19515012017-06-26 18:00:17 +0300752Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400753{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000754 Uniform uniform;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200755 setCommonVariableProperties(variable.getType(), variable.variable(), &uniform);
Olli Etuaho78ed6cd2017-08-09 16:19:00 +0300756 uniform.binding = variable.getType().getLayoutQualifier().binding;
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000757 uniform.location = variable.getType().getLayoutQualifier().location;
jchen104cdac9e2017-05-08 11:01:20 +0800758 uniform.offset = variable.getType().getLayoutQualifier().offset;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800759 uniform.readonly = variable.getType().getMemoryQualifier().readonly;
760 uniform.writeonly = variable.getType().getMemoryQualifier().writeonly;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000761 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000762}
763
Olli Etuaho19515012017-06-26 18:00:17 +0300764bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000765{
Olli Etuaho13389b62016-10-16 11:48:18 +0100766 const TIntermSequence &sequence = *(node->getSequence());
767 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000768
Olli Etuaho13389b62016-10-16 11:48:18 +0100769 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
770 TQualifier qualifier = typedNode.getQualifier();
771
Olli Etuahoa55102c2017-02-24 12:36:50 +0000772 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
773 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
774 IsVarying(qualifier);
775
776 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000777 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000778 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100779 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000780
781 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100782 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000783 // The only case in which the sequence will not contain a TIntermSymbol node is
784 // initialization. It will contain a TInterBinary node in that case. Since attributes,
785 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
786 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
787 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200788 if (variable.variable().symbolType() == SymbolType::AngleInternal)
Olli Etuaho34d20072017-07-18 20:07:18 +0300789 {
790 // Internal variables are not collected.
791 continue;
792 }
793
Jiawei Shaobd924af2017-11-16 15:28:04 +0800794 // TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuahoa55102c2017-02-24 12:36:50 +0000795 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000796 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800797 InterfaceBlock interfaceBlock;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200798 recordInterfaceBlock(variable.variable().symbolType() != SymbolType::Empty
Olli Etuahofbb1c792018-01-19 16:26:59 +0200799 ? variable.getName().data()
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200800 : nullptr,
801 variable.getType(), &interfaceBlock);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800802
803 switch (qualifier)
Jiajia Qinbc585152017-06-23 15:42:17 +0800804 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800805 case EvqUniform:
806 mUniformBlocks->push_back(interfaceBlock);
807 break;
808 case EvqBuffer:
809 mShaderStorageBlocks->push_back(interfaceBlock);
810 break;
811 default:
812 UNREACHABLE();
Jiajia Qinbc585152017-06-23 15:42:17 +0800813 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000814 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000815 else
816 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200817 ASSERT(variable.variable().symbolType() != SymbolType::Empty);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000818 switch (qualifier)
819 {
820 case EvqAttribute:
821 case EvqVertexIn:
822 mAttribs->push_back(recordAttribute(variable));
823 break;
824 case EvqFragmentOut:
825 mOutputVariables->push_back(recordOutputVariable(variable));
826 break;
827 case EvqUniform:
828 mUniforms->push_back(recordUniform(variable));
829 break;
830 default:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800831 if (IsVaryingIn(qualifier))
832 {
833 mInputVaryings->push_back(recordVarying(variable));
834 }
835 else
836 {
837 ASSERT(IsVaryingOut(qualifier));
838 mOutputVaryings->push_back(recordVarying(variable));
839 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000840 break;
841 }
842 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000843 }
844
Olli Etuahoa55102c2017-02-24 12:36:50 +0000845 // None of the recorded variables can have initializers, so we don't need to traverse the
846 // declarators.
847 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000848}
Jamie Madill23a8a432014-07-09 13:27:42 -0400849
Jiawei Shaod8105a02017-08-08 09:54:36 +0800850// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
Jiawei Shaobd924af2017-11-16 15:28:04 +0800851// GL_EXT_shader_io_blocks.
Olli Etuahofbb1c792018-01-19 16:26:59 +0200852InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(
853 const ImmutableString &blockName) const
Jiawei Shaod8105a02017-08-08 09:54:36 +0800854{
855 InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
856 if (!namedBlock)
857 {
858 namedBlock = FindVariable(blockName, mShaderStorageBlocks);
859 }
860 return namedBlock;
861}
862
Olli Etuaho19515012017-06-26 18:00:17 +0300863bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
Jamie Madillb547ddf2014-08-25 16:20:46 -0400864{
865 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
866 {
Olli Etuaho94bbed12018-03-20 14:44:53 +0200867 // NOTE: we do not determine static use / activeness for individual blocks of an array.
Jamie Madilla6f267f2014-08-27 11:44:15 -0400868 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
869 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400870
871 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
872 ASSERT(constantUnion);
873
Jiawei Shaod8105a02017-08-08 09:54:36 +0800874 InterfaceBlock *namedBlock = nullptr;
875
876 bool traverseIndexExpression = false;
877 TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
878 if (interfaceIndexingNode)
879 {
880 TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
881 ASSERT(interfaceNode);
882
883 const TType &interfaceType = interfaceNode->getType();
884 if (interfaceType.getQualifier() == EvqPerVertexIn)
885 {
886 namedBlock = recordGLInUsed(interfaceType);
887 ASSERT(namedBlock);
888
889 // We need to continue traversing to collect useful variables in the index
890 // expression of gl_in.
891 traverseIndexExpression = true;
892 }
893 }
894
Jamie Madilla6f267f2014-08-27 11:44:15 -0400895 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800896 if (!namedBlock)
Jiajia Qinbc585152017-06-23 15:42:17 +0800897 {
Olli Etuahobed35d72017-12-20 16:36:26 +0200898 namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
Jiajia Qinbc585152017-06-23 15:42:17 +0800899 }
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800900 ASSERT(namedBlock);
Olli Etuaho94bbed12018-03-20 14:44:53 +0200901 ASSERT(namedBlock->staticUse);
Olli Etuaho107c7242018-03-20 15:45:35 +0200902 namedBlock->active = true;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800903 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
904 ASSERT(fieldIndex < namedBlock->fields.size());
Olli Etuaho94bbed12018-03-20 14:44:53 +0200905 // TODO(oetuaho): Would be nicer to record static use of fields of named interface blocks
906 // more accurately at parse time - now we only mark the fields statically used if they are
907 // active. http://anglebug.com/2440
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800908 namedBlock->fields[fieldIndex].staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200909 namedBlock->fields[fieldIndex].active = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800910
911 if (traverseIndexExpression)
912 {
913 ASSERT(interfaceIndexingNode);
914 interfaceIndexingNode->getRight()->traverse(this);
915 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400916 return false;
917 }
918
919 return true;
920}
921
Olli Etuaho19515012017-06-26 18:00:17 +0300922} // anonymous namespace
923
924void CollectVariables(TIntermBlock *root,
925 std::vector<Attribute> *attributes,
926 std::vector<OutputVariable> *outputVariables,
927 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800928 std::vector<Varying> *inputVaryings,
929 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800930 std::vector<InterfaceBlock> *uniformBlocks,
931 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800932 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300933 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300934 TSymbolTable *symbolTable,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800935 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300936 const TExtensionBehavior &extensionBehavior)
937{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800938 CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800939 outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
Olli Etuaho822a84b2018-03-23 12:30:18 +0200940 hashFunction, symbolTable, shaderType, extensionBehavior);
Olli Etuaho19515012017-06-26 18:00:17 +0300941 root->traverse(&collect);
942}
943
Olli Etuaho19515012017-06-26 18:00:17 +0300944} // namespace sh