blob: 7aaf6531c53f1762650d571f2bc221344562acc1 [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,
Olli Etuaho19515012017-06-26 18:00:17 +0300119 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800120 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300121 const TExtensionBehavior &extensionBehavior);
122
123 void visitSymbol(TIntermSymbol *symbol) override;
124 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
125 bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
126
127 private:
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200128 std::string getMappedName(const TSymbol *symbol) const;
Olli Etuaho855d9642017-05-17 14:05:06 +0300129
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200130 void setFieldOrVariableProperties(const TType &type, ShaderVariable *variableOut) const;
131 void setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200132 const ImmutableString &name,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200133 ShaderVariable *variableOut) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300134 void setCommonVariableProperties(const TType &type,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200135 const TVariable &variable,
Olli Etuaho19515012017-06-26 18:00:17 +0300136 ShaderVariable *variableOut) const;
137
138 Attribute recordAttribute(const TIntermSymbol &variable) const;
139 OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
140 Varying recordVarying(const TIntermSymbol &variable) const;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200141 void recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200142 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800143 InterfaceBlock *interfaceBlock) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300144 Uniform recordUniform(const TIntermSymbol &variable) const;
145
Olli Etuahofbb1c792018-01-19 16:26:59 +0200146 void setBuiltInInfoFromSymbolTable(const ImmutableString &name, ShaderVariable *info);
Olli Etuaho19515012017-06-26 18:00:17 +0300147
Olli Etuahofbb1c792018-01-19 16:26:59 +0200148 void recordBuiltInVaryingUsed(const ImmutableString &name,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800149 bool *addedFlag,
150 std::vector<Varying> *varyings);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200151 void recordBuiltInFragmentOutputUsed(const ImmutableString &name, bool *addedFlag);
152 void recordBuiltInAttributeUsed(const ImmutableString &name, bool *addedFlag);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800153 InterfaceBlock *recordGLInUsed(const TType &glInType);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200154 InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300155
156 std::vector<Attribute> *mAttribs;
157 std::vector<OutputVariable> *mOutputVariables;
158 std::vector<Uniform> *mUniforms;
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800159 std::vector<Varying> *mInputVaryings;
160 std::vector<Varying> *mOutputVaryings;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800161 std::vector<InterfaceBlock> *mUniformBlocks;
162 std::vector<InterfaceBlock> *mShaderStorageBlocks;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800163 std::vector<InterfaceBlock> *mInBlocks;
Olli Etuaho19515012017-06-26 18:00:17 +0300164
165 std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
166
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800167 // Shader uniforms
Olli Etuaho19515012017-06-26 18:00:17 +0300168 bool mDepthRangeAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800169
170 // Vertex Shader builtins
171 bool mInstanceIDAdded;
172 bool mVertexIDAdded;
173 bool mPointSizeAdded;
174
175 // Vertex Shader and Geometry Shader builtins
176 bool mPositionAdded;
177
178 // Fragment Shader builtins
Olli Etuaho19515012017-06-26 18:00:17 +0300179 bool mPointCoordAdded;
180 bool mFrontFacingAdded;
181 bool mFragCoordAdded;
Olli Etuaho19515012017-06-26 18:00:17 +0300182 bool mLastFragDataAdded;
183 bool mFragColorAdded;
184 bool mFragDataAdded;
185 bool mFragDepthEXTAdded;
186 bool mFragDepthAdded;
187 bool mSecondaryFragColorEXTAdded;
188 bool mSecondaryFragDataEXTAdded;
189
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800190 // Geometry Shader builtins
Jiawei Shaod8105a02017-08-08 09:54:36 +0800191 bool mPerVertexInAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800192 bool mPrimitiveIDInAdded;
193 bool mInvocationIDAdded;
194
195 // Geometry Shader and Fragment Shader builtins
196 bool mPrimitiveIDAdded;
197 bool mLayerAdded;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800198
Olli Etuaho19515012017-06-26 18:00:17 +0300199 ShHashFunction64 mHashFunction;
200
Olli Etuaho19515012017-06-26 18:00:17 +0300201 int mShaderVersion;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800202 GLenum mShaderType;
Olli Etuaho19515012017-06-26 18:00:17 +0300203 const TExtensionBehavior &mExtensionBehavior;
204};
205
206CollectVariablesTraverser::CollectVariablesTraverser(
207 std::vector<sh::Attribute> *attribs,
208 std::vector<sh::OutputVariable> *outputVariables,
209 std::vector<sh::Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800210 std::vector<sh::Varying> *inputVaryings,
211 std::vector<sh::Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800212 std::vector<sh::InterfaceBlock> *uniformBlocks,
213 std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800214 std::vector<sh::InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300215 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300216 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300217 int shaderVersion,
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),
Olli Etuaho19515012017-06-26 18:00:17 +0300250 mShaderVersion(shaderVersion),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800251 mShaderType(shaderType),
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700252 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000253{
254}
255
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200256std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const
Olli Etuaho855d9642017-05-17 14:05:06 +0300257{
Olli Etuahofbb1c792018-01-19 16:26:59 +0200258 return HashName(symbol, mHashFunction, nullptr).data();
Olli Etuaho855d9642017-05-17 14:05:06 +0300259}
260
Olli Etuahofbb1c792018-01-19 16:26:59 +0200261void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const ImmutableString &name,
Olli Etuaho19515012017-06-26 18:00:17 +0300262 ShaderVariable *info)
263{
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200264 const TVariable *symbolTableVar =
265 reinterpret_cast<const TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
Olli Etuaho19515012017-06-26 18:00:17 +0300266 ASSERT(symbolTableVar);
267 const TType &type = symbolTableVar->getType();
268
Olli Etuahofbb1c792018-01-19 16:26:59 +0200269 info->name = name.data();
270 info->mappedName = name.data();
Olli Etuaho19515012017-06-26 18:00:17 +0300271 info->type = GLVariableType(type);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300272 info->precision = GLVariablePrecision(type);
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800273 if (auto *arraySizes = type.getArraySizes())
274 {
275 info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
276 }
Olli Etuaho19515012017-06-26 18:00:17 +0300277}
278
Olli Etuahofbb1c792018-01-19 16:26:59 +0200279void CollectVariablesTraverser::recordBuiltInVaryingUsed(const ImmutableString &name,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800280 bool *addedFlag,
281 std::vector<Varying> *varyings)
Olli Etuaho19515012017-06-26 18:00:17 +0300282{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800283 ASSERT(varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300284 if (!(*addedFlag))
285 {
286 Varying info;
287 setBuiltInInfoFromSymbolTable(name, &info);
288 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200289 info.active = true;
Olli Etuahodefe3932018-02-13 11:56:09 +0200290 info.isInvariant = mSymbolTable->isVaryingInvariant(name);
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800291 varyings->push_back(info);
Olli Etuaho19515012017-06-26 18:00:17 +0300292 (*addedFlag) = true;
293 }
294}
295
Olli Etuahofbb1c792018-01-19 16:26:59 +0200296void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const ImmutableString &name,
297 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300298{
299 if (!(*addedFlag))
300 {
301 OutputVariable info;
302 setBuiltInInfoFromSymbolTable(name, &info);
303 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200304 info.active = true;
Olli Etuaho19515012017-06-26 18:00:17 +0300305 mOutputVariables->push_back(info);
306 (*addedFlag) = true;
307 }
308}
309
Olli Etuahofbb1c792018-01-19 16:26:59 +0200310void CollectVariablesTraverser::recordBuiltInAttributeUsed(const ImmutableString &name,
311 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300312{
313 if (!(*addedFlag))
314 {
315 Attribute info;
316 setBuiltInInfoFromSymbolTable(name, &info);
317 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200318 info.active = true;
Olli Etuaho19515012017-06-26 18:00:17 +0300319 info.location = -1;
320 mAttribs->push_back(info);
321 (*addedFlag) = true;
322 }
323}
324
Jiawei Shaod8105a02017-08-08 09:54:36 +0800325InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
326{
327 if (!mPerVertexInAdded)
328 {
329 ASSERT(glInType.getQualifier() == EvqPerVertexIn);
330 InterfaceBlock info;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200331 recordInterfaceBlock("gl_in", glInType, &info);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800332 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200333 info.active = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800334
335 mPerVertexInAdded = true;
336 mInBlocks->push_back(info);
337 return &mInBlocks->back();
338 }
339 else
340 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200341 return FindVariable(ImmutableString("gl_PerVertex"), mInBlocks);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800342 }
343}
344
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400345// We want to check whether a uniform/varying is statically used
346// because we only count the used ones in packing computing.
347// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
348// toward varying counting if they are statically used in a fragment
349// shader.
Olli Etuaho19515012017-06-26 18:00:17 +0300350void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000351{
Yunchao He4f285442017-04-21 12:15:49 +0800352 ASSERT(symbol != nullptr);
Olli Etuaho34d20072017-07-18 20:07:18 +0300353
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200354 if (symbol->variable().symbolType() == SymbolType::AngleInternal ||
355 symbol->variable().symbolType() == SymbolType::Empty)
Olli Etuaho34d20072017-07-18 20:07:18 +0300356 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200357 // Internal variables or nameless variables are not collected.
Olli Etuaho34d20072017-07-18 20:07:18 +0300358 return;
359 }
360
Yunchao Hed7297bf2017-04-19 15:27:10 +0800361 ShaderVariable *var = nullptr;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200362
Olli Etuahofbb1c792018-01-19 16:26:59 +0200363 const ImmutableString &symbolName = symbol->getName();
Jamie Madill4667c452014-07-08 15:02:36 -0400364
Olli Etuahob8cb9392017-12-20 14:23:19 +0200365 // Check the qualifier from the variable, not from the symbol node. The node may have a
366 // different qualifier if it's the result of a folded ternary node.
367 TQualifier qualifier = symbol->variable().getType().getQualifier();
368
369 if (IsVaryingIn(qualifier))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400370 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800371 var = FindVariable(symbolName, mInputVaryings);
372 }
Olli Etuahob8cb9392017-12-20 14:23:19 +0200373 else if (IsVaryingOut(qualifier))
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800374 {
375 var = FindVariable(symbolName, mOutputVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400376 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400377 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
378 {
379 UNREACHABLE();
380 }
Jamie Madill55def582015-05-04 11:24:57 -0400381 else if (symbolName == "gl_DepthRange")
382 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200383 ASSERT(qualifier == EvqUniform);
Jamie Madill55def582015-05-04 11:24:57 -0400384
385 if (!mDepthRangeAdded)
386 {
387 Uniform info;
388 const char kName[] = "gl_DepthRange";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500389 info.name = kName;
390 info.mappedName = kName;
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400391 info.type = GL_NONE;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500392 info.precision = GL_NONE;
393 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200394 info.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400395
Olli Etuahoe7c28572017-10-23 16:29:33 +0300396 ShaderVariable nearInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400397 const char kNearName[] = "near";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500398 nearInfo.name = kNearName;
399 nearInfo.mappedName = kNearName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500400 nearInfo.precision = GL_HIGH_FLOAT;
401 nearInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200402 nearInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400403
Olli Etuahoe7c28572017-10-23 16:29:33 +0300404 ShaderVariable farInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400405 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500406 farInfo.name = kFarName;
407 farInfo.mappedName = kFarName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500408 farInfo.precision = GL_HIGH_FLOAT;
409 farInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200410 farInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400411
Olli Etuahoe7c28572017-10-23 16:29:33 +0300412 ShaderVariable diffInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400413 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500414 diffInfo.name = kDiffName;
415 diffInfo.mappedName = kDiffName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500416 diffInfo.precision = GL_HIGH_FLOAT;
417 diffInfo.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200418 diffInfo.active = true;
Jamie Madill55def582015-05-04 11:24:57 -0400419
420 info.fields.push_back(nearInfo);
421 info.fields.push_back(farInfo);
422 info.fields.push_back(diffInfo);
423
424 mUniforms->push_back(info);
425 mDepthRangeAdded = true;
426 }
427 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400428 else
Jamie Madill4667c452014-07-08 15:02:36 -0400429 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200430 switch (qualifier)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400431 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500432 case EvqAttribute:
433 case EvqVertexIn:
434 var = FindVariable(symbolName, mAttribs);
435 break;
436 case EvqFragmentOut:
437 var = FindVariable(symbolName, mOutputVariables);
438 break;
439 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400440 {
441 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
442 if (interfaceBlock)
443 {
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800444 var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400445 }
446 else
447 {
448 var = FindVariable(symbolName, mUniforms);
449 }
450
451 // It's an internal error to reference an undefined user uniform
Olli Etuahofbb1c792018-01-19 16:26:59 +0200452 ASSERT(!symbolName.beginsWith("gl_") || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400453 }
Jamie Madill4667c452014-07-08 15:02:36 -0400454 break;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800455 case EvqBuffer:
456 {
457 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
458 var =
459 FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
460 }
461 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500462 case EvqFragCoord:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200463 recordBuiltInVaryingUsed(ImmutableString("gl_FragCoord"), &mFragCoordAdded,
464 mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500465 return;
466 case EvqFrontFacing:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200467 recordBuiltInVaryingUsed(ImmutableString("gl_FrontFacing"), &mFrontFacingAdded,
468 mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500469 return;
470 case EvqPointCoord:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200471 recordBuiltInVaryingUsed(ImmutableString("gl_PointCoord"), &mPointCoordAdded,
472 mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500473 return;
474 case EvqInstanceID:
Martin Radev115fc552017-07-05 17:11:06 +0300475 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
476 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
477 // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
478 // which makes it necessary to populate the type information explicitly instead of
479 // extracting it from the symbol table.
480 if (!mInstanceIDAdded)
481 {
482 Attribute info;
483 const char kName[] = "gl_InstanceID";
484 info.name = kName;
485 info.mappedName = kName;
486 info.type = GL_INT;
Martin Radev115fc552017-07-05 17:11:06 +0300487 info.precision = GL_HIGH_INT; // Defined by spec.
488 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200489 info.active = true;
Martin Radev115fc552017-07-05 17:11:06 +0300490 info.location = -1;
491 mAttribs->push_back(info);
492 mInstanceIDAdded = true;
493 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500494 return;
495 case EvqVertexID:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200496 recordBuiltInAttributeUsed(ImmutableString("gl_VertexID"), &mVertexIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500497 return;
498 case EvqPosition:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200499 recordBuiltInVaryingUsed(ImmutableString("gl_Position"), &mPositionAdded,
500 mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500501 return;
502 case EvqPointSize:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200503 recordBuiltInVaryingUsed(ImmutableString("gl_PointSize"), &mPointSizeAdded,
504 mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500505 return;
506 case EvqLastFragData:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200507 recordBuiltInVaryingUsed(ImmutableString("gl_LastFragData"), &mLastFragDataAdded,
508 mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500509 return;
510 case EvqFragColor:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200511 recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragColor"), &mFragColorAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500512 return;
513 case EvqFragData:
514 if (!mFragDataAdded)
515 {
516 OutputVariable info;
Olli Etuahofbb1c792018-01-19 16:26:59 +0200517 setBuiltInInfoFromSymbolTable(ImmutableString("gl_FragData"), &info);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300518 if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500519 {
Olli Etuaho465835d2017-09-26 13:34:10 +0300520 ASSERT(info.arraySizes.size() == 1u);
521 info.arraySizes.back() = 1u;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500522 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500523 info.staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200524 info.active = true;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500525 mOutputVariables->push_back(info);
526 mFragDataAdded = true;
527 }
528 return;
529 case EvqFragDepthEXT:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200530 recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepthEXT"),
531 &mFragDepthEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500532 return;
533 case EvqFragDepth:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200534 recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepth"), &mFragDepthAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500535 return;
536 case EvqSecondaryFragColorEXT:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200537 recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragColorEXT"),
Olli Etuaho19515012017-06-26 18:00:17 +0300538 &mSecondaryFragColorEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500539 return;
540 case EvqSecondaryFragDataEXT:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200541 recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragDataEXT"),
Olli Etuaho19515012017-06-26 18:00:17 +0300542 &mSecondaryFragDataEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500543 return;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800544 case EvqInvocationID:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200545 recordBuiltInVaryingUsed(ImmutableString("gl_InvocationID"), &mInvocationIDAdded,
546 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800547 break;
548 case EvqPrimitiveIDIn:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200549 recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveIDIn"), &mPrimitiveIDInAdded,
550 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800551 break;
552 case EvqPrimitiveID:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800553 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800554 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200555 recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded,
556 mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800557 }
558 else
559 {
560 ASSERT(mShaderType == GL_FRAGMENT_SHADER);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200561 recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded,
562 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800563 }
564 break;
565 case EvqLayer:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800566 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800567 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200568 recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded,
569 mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800570 }
571 else if (mShaderType == GL_FRAGMENT_SHADER)
572 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200573 recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded,
574 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800575 }
576 else
577 {
578 ASSERT(mShaderType == GL_VERTEX_SHADER &&
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300579 IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800580 }
581 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500582 default:
583 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400584 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400585 }
586 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400587 {
Olli Etuaho06a06f52017-07-12 12:22:15 +0300588 MarkStaticallyUsed(var);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400589 }
590}
591
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200592void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
593 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400594{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000595 ASSERT(variableOut);
596
597 const TStructure *structure = type.getStruct();
Olli Etuahoa55102c2017-02-24 12:36:50 +0000598 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500599 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000600 variableOut->type = GLVariableType(type);
601 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500602 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000603 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400604 {
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400605 // Structures use a NONE type that isn't exposed outside ANGLE.
606 variableOut->type = GL_NONE;
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100607 if (structure->symbolType() != SymbolType::Empty)
608 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200609 variableOut->structName = structure->name().data();
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100610 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000611
612 const TFieldList &fields = structure->fields();
613
Olli Etuaho378c3a52017-12-04 11:32:13 +0200614 for (const TField *field : fields)
Olli Etuahoa55102c2017-02-24 12:36:50 +0000615 {
616 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
617 // ShaderVariable objects.
618 ShaderVariable fieldVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200619 setFieldProperties(*field->type(), field->name(), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000620 variableOut->fields.push_back(fieldVariable);
621 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400622 }
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800623 if (auto *arraySizes = type.getArraySizes())
624 {
625 variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
626 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000627}
Jamie Madill23a8a432014-07-09 13:27:42 -0400628
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200629void CollectVariablesTraverser::setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200630 const ImmutableString &name,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200631 ShaderVariable *variableOut) const
632{
633 ASSERT(variableOut);
634 setFieldOrVariableProperties(type, variableOut);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200635 variableOut->name.assign(name.data(), name.length());
636 variableOut->mappedName = HashName(name, mHashFunction, nullptr).data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200637}
638
639void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
640 const TVariable &variable,
641 ShaderVariable *variableOut) const
642{
643 ASSERT(variableOut);
644
645 setFieldOrVariableProperties(type, variableOut);
646 ASSERT(variable.symbolType() != SymbolType::Empty);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200647 variableOut->name.assign(variable.name().data(), variable.name().length());
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200648 variableOut->mappedName = getMappedName(&variable);
649}
650
Olli Etuaho19515012017-06-26 18:00:17 +0300651Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400652{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000653 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400654 ASSERT(!type.getStruct());
655
Jamie Madilla2fbb842014-09-03 09:40:47 -0400656 Attribute attribute;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200657 setCommonVariableProperties(type, variable.variable(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400658
Olli Etuahoa55102c2017-02-24 12:36:50 +0000659 attribute.location = type.getLayoutQualifier().location;
660 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400661}
662
Olli Etuaho19515012017-06-26 18:00:17 +0300663OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400664{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000665 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400666 ASSERT(!type.getStruct());
667
Olli Etuahoa55102c2017-02-24 12:36:50 +0000668 OutputVariable outputVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200669 setCommonVariableProperties(type, variable.variable(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400670
Olli Etuahoa55102c2017-02-24 12:36:50 +0000671 outputVariable.location = type.getLayoutQualifier().location;
672 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400673}
674
Olli Etuaho19515012017-06-26 18:00:17 +0300675Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400676{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000677 const TType &type = variable.getType();
678
679 Varying varying;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200680 setCommonVariableProperties(type, variable.variable(), &varying);
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800681 varying.location = type.getLayoutQualifier().location;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000682
683 switch (type.getQualifier())
684 {
685 case EvqVaryingIn:
686 case EvqVaryingOut:
687 case EvqVertexOut:
688 case EvqSmoothOut:
689 case EvqFlatOut:
690 case EvqCentroidOut:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800691 case EvqGeometryOut:
Olli Etuahodefe3932018-02-13 11:56:09 +0200692 if (mSymbolTable->isVaryingInvariant(variable.getName()) || type.isInvariant())
Olli Etuahoa55102c2017-02-24 12:36:50 +0000693 {
694 varying.isInvariant = true;
695 }
696 break;
697 default:
698 break;
699 }
700
701 varying.interpolation = GetInterpolationType(type.getQualifier());
702 return varying;
703}
704
Jiawei Shaobd924af2017-11-16 15:28:04 +0800705// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200706void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200707 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800708 InterfaceBlock *interfaceBlock) const
Olli Etuahoa55102c2017-02-24 12:36:50 +0000709{
Jiawei Shaod8105a02017-08-08 09:54:36 +0800710 ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
711 ASSERT(interfaceBlock);
712
713 const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400714 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400715
Olli Etuahofbb1c792018-01-19 16:26:59 +0200716 interfaceBlock->name = blockType->name().data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200717 interfaceBlock->mappedName = getMappedName(blockType);
718 if (instanceName != nullptr)
719 {
720 interfaceBlock->instanceName = instanceName;
721 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300722 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
723 interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800724
725 interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
726 if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
727 interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
728 {
Olli Etuaho3de27032017-11-30 12:16:47 +0200729 // TODO(oetuaho): Remove setting isRowMajorLayout.
730 interfaceBlock->isRowMajorLayout = false;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800731 interfaceBlock->binding = blockType->blockBinding();
732 interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
733 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400734
Jamie Madilla6f267f2014-08-27 11:44:15 -0400735 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500736 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400737 {
Jamie Madill39046162016-02-08 15:05:17 -0500738 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400739
Olli Etuahoa55102c2017-02-24 12:36:50 +0000740 InterfaceBlockField fieldVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200741 setFieldProperties(fieldType, field->name(), &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 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400746}
747
Olli Etuaho19515012017-06-26 18:00:17 +0300748Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400749{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000750 Uniform uniform;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200751 setCommonVariableProperties(variable.getType(), variable.variable(), &uniform);
Olli Etuaho78ed6cd2017-08-09 16:19:00 +0300752 uniform.binding = variable.getType().getLayoutQualifier().binding;
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000753 uniform.location = variable.getType().getLayoutQualifier().location;
jchen104cdac9e2017-05-08 11:01:20 +0800754 uniform.offset = variable.getType().getLayoutQualifier().offset;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800755 uniform.readonly = variable.getType().getMemoryQualifier().readonly;
756 uniform.writeonly = variable.getType().getMemoryQualifier().writeonly;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000757 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000758}
759
Olli Etuaho19515012017-06-26 18:00:17 +0300760bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000761{
Olli Etuaho13389b62016-10-16 11:48:18 +0100762 const TIntermSequence &sequence = *(node->getSequence());
763 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000764
Olli Etuaho13389b62016-10-16 11:48:18 +0100765 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
766 TQualifier qualifier = typedNode.getQualifier();
767
Olli Etuahoa55102c2017-02-24 12:36:50 +0000768 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
769 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
770 IsVarying(qualifier);
771
772 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000773 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000774 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100775 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000776
777 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100778 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000779 // The only case in which the sequence will not contain a TIntermSymbol node is
780 // initialization. It will contain a TInterBinary node in that case. Since attributes,
781 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
782 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
783 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200784 if (variable.variable().symbolType() == SymbolType::AngleInternal)
Olli Etuaho34d20072017-07-18 20:07:18 +0300785 {
786 // Internal variables are not collected.
787 continue;
788 }
789
Jiawei Shaobd924af2017-11-16 15:28:04 +0800790 // TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuahoa55102c2017-02-24 12:36:50 +0000791 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000792 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800793 InterfaceBlock interfaceBlock;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200794 recordInterfaceBlock(variable.variable().symbolType() != SymbolType::Empty
Olli Etuahofbb1c792018-01-19 16:26:59 +0200795 ? variable.getName().data()
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200796 : nullptr,
797 variable.getType(), &interfaceBlock);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800798
799 switch (qualifier)
Jiajia Qinbc585152017-06-23 15:42:17 +0800800 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800801 case EvqUniform:
802 mUniformBlocks->push_back(interfaceBlock);
803 break;
804 case EvqBuffer:
805 mShaderStorageBlocks->push_back(interfaceBlock);
806 break;
807 default:
808 UNREACHABLE();
Jiajia Qinbc585152017-06-23 15:42:17 +0800809 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000810 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000811 else
812 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200813 ASSERT(variable.variable().symbolType() != SymbolType::Empty);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000814 switch (qualifier)
815 {
816 case EvqAttribute:
817 case EvqVertexIn:
818 mAttribs->push_back(recordAttribute(variable));
819 break;
820 case EvqFragmentOut:
821 mOutputVariables->push_back(recordOutputVariable(variable));
822 break;
823 case EvqUniform:
824 mUniforms->push_back(recordUniform(variable));
825 break;
826 default:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800827 if (IsVaryingIn(qualifier))
828 {
829 mInputVaryings->push_back(recordVarying(variable));
830 }
831 else
832 {
833 ASSERT(IsVaryingOut(qualifier));
834 mOutputVaryings->push_back(recordVarying(variable));
835 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000836 break;
837 }
838 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000839 }
840
Olli Etuahoa55102c2017-02-24 12:36:50 +0000841 // None of the recorded variables can have initializers, so we don't need to traverse the
842 // declarators.
843 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000844}
Jamie Madill23a8a432014-07-09 13:27:42 -0400845
Jiawei Shaod8105a02017-08-08 09:54:36 +0800846// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
Jiawei Shaobd924af2017-11-16 15:28:04 +0800847// GL_EXT_shader_io_blocks.
Olli Etuahofbb1c792018-01-19 16:26:59 +0200848InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(
849 const ImmutableString &blockName) const
Jiawei Shaod8105a02017-08-08 09:54:36 +0800850{
851 InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
852 if (!namedBlock)
853 {
854 namedBlock = FindVariable(blockName, mShaderStorageBlocks);
855 }
856 return namedBlock;
857}
858
Olli Etuaho19515012017-06-26 18:00:17 +0300859bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
Jamie Madillb547ddf2014-08-25 16:20:46 -0400860{
861 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
862 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400863 // NOTE: we do not determine static use for individual blocks of an array
864 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
865 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400866
867 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
868 ASSERT(constantUnion);
869
Jiawei Shaod8105a02017-08-08 09:54:36 +0800870 InterfaceBlock *namedBlock = nullptr;
871
872 bool traverseIndexExpression = false;
873 TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
874 if (interfaceIndexingNode)
875 {
876 TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
877 ASSERT(interfaceNode);
878
879 const TType &interfaceType = interfaceNode->getType();
880 if (interfaceType.getQualifier() == EvqPerVertexIn)
881 {
882 namedBlock = recordGLInUsed(interfaceType);
883 ASSERT(namedBlock);
884
885 // We need to continue traversing to collect useful variables in the index
886 // expression of gl_in.
887 traverseIndexExpression = true;
888 }
889 }
890
Jamie Madilla6f267f2014-08-27 11:44:15 -0400891 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800892 if (!namedBlock)
Jiajia Qinbc585152017-06-23 15:42:17 +0800893 {
Olli Etuahobed35d72017-12-20 16:36:26 +0200894 namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
Jiajia Qinbc585152017-06-23 15:42:17 +0800895 }
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800896 ASSERT(namedBlock);
897 namedBlock->staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200898 namedBlock->active = true;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800899 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
900 ASSERT(fieldIndex < namedBlock->fields.size());
901 namedBlock->fields[fieldIndex].staticUse = true;
Olli Etuaho107c7242018-03-20 15:45:35 +0200902 namedBlock->fields[fieldIndex].active = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800903
904 if (traverseIndexExpression)
905 {
906 ASSERT(interfaceIndexingNode);
907 interfaceIndexingNode->getRight()->traverse(this);
908 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400909 return false;
910 }
911
912 return true;
913}
914
Olli Etuaho19515012017-06-26 18:00:17 +0300915} // anonymous namespace
916
917void CollectVariables(TIntermBlock *root,
918 std::vector<Attribute> *attributes,
919 std::vector<OutputVariable> *outputVariables,
920 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800921 std::vector<Varying> *inputVaryings,
922 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800923 std::vector<InterfaceBlock> *uniformBlocks,
924 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800925 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300926 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300927 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300928 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800929 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300930 const TExtensionBehavior &extensionBehavior)
931{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800932 CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800933 outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800934 hashFunction, symbolTable, shaderVersion, shaderType,
935 extensionBehavior);
Olli Etuaho19515012017-06-26 18:00:17 +0300936 root->traverse(&collect);
937}
938
Olli Etuaho19515012017-06-26 18:00:17 +0300939} // namespace sh