blob: 30294dc8922b0aa0aa1f4113f5fea2aae847e86a [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 Etuaho06a06f52017-07-12 12:22:15 +030071// Note that this shouldn't be called for interface blocks - static use information is collected for
72// individual fields in case of interface blocks.
73void MarkStaticallyUsed(ShaderVariable *variable)
74{
75 if (!variable->staticUse)
76 {
77 if (variable->isStruct())
78 {
79 // Conservatively assume all fields are statically used as well.
80 for (auto &field : variable->fields)
81 {
82 MarkStaticallyUsed(&field);
83 }
84 }
85 variable->staticUse = true;
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 Etuaho8b5e8fd2017-12-15 14:59:15 +0200129 void setFieldOrVariableProperties(const TType &type, ShaderVariable *variableOut) const;
130 void setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200131 const ImmutableString &name,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200132 ShaderVariable *variableOut) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300133 void setCommonVariableProperties(const TType &type,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200134 const TVariable &variable,
Olli Etuaho19515012017-06-26 18:00:17 +0300135 ShaderVariable *variableOut) const;
136
137 Attribute recordAttribute(const TIntermSymbol &variable) const;
138 OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
139 Varying recordVarying(const TIntermSymbol &variable) const;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200140 void recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200141 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800142 InterfaceBlock *interfaceBlock) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300143 Uniform recordUniform(const TIntermSymbol &variable) const;
144
Olli Etuaho822a84b2018-03-23 12:30:18 +0200145 void setBuiltInInfoFromSymbol(const TVariable &variable, ShaderVariable *info);
Olli Etuaho19515012017-06-26 18:00:17 +0300146
Olli Etuaho822a84b2018-03-23 12:30:18 +0200147 void recordBuiltInVaryingUsed(const TVariable &variable,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800148 bool *addedFlag,
149 std::vector<Varying> *varyings);
Olli Etuaho822a84b2018-03-23 12:30:18 +0200150 void recordBuiltInFragmentOutputUsed(const TVariable &variable, bool *addedFlag);
151 void recordBuiltInAttributeUsed(const TVariable &variable, bool *addedFlag);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800152 InterfaceBlock *recordGLInUsed(const TType &glInType);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200153 InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300154
155 std::vector<Attribute> *mAttribs;
156 std::vector<OutputVariable> *mOutputVariables;
157 std::vector<Uniform> *mUniforms;
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800158 std::vector<Varying> *mInputVaryings;
159 std::vector<Varying> *mOutputVaryings;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800160 std::vector<InterfaceBlock> *mUniformBlocks;
161 std::vector<InterfaceBlock> *mShaderStorageBlocks;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800162 std::vector<InterfaceBlock> *mInBlocks;
Olli Etuaho19515012017-06-26 18:00:17 +0300163
164 std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
165
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800166 // Shader uniforms
Olli Etuaho19515012017-06-26 18:00:17 +0300167 bool mDepthRangeAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800168
169 // Vertex Shader builtins
170 bool mInstanceIDAdded;
171 bool mVertexIDAdded;
172 bool mPointSizeAdded;
173
174 // Vertex Shader and Geometry Shader builtins
175 bool mPositionAdded;
176
177 // Fragment Shader builtins
Olli Etuaho19515012017-06-26 18:00:17 +0300178 bool mPointCoordAdded;
179 bool mFrontFacingAdded;
180 bool mFragCoordAdded;
Olli Etuaho19515012017-06-26 18:00:17 +0300181 bool mLastFragDataAdded;
182 bool mFragColorAdded;
183 bool mFragDataAdded;
184 bool mFragDepthEXTAdded;
185 bool mFragDepthAdded;
186 bool mSecondaryFragColorEXTAdded;
187 bool mSecondaryFragDataEXTAdded;
188
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800189 // Geometry Shader builtins
Jiawei Shaod8105a02017-08-08 09:54:36 +0800190 bool mPerVertexInAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800191 bool mPrimitiveIDInAdded;
192 bool mInvocationIDAdded;
193
194 // Geometry Shader and Fragment Shader builtins
195 bool mPrimitiveIDAdded;
196 bool mLayerAdded;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800197
Olli Etuaho19515012017-06-26 18:00:17 +0300198 ShHashFunction64 mHashFunction;
199
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800200 GLenum mShaderType;
Olli Etuaho19515012017-06-26 18:00:17 +0300201 const TExtensionBehavior &mExtensionBehavior;
202};
203
204CollectVariablesTraverser::CollectVariablesTraverser(
205 std::vector<sh::Attribute> *attribs,
206 std::vector<sh::OutputVariable> *outputVariables,
207 std::vector<sh::Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800208 std::vector<sh::Varying> *inputVaryings,
209 std::vector<sh::Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800210 std::vector<sh::InterfaceBlock> *uniformBlocks,
211 std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800212 std::vector<sh::InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300213 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300214 TSymbolTable *symbolTable,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800215 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300216 const TExtensionBehavior &extensionBehavior)
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300217 : TIntermTraverser(true, false, false, symbolTable),
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300218 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400219 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000220 mUniforms(uniforms),
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800221 mInputVaryings(inputVaryings),
222 mOutputVaryings(outputVaryings),
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800223 mUniformBlocks(uniformBlocks),
224 mShaderStorageBlocks(shaderStorageBlocks),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800225 mInBlocks(inBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400226 mDepthRangeAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800227 mInstanceIDAdded(false),
228 mVertexIDAdded(false),
229 mPointSizeAdded(false),
230 mPositionAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400231 mPointCoordAdded(false),
232 mFrontFacingAdded(false),
233 mFragCoordAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100234 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300235 mFragColorAdded(false),
236 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300237 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300238 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300239 mSecondaryFragColorEXTAdded(false),
240 mSecondaryFragDataEXTAdded(false),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800241 mPerVertexInAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800242 mPrimitiveIDInAdded(false),
243 mInvocationIDAdded(false),
244 mPrimitiveIDAdded(false),
245 mLayerAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700246 mHashFunction(hashFunction),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800247 mShaderType(shaderType),
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700248 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000249{
250}
251
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200252std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const
Olli Etuaho855d9642017-05-17 14:05:06 +0300253{
Olli Etuahofbb1c792018-01-19 16:26:59 +0200254 return HashName(symbol, mHashFunction, nullptr).data();
Olli Etuaho855d9642017-05-17 14:05:06 +0300255}
256
Olli Etuaho822a84b2018-03-23 12:30:18 +0200257void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable,
258 ShaderVariable *info)
Olli Etuaho19515012017-06-26 18:00:17 +0300259{
Olli Etuaho822a84b2018-03-23 12:30:18 +0200260 const TType &type = variable.getType();
Olli Etuaho19515012017-06-26 18:00:17 +0300261
Olli Etuaho822a84b2018-03-23 12:30:18 +0200262 info->name = variable.name().data();
263 info->mappedName = variable.name().data();
Olli Etuaho19515012017-06-26 18:00:17 +0300264 info->type = GLVariableType(type);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300265 info->precision = GLVariablePrecision(type);
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800266 if (auto *arraySizes = type.getArraySizes())
267 {
268 info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
269 }
Olli Etuaho19515012017-06-26 18:00:17 +0300270}
271
Olli Etuaho822a84b2018-03-23 12:30:18 +0200272void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800273 bool *addedFlag,
274 std::vector<Varying> *varyings)
Olli Etuaho19515012017-06-26 18:00:17 +0300275{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800276 ASSERT(varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300277 if (!(*addedFlag))
278 {
279 Varying info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200280 setBuiltInInfoFromSymbol(variable, &info);
Olli Etuaho19515012017-06-26 18:00:17 +0300281 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200282 info.active = true;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200283 info.isInvariant = mSymbolTable->isVaryingInvariant(variable.name());
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800284 varyings->push_back(info);
Olli Etuaho19515012017-06-26 18:00:17 +0300285 (*addedFlag) = true;
286 }
287}
288
Olli Etuaho822a84b2018-03-23 12:30:18 +0200289void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const TVariable &variable,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200290 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300291{
292 if (!(*addedFlag))
293 {
294 OutputVariable info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200295 setBuiltInInfoFromSymbol(variable, &info);
Olli Etuaho19515012017-06-26 18:00:17 +0300296 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200297 info.active = true;
Olli Etuaho19515012017-06-26 18:00:17 +0300298 mOutputVariables->push_back(info);
299 (*addedFlag) = true;
300 }
301}
302
Olli Etuaho822a84b2018-03-23 12:30:18 +0200303void CollectVariablesTraverser::recordBuiltInAttributeUsed(const TVariable &variable,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200304 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300305{
306 if (!(*addedFlag))
307 {
308 Attribute info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200309 setBuiltInInfoFromSymbol(variable, &info);
Olli Etuaho19515012017-06-26 18:00:17 +0300310 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200311 info.active = true;
Olli Etuaho19515012017-06-26 18:00:17 +0300312 info.location = -1;
313 mAttribs->push_back(info);
314 (*addedFlag) = true;
315 }
316}
317
Jiawei Shaod8105a02017-08-08 09:54:36 +0800318InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
319{
320 if (!mPerVertexInAdded)
321 {
322 ASSERT(glInType.getQualifier() == EvqPerVertexIn);
323 InterfaceBlock info;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200324 recordInterfaceBlock("gl_in", glInType, &info);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800325 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200326 info.active = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800327
328 mPerVertexInAdded = true;
329 mInBlocks->push_back(info);
330 return &mInBlocks->back();
331 }
332 else
333 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200334 return FindVariable(ImmutableString("gl_PerVertex"), mInBlocks);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800335 }
336}
337
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400338// We want to check whether a uniform/varying is statically used
339// because we only count the used ones in packing computing.
340// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
341// toward varying counting if they are statically used in a fragment
342// shader.
Olli Etuaho19515012017-06-26 18:00:17 +0300343void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000344{
Yunchao He4f285442017-04-21 12:15:49 +0800345 ASSERT(symbol != nullptr);
Olli Etuaho34d20072017-07-18 20:07:18 +0300346
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200347 if (symbol->variable().symbolType() == SymbolType::AngleInternal ||
348 symbol->variable().symbolType() == SymbolType::Empty)
Olli Etuaho34d20072017-07-18 20:07:18 +0300349 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200350 // Internal variables or nameless variables are not collected.
Olli Etuaho34d20072017-07-18 20:07:18 +0300351 return;
352 }
353
Yunchao Hed7297bf2017-04-19 15:27:10 +0800354 ShaderVariable *var = nullptr;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200355
Olli Etuahofbb1c792018-01-19 16:26:59 +0200356 const ImmutableString &symbolName = symbol->getName();
Jamie Madill4667c452014-07-08 15:02:36 -0400357
Olli Etuahob8cb9392017-12-20 14:23:19 +0200358 // Check the qualifier from the variable, not from the symbol node. The node may have a
359 // different qualifier if it's the result of a folded ternary node.
360 TQualifier qualifier = symbol->variable().getType().getQualifier();
361
362 if (IsVaryingIn(qualifier))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400363 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800364 var = FindVariable(symbolName, mInputVaryings);
365 }
Olli Etuahob8cb9392017-12-20 14:23:19 +0200366 else if (IsVaryingOut(qualifier))
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800367 {
368 var = FindVariable(symbolName, mOutputVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400369 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400370 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
371 {
372 UNREACHABLE();
373 }
Jamie Madill55def582015-05-04 11:24:57 -0400374 else if (symbolName == "gl_DepthRange")
375 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200376 ASSERT(qualifier == EvqUniform);
Jamie Madill55def582015-05-04 11:24:57 -0400377
378 if (!mDepthRangeAdded)
379 {
380 Uniform info;
381 const char kName[] = "gl_DepthRange";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500382 info.name = kName;
383 info.mappedName = kName;
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400384 info.type = GL_NONE;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500385 info.precision = GL_NONE;
386 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200387 info.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400388
Olli Etuahoe7c28572017-10-23 16:29:33 +0300389 ShaderVariable nearInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400390 const char kNearName[] = "near";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500391 nearInfo.name = kNearName;
392 nearInfo.mappedName = kNearName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500393 nearInfo.precision = GL_HIGH_FLOAT;
394 nearInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200395 nearInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400396
Olli Etuahoe7c28572017-10-23 16:29:33 +0300397 ShaderVariable farInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400398 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500399 farInfo.name = kFarName;
400 farInfo.mappedName = kFarName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500401 farInfo.precision = GL_HIGH_FLOAT;
402 farInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200403 farInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400404
Olli Etuahoe7c28572017-10-23 16:29:33 +0300405 ShaderVariable diffInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400406 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500407 diffInfo.name = kDiffName;
408 diffInfo.mappedName = kDiffName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500409 diffInfo.precision = GL_HIGH_FLOAT;
410 diffInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200411 diffInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400412
413 info.fields.push_back(nearInfo);
414 info.fields.push_back(farInfo);
415 info.fields.push_back(diffInfo);
416
417 mUniforms->push_back(info);
418 mDepthRangeAdded = true;
419 }
420 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400421 else
Jamie Madill4667c452014-07-08 15:02:36 -0400422 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200423 switch (qualifier)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400424 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500425 case EvqAttribute:
426 case EvqVertexIn:
427 var = FindVariable(symbolName, mAttribs);
428 break;
429 case EvqFragmentOut:
430 var = FindVariable(symbolName, mOutputVariables);
431 break;
432 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400433 {
434 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
435 if (interfaceBlock)
436 {
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800437 var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400438 }
439 else
440 {
441 var = FindVariable(symbolName, mUniforms);
442 }
443
444 // It's an internal error to reference an undefined user uniform
Olli Etuahofbb1c792018-01-19 16:26:59 +0200445 ASSERT(!symbolName.beginsWith("gl_") || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400446 }
Jamie Madill4667c452014-07-08 15:02:36 -0400447 break;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800448 case EvqBuffer:
449 {
450 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
451 var =
452 FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
453 }
454 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500455 case EvqFragCoord:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200456 recordBuiltInVaryingUsed(symbol->variable(), &mFragCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500457 return;
458 case EvqFrontFacing:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200459 recordBuiltInVaryingUsed(symbol->variable(), &mFrontFacingAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500460 return;
461 case EvqPointCoord:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200462 recordBuiltInVaryingUsed(symbol->variable(), &mPointCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500463 return;
464 case EvqInstanceID:
Martin Radev115fc552017-07-05 17:11:06 +0300465 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
466 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
Olli Etuaho822a84b2018-03-23 12:30:18 +0200467 // InstanceID. Note that gl_InstanceID is not added to the symbol table for ESSL1
468 // shaders.
469 recordBuiltInAttributeUsed(symbol->variable(), &mInstanceIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500470 return;
471 case EvqVertexID:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200472 recordBuiltInAttributeUsed(symbol->variable(), &mVertexIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500473 return;
474 case EvqPosition:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200475 recordBuiltInVaryingUsed(symbol->variable(), &mPositionAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500476 return;
477 case EvqPointSize:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200478 recordBuiltInVaryingUsed(symbol->variable(), &mPointSizeAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500479 return;
480 case EvqLastFragData:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200481 recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500482 return;
483 case EvqFragColor:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200484 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragColorAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500485 return;
486 case EvqFragData:
487 if (!mFragDataAdded)
488 {
489 OutputVariable info;
Olli Etuaho822a84b2018-03-23 12:30:18 +0200490 setBuiltInInfoFromSymbol(symbol->variable(), &info);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300491 if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500492 {
Olli Etuaho465835d2017-09-26 13:34:10 +0300493 ASSERT(info.arraySizes.size() == 1u);
494 info.arraySizes.back() = 1u;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500495 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500496 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200497 info.active = true;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500498 mOutputVariables->push_back(info);
499 mFragDataAdded = true;
500 }
501 return;
502 case EvqFragDepthEXT:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200503 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500504 return;
505 case EvqFragDepth:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200506 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500507 return;
508 case EvqSecondaryFragColorEXT:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200509 recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragColorEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500510 return;
511 case EvqSecondaryFragDataEXT:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200512 recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragDataEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500513 return;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800514 case EvqInvocationID:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200515 recordBuiltInVaryingUsed(symbol->variable(), &mInvocationIDAdded, mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800516 break;
517 case EvqPrimitiveIDIn:
Olli Etuaho822a84b2018-03-23 12:30:18 +0200518 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDInAdded, mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800519 break;
520 case EvqPrimitiveID:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800521 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800522 {
Olli Etuaho822a84b2018-03-23 12:30:18 +0200523 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200524 mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800525 }
526 else
527 {
528 ASSERT(mShaderType == GL_FRAGMENT_SHADER);
Olli Etuaho822a84b2018-03-23 12:30:18 +0200529 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200530 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800531 }
532 break;
533 case EvqLayer:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800534 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800535 {
Olli Etuaho822a84b2018-03-23 12:30:18 +0200536 recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800537 }
538 else if (mShaderType == GL_FRAGMENT_SHADER)
539 {
Olli Etuaho822a84b2018-03-23 12:30:18 +0200540 recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800541 }
542 else
543 {
544 ASSERT(mShaderType == GL_VERTEX_SHADER &&
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300545 IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800546 }
547 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500548 default:
549 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400550 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400551 }
552 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400553 {
Olli Etuaho06a06f52017-07-12 12:22:15 +0300554 MarkStaticallyUsed(var);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400555 }
556}
557
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200558void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
559 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400560{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000561 ASSERT(variableOut);
562
563 const TStructure *structure = type.getStruct();
Olli Etuahoa55102c2017-02-24 12:36:50 +0000564 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500565 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000566 variableOut->type = GLVariableType(type);
567 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500568 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000569 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400570 {
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400571 // Structures use a NONE type that isn't exposed outside ANGLE.
572 variableOut->type = GL_NONE;
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100573 if (structure->symbolType() != SymbolType::Empty)
574 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200575 variableOut->structName = structure->name().data();
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100576 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000577
578 const TFieldList &fields = structure->fields();
579
Olli Etuaho378c3a52017-12-04 11:32:13 +0200580 for (const TField *field : fields)
Olli Etuahoa55102c2017-02-24 12:36:50 +0000581 {
582 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
583 // ShaderVariable objects.
584 ShaderVariable fieldVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200585 setFieldProperties(*field->type(), field->name(), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000586 variableOut->fields.push_back(fieldVariable);
587 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400588 }
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800589 if (auto *arraySizes = type.getArraySizes())
590 {
591 variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
592 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000593}
Jamie Madill23a8a432014-07-09 13:27:42 -0400594
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200595void CollectVariablesTraverser::setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200596 const ImmutableString &name,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200597 ShaderVariable *variableOut) const
598{
599 ASSERT(variableOut);
600 setFieldOrVariableProperties(type, variableOut);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200601 variableOut->name.assign(name.data(), name.length());
602 variableOut->mappedName = HashName(name, mHashFunction, nullptr).data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200603}
604
605void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
606 const TVariable &variable,
607 ShaderVariable *variableOut) const
608{
609 ASSERT(variableOut);
610
611 setFieldOrVariableProperties(type, variableOut);
612 ASSERT(variable.symbolType() != SymbolType::Empty);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200613 variableOut->name.assign(variable.name().data(), variable.name().length());
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200614 variableOut->mappedName = getMappedName(&variable);
615}
616
Olli Etuaho19515012017-06-26 18:00:17 +0300617Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400618{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000619 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400620 ASSERT(!type.getStruct());
621
Jamie Madilla2fbb842014-09-03 09:40:47 -0400622 Attribute attribute;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200623 setCommonVariableProperties(type, variable.variable(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400624
Olli Etuahoa55102c2017-02-24 12:36:50 +0000625 attribute.location = type.getLayoutQualifier().location;
626 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400627}
628
Olli Etuaho19515012017-06-26 18:00:17 +0300629OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400630{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000631 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400632 ASSERT(!type.getStruct());
633
Olli Etuahoa55102c2017-02-24 12:36:50 +0000634 OutputVariable outputVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200635 setCommonVariableProperties(type, variable.variable(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400636
Olli Etuahoa55102c2017-02-24 12:36:50 +0000637 outputVariable.location = type.getLayoutQualifier().location;
638 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400639}
640
Olli Etuaho19515012017-06-26 18:00:17 +0300641Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400642{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000643 const TType &type = variable.getType();
644
645 Varying varying;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200646 setCommonVariableProperties(type, variable.variable(), &varying);
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800647 varying.location = type.getLayoutQualifier().location;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000648
649 switch (type.getQualifier())
650 {
651 case EvqVaryingIn:
652 case EvqVaryingOut:
653 case EvqVertexOut:
654 case EvqSmoothOut:
655 case EvqFlatOut:
656 case EvqCentroidOut:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800657 case EvqGeometryOut:
Olli Etuahodefe3932018-02-13 11:56:09 +0200658 if (mSymbolTable->isVaryingInvariant(variable.getName()) || type.isInvariant())
Olli Etuahoa55102c2017-02-24 12:36:50 +0000659 {
660 varying.isInvariant = true;
661 }
662 break;
663 default:
664 break;
665 }
666
667 varying.interpolation = GetInterpolationType(type.getQualifier());
668 return varying;
669}
670
Jiawei Shaobd924af2017-11-16 15:28:04 +0800671// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200672void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200673 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800674 InterfaceBlock *interfaceBlock) const
Olli Etuahoa55102c2017-02-24 12:36:50 +0000675{
Jiawei Shaod8105a02017-08-08 09:54:36 +0800676 ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
677 ASSERT(interfaceBlock);
678
679 const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400680 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400681
Olli Etuahofbb1c792018-01-19 16:26:59 +0200682 interfaceBlock->name = blockType->name().data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200683 interfaceBlock->mappedName = getMappedName(blockType);
684 if (instanceName != nullptr)
685 {
686 interfaceBlock->instanceName = instanceName;
687 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300688 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
689 interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800690
691 interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
692 if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
693 interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
694 {
Olli Etuaho3de27032017-11-30 12:16:47 +0200695 // TODO(oetuaho): Remove setting isRowMajorLayout.
696 interfaceBlock->isRowMajorLayout = false;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800697 interfaceBlock->binding = blockType->blockBinding();
698 interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
699 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400700
Jamie Madilla6f267f2014-08-27 11:44:15 -0400701 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500702 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400703 {
Jamie Madill39046162016-02-08 15:05:17 -0500704 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400705
Olli Etuahoa55102c2017-02-24 12:36:50 +0000706 InterfaceBlockField fieldVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200707 setFieldProperties(fieldType, field->name(), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000708 fieldVariable.isRowMajorLayout =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500709 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800710 interfaceBlock->fields.push_back(fieldVariable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400711 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400712}
713
Olli Etuaho19515012017-06-26 18:00:17 +0300714Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400715{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000716 Uniform uniform;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200717 setCommonVariableProperties(variable.getType(), variable.variable(), &uniform);
Olli Etuaho78ed6cd2017-08-09 16:19:00 +0300718 uniform.binding = variable.getType().getLayoutQualifier().binding;
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000719 uniform.location = variable.getType().getLayoutQualifier().location;
jchen104cdac9e2017-05-08 11:01:20 +0800720 uniform.offset = variable.getType().getLayoutQualifier().offset;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800721 uniform.readonly = variable.getType().getMemoryQualifier().readonly;
722 uniform.writeonly = variable.getType().getMemoryQualifier().writeonly;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000723 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000724}
725
Olli Etuaho19515012017-06-26 18:00:17 +0300726bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000727{
Olli Etuaho13389b62016-10-16 11:48:18 +0100728 const TIntermSequence &sequence = *(node->getSequence());
729 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000730
Olli Etuaho13389b62016-10-16 11:48:18 +0100731 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
732 TQualifier qualifier = typedNode.getQualifier();
733
Olli Etuahoa55102c2017-02-24 12:36:50 +0000734 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
735 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
736 IsVarying(qualifier);
737
738 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000739 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000740 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100741 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000742
743 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100744 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000745 // The only case in which the sequence will not contain a TIntermSymbol node is
746 // initialization. It will contain a TInterBinary node in that case. Since attributes,
747 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
748 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
749 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200750 if (variable.variable().symbolType() == SymbolType::AngleInternal)
Olli Etuaho34d20072017-07-18 20:07:18 +0300751 {
752 // Internal variables are not collected.
753 continue;
754 }
755
Jiawei Shaobd924af2017-11-16 15:28:04 +0800756 // TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuahoa55102c2017-02-24 12:36:50 +0000757 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000758 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800759 InterfaceBlock interfaceBlock;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200760 recordInterfaceBlock(variable.variable().symbolType() != SymbolType::Empty
Olli Etuahofbb1c792018-01-19 16:26:59 +0200761 ? variable.getName().data()
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200762 : nullptr,
763 variable.getType(), &interfaceBlock);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800764
765 switch (qualifier)
Jiajia Qinbc585152017-06-23 15:42:17 +0800766 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800767 case EvqUniform:
768 mUniformBlocks->push_back(interfaceBlock);
769 break;
770 case EvqBuffer:
771 mShaderStorageBlocks->push_back(interfaceBlock);
772 break;
773 default:
774 UNREACHABLE();
Jiajia Qinbc585152017-06-23 15:42:17 +0800775 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000776 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000777 else
778 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200779 ASSERT(variable.variable().symbolType() != SymbolType::Empty);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000780 switch (qualifier)
781 {
782 case EvqAttribute:
783 case EvqVertexIn:
784 mAttribs->push_back(recordAttribute(variable));
785 break;
786 case EvqFragmentOut:
787 mOutputVariables->push_back(recordOutputVariable(variable));
788 break;
789 case EvqUniform:
790 mUniforms->push_back(recordUniform(variable));
791 break;
792 default:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800793 if (IsVaryingIn(qualifier))
794 {
795 mInputVaryings->push_back(recordVarying(variable));
796 }
797 else
798 {
799 ASSERT(IsVaryingOut(qualifier));
800 mOutputVaryings->push_back(recordVarying(variable));
801 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000802 break;
803 }
804 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000805 }
806
Olli Etuahoa55102c2017-02-24 12:36:50 +0000807 // None of the recorded variables can have initializers, so we don't need to traverse the
808 // declarators.
809 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000810}
Jamie Madill23a8a432014-07-09 13:27:42 -0400811
Jiawei Shaod8105a02017-08-08 09:54:36 +0800812// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
Jiawei Shaobd924af2017-11-16 15:28:04 +0800813// GL_EXT_shader_io_blocks.
Olli Etuahofbb1c792018-01-19 16:26:59 +0200814InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(
815 const ImmutableString &blockName) const
Jiawei Shaod8105a02017-08-08 09:54:36 +0800816{
817 InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
818 if (!namedBlock)
819 {
820 namedBlock = FindVariable(blockName, mShaderStorageBlocks);
821 }
822 return namedBlock;
823}
824
Olli Etuaho19515012017-06-26 18:00:17 +0300825bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
Jamie Madillb547ddf2014-08-25 16:20:46 -0400826{
827 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
828 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400829 // NOTE: we do not determine static use for individual blocks of an array
830 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
831 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400832
833 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
834 ASSERT(constantUnion);
835
Jiawei Shaod8105a02017-08-08 09:54:36 +0800836 InterfaceBlock *namedBlock = nullptr;
837
838 bool traverseIndexExpression = false;
839 TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
840 if (interfaceIndexingNode)
841 {
842 TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
843 ASSERT(interfaceNode);
844
845 const TType &interfaceType = interfaceNode->getType();
846 if (interfaceType.getQualifier() == EvqPerVertexIn)
847 {
848 namedBlock = recordGLInUsed(interfaceType);
849 ASSERT(namedBlock);
850
851 // We need to continue traversing to collect useful variables in the index
852 // expression of gl_in.
853 traverseIndexExpression = true;
854 }
855 }
856
Jamie Madilla6f267f2014-08-27 11:44:15 -0400857 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800858 if (!namedBlock)
Jiajia Qinbc585152017-06-23 15:42:17 +0800859 {
Olli Etuahobed35d72017-12-20 16:36:26 +0200860 namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
Jiajia Qinbc585152017-06-23 15:42:17 +0800861 }
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800862 ASSERT(namedBlock);
863 namedBlock->staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200864 namedBlock->active = true;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800865 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
866 ASSERT(fieldIndex < namedBlock->fields.size());
867 namedBlock->fields[fieldIndex].staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200868 namedBlock->fields[fieldIndex].active = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800869
870 if (traverseIndexExpression)
871 {
872 ASSERT(interfaceIndexingNode);
873 interfaceIndexingNode->getRight()->traverse(this);
874 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400875 return false;
876 }
877
878 return true;
879}
880
Olli Etuaho19515012017-06-26 18:00:17 +0300881} // anonymous namespace
882
883void CollectVariables(TIntermBlock *root,
884 std::vector<Attribute> *attributes,
885 std::vector<OutputVariable> *outputVariables,
886 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800887 std::vector<Varying> *inputVaryings,
888 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800889 std::vector<InterfaceBlock> *uniformBlocks,
890 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800891 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300892 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300893 TSymbolTable *symbolTable,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800894 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300895 const TExtensionBehavior &extensionBehavior)
896{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800897 CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800898 outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
Olli Etuaho822a84b2018-03-23 12:30:18 +0200899 hashFunction, symbolTable, shaderType, extensionBehavior);
Olli Etuaho19515012017-06-26 18:00:17 +0300900 root->traverse(&collect);
901}
902
Olli Etuaho19515012017-06-26 18:00:17 +0300903} // namespace sh