blob: e0f73ca4ad5bc055e735d3b80ff7d2ea13e6521e [file] [log] [blame]
alokp@chromium.org07620a52010-09-23 17:53:56 +00001//
shannonwoods@chromium.orge429ab72013-05-30 00:12:52 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
alokp@chromium.org07620a52010-09-23 17:53:56 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
Olli Etuaho78ed6cd2017-08-09 16:19:00 +03006// CollectVariables.cpp: Collect lists of shader interface variables based on the AST.
alokp@chromium.org07620a52010-09-23 17:53:56 +00007
Olli Etuaho78ed6cd2017-08-09 16:19:00 +03008#include "compiler/translator/CollectVariables.h"
Olli Etuaho19515012017-06-26 18:00:17 +03009
10#include "angle_gl.h"
Jamie Madilld5512cd2014-07-10 17:50:08 -040011#include "common/utilities.h"
Olli Etuahocccf2b02017-07-05 14:50:54 +030012#include "compiler/translator/HashNames.h"
13#include "compiler/translator/IntermTraverse.h"
Olli Etuaho19515012017-06-26 18:00:17 +030014#include "compiler/translator/SymbolTable.h"
15#include "compiler/translator/util.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000016
Jamie Madilla2fbb842014-09-03 09:40:47 -040017namespace sh
18{
19
Jamie Madill54ad4f82014-09-03 09:40:46 -040020namespace
21{
Zhenyao Mod2d340b2013-09-23 14:57:05 -040022
Jamie Madilla2fbb842014-09-03 09:40:47 -040023BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
Jamie Madill54ad4f82014-09-03 09:40:46 -040024{
25 switch (blockStorage)
26 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -050027 case EbsPacked:
28 return BLOCKLAYOUT_PACKED;
29 case EbsShared:
30 return BLOCKLAYOUT_SHARED;
31 case EbsStd140:
Qin Jiajiaca68d982017-09-18 16:41:56 +080032 return BLOCKLAYOUT_STD140;
33 case EbsStd430:
34 return BLOCKLAYOUT_STD430;
Jamie Madilld7b1ab52016-12-12 14:42:19 -050035 default:
36 UNREACHABLE();
37 return BLOCKLAYOUT_SHARED;
Jamie Madill54ad4f82014-09-03 09:40:46 -040038 }
39}
40
Jiawei Shaobd924af2017-11-16 15:28:04 +080041// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Jiajia Qin9b11ea42017-07-11 16:50:08 +080042BlockType GetBlockType(TQualifier qualifier)
43{
44 switch (qualifier)
45 {
46 case EvqUniform:
47 return BlockType::BLOCK_UNIFORM;
48 case EvqBuffer:
49 return BlockType::BLOCK_BUFFER;
Jiawei Shaod8105a02017-08-08 09:54:36 +080050 case EvqPerVertexIn:
51 return BlockType::BLOCK_IN;
Jiajia Qin9b11ea42017-07-11 16:50:08 +080052 default:
53 UNREACHABLE();
54 return BlockType::BLOCK_UNIFORM;
55 }
56}
57
Jamie Madilla718c1e2014-07-02 15:31:22 -040058template <class VarT>
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;
86 }
87}
88
Olli Etuahofbb1c792018-01-19 16:26:59 +020089ShaderVariable *FindVariableInInterfaceBlock(const ImmutableString &name,
Jiajia Qin3a9090f2017-09-27 14:37:04 +080090 const TInterfaceBlock *interfaceBlock,
91 std::vector<InterfaceBlock> *infoList)
92{
93 ASSERT(interfaceBlock);
Olli Etuahobed35d72017-12-20 16:36:26 +020094 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
Jiajia Qin3a9090f2017-09-27 14:37:04 +080095 ASSERT(namedBlock);
96
97 // Set static use on the parent interface block here
98 namedBlock->staticUse = true;
99 return FindVariable(name, &namedBlock->fields);
100}
101
Olli Etuaho19515012017-06-26 18:00:17 +0300102// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
103// and interface blocks.
104class CollectVariablesTraverser : public TIntermTraverser
105{
106 public:
107 CollectVariablesTraverser(std::vector<Attribute> *attribs,
108 std::vector<OutputVariable> *outputVariables,
109 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800110 std::vector<Varying> *inputVaryings,
111 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800112 std::vector<InterfaceBlock> *uniformBlocks,
113 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800114 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300115 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300116 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300117 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800118 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300119 const TExtensionBehavior &extensionBehavior);
120
121 void visitSymbol(TIntermSymbol *symbol) override;
122 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
123 bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
124
125 private:
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200126 std::string getMappedName(const TSymbol *symbol) const;
Olli Etuaho855d9642017-05-17 14:05:06 +0300127
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200128 void setFieldOrVariableProperties(const TType &type, ShaderVariable *variableOut) const;
129 void setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200130 const ImmutableString &name,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200131 ShaderVariable *variableOut) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300132 void setCommonVariableProperties(const TType &type,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200133 const TVariable &variable,
Olli Etuaho19515012017-06-26 18:00:17 +0300134 ShaderVariable *variableOut) const;
135
136 Attribute recordAttribute(const TIntermSymbol &variable) const;
137 OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
138 Varying recordVarying(const TIntermSymbol &variable) const;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200139 void recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200140 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800141 InterfaceBlock *interfaceBlock) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300142 Uniform recordUniform(const TIntermSymbol &variable) const;
143
Olli Etuahofbb1c792018-01-19 16:26:59 +0200144 void setBuiltInInfoFromSymbolTable(const ImmutableString &name, ShaderVariable *info);
Olli Etuaho19515012017-06-26 18:00:17 +0300145
Olli Etuahofbb1c792018-01-19 16:26:59 +0200146 void recordBuiltInVaryingUsed(const ImmutableString &name,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800147 bool *addedFlag,
148 std::vector<Varying> *varyings);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200149 void recordBuiltInFragmentOutputUsed(const ImmutableString &name, bool *addedFlag);
150 void recordBuiltInAttributeUsed(const ImmutableString &name, bool *addedFlag);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800151 InterfaceBlock *recordGLInUsed(const TType &glInType);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200152 InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300153
154 std::vector<Attribute> *mAttribs;
155 std::vector<OutputVariable> *mOutputVariables;
156 std::vector<Uniform> *mUniforms;
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800157 std::vector<Varying> *mInputVaryings;
158 std::vector<Varying> *mOutputVaryings;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800159 std::vector<InterfaceBlock> *mUniformBlocks;
160 std::vector<InterfaceBlock> *mShaderStorageBlocks;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800161 std::vector<InterfaceBlock> *mInBlocks;
Olli Etuaho19515012017-06-26 18:00:17 +0300162
163 std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
164
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800165 // Shader uniforms
Olli Etuaho19515012017-06-26 18:00:17 +0300166 bool mDepthRangeAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800167
168 // Vertex Shader builtins
169 bool mInstanceIDAdded;
170 bool mVertexIDAdded;
171 bool mPointSizeAdded;
172
173 // Vertex Shader and Geometry Shader builtins
174 bool mPositionAdded;
175
176 // Fragment Shader builtins
Olli Etuaho19515012017-06-26 18:00:17 +0300177 bool mPointCoordAdded;
178 bool mFrontFacingAdded;
179 bool mFragCoordAdded;
Olli Etuaho19515012017-06-26 18:00:17 +0300180 bool mLastFragDataAdded;
181 bool mFragColorAdded;
182 bool mFragDataAdded;
183 bool mFragDepthEXTAdded;
184 bool mFragDepthAdded;
185 bool mSecondaryFragColorEXTAdded;
186 bool mSecondaryFragDataEXTAdded;
187
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800188 // Geometry Shader builtins
Jiawei Shaod8105a02017-08-08 09:54:36 +0800189 bool mPerVertexInAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800190 bool mPrimitiveIDInAdded;
191 bool mInvocationIDAdded;
192
193 // Geometry Shader and Fragment Shader builtins
194 bool mPrimitiveIDAdded;
195 bool mLayerAdded;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800196
Olli Etuaho19515012017-06-26 18:00:17 +0300197 ShHashFunction64 mHashFunction;
198
Olli Etuaho19515012017-06-26 18:00:17 +0300199 int mShaderVersion;
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,
Olli Etuaho19515012017-06-26 18:00:17 +0300215 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800216 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300217 const TExtensionBehavior &extensionBehavior)
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300218 : TIntermTraverser(true, false, false, symbolTable),
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300219 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400220 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000221 mUniforms(uniforms),
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800222 mInputVaryings(inputVaryings),
223 mOutputVaryings(outputVaryings),
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800224 mUniformBlocks(uniformBlocks),
225 mShaderStorageBlocks(shaderStorageBlocks),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800226 mInBlocks(inBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400227 mDepthRangeAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800228 mInstanceIDAdded(false),
229 mVertexIDAdded(false),
230 mPointSizeAdded(false),
231 mPositionAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400232 mPointCoordAdded(false),
233 mFrontFacingAdded(false),
234 mFragCoordAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100235 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300236 mFragColorAdded(false),
237 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300238 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300239 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300240 mSecondaryFragColorEXTAdded(false),
241 mSecondaryFragDataEXTAdded(false),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800242 mPerVertexInAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800243 mPrimitiveIDInAdded(false),
244 mInvocationIDAdded(false),
245 mPrimitiveIDAdded(false),
246 mLayerAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700247 mHashFunction(hashFunction),
Olli Etuaho19515012017-06-26 18:00:17 +0300248 mShaderVersion(shaderVersion),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800249 mShaderType(shaderType),
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700250 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000251{
252}
253
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200254std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const
Olli Etuaho855d9642017-05-17 14:05:06 +0300255{
Olli Etuahofbb1c792018-01-19 16:26:59 +0200256 return HashName(symbol, mHashFunction, nullptr).data();
Olli Etuaho855d9642017-05-17 14:05:06 +0300257}
258
Olli Etuahofbb1c792018-01-19 16:26:59 +0200259void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const ImmutableString &name,
Olli Etuaho19515012017-06-26 18:00:17 +0300260 ShaderVariable *info)
261{
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200262 const TVariable *symbolTableVar =
263 reinterpret_cast<const TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
Olli Etuaho19515012017-06-26 18:00:17 +0300264 ASSERT(symbolTableVar);
265 const TType &type = symbolTableVar->getType();
266
Olli Etuahofbb1c792018-01-19 16:26:59 +0200267 info->name = name.data();
268 info->mappedName = name.data();
Olli Etuaho19515012017-06-26 18:00:17 +0300269 info->type = GLVariableType(type);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300270 info->precision = GLVariablePrecision(type);
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800271 if (auto *arraySizes = type.getArraySizes())
272 {
273 info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
274 }
Olli Etuaho19515012017-06-26 18:00:17 +0300275}
276
Olli Etuahofbb1c792018-01-19 16:26:59 +0200277void CollectVariablesTraverser::recordBuiltInVaryingUsed(const ImmutableString &name,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800278 bool *addedFlag,
279 std::vector<Varying> *varyings)
Olli Etuaho19515012017-06-26 18:00:17 +0300280{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800281 ASSERT(varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300282 if (!(*addedFlag))
283 {
284 Varying info;
285 setBuiltInInfoFromSymbolTable(name, &info);
286 info.staticUse = true;
Olli Etuahofbb1c792018-01-19 16:26:59 +0200287 info.isInvariant = mSymbolTable->isVaryingInvariant(name.data());
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800288 varyings->push_back(info);
Olli Etuaho19515012017-06-26 18:00:17 +0300289 (*addedFlag) = true;
290 }
291}
292
Olli Etuahofbb1c792018-01-19 16:26:59 +0200293void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const ImmutableString &name,
294 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300295{
296 if (!(*addedFlag))
297 {
298 OutputVariable info;
299 setBuiltInInfoFromSymbolTable(name, &info);
300 info.staticUse = true;
301 mOutputVariables->push_back(info);
302 (*addedFlag) = true;
303 }
304}
305
Olli Etuahofbb1c792018-01-19 16:26:59 +0200306void CollectVariablesTraverser::recordBuiltInAttributeUsed(const ImmutableString &name,
307 bool *addedFlag)
Olli Etuaho19515012017-06-26 18:00:17 +0300308{
309 if (!(*addedFlag))
310 {
311 Attribute info;
312 setBuiltInInfoFromSymbolTable(name, &info);
313 info.staticUse = true;
314 info.location = -1;
315 mAttribs->push_back(info);
316 (*addedFlag) = true;
317 }
318}
319
Jiawei Shaod8105a02017-08-08 09:54:36 +0800320InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
321{
322 if (!mPerVertexInAdded)
323 {
324 ASSERT(glInType.getQualifier() == EvqPerVertexIn);
325 InterfaceBlock info;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200326 recordInterfaceBlock("gl_in", glInType, &info);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800327 info.staticUse = true;
328
329 mPerVertexInAdded = true;
330 mInBlocks->push_back(info);
331 return &mInBlocks->back();
332 }
333 else
334 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200335 return FindVariable(ImmutableString("gl_PerVertex"), mInBlocks);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800336 }
337}
338
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400339// We want to check whether a uniform/varying is statically used
340// because we only count the used ones in packing computing.
341// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
342// toward varying counting if they are statically used in a fragment
343// shader.
Olli Etuaho19515012017-06-26 18:00:17 +0300344void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000345{
Yunchao He4f285442017-04-21 12:15:49 +0800346 ASSERT(symbol != nullptr);
Olli Etuaho34d20072017-07-18 20:07:18 +0300347
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200348 if (symbol->variable().symbolType() == SymbolType::AngleInternal ||
349 symbol->variable().symbolType() == SymbolType::Empty)
Olli Etuaho34d20072017-07-18 20:07:18 +0300350 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200351 // Internal variables or nameless variables are not collected.
Olli Etuaho34d20072017-07-18 20:07:18 +0300352 return;
353 }
354
Yunchao Hed7297bf2017-04-19 15:27:10 +0800355 ShaderVariable *var = nullptr;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200356
Olli Etuahofbb1c792018-01-19 16:26:59 +0200357 const ImmutableString &symbolName = symbol->getName();
Jamie Madill4667c452014-07-08 15:02:36 -0400358
Olli Etuahob8cb9392017-12-20 14:23:19 +0200359 // Check the qualifier from the variable, not from the symbol node. The node may have a
360 // different qualifier if it's the result of a folded ternary node.
361 TQualifier qualifier = symbol->variable().getType().getQualifier();
362
363 if (IsVaryingIn(qualifier))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400364 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800365 var = FindVariable(symbolName, mInputVaryings);
366 }
Olli Etuahob8cb9392017-12-20 14:23:19 +0200367 else if (IsVaryingOut(qualifier))
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800368 {
369 var = FindVariable(symbolName, mOutputVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400370 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400371 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
372 {
373 UNREACHABLE();
374 }
Jamie Madill55def582015-05-04 11:24:57 -0400375 else if (symbolName == "gl_DepthRange")
376 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200377 ASSERT(qualifier == EvqUniform);
Jamie Madill55def582015-05-04 11:24:57 -0400378
379 if (!mDepthRangeAdded)
380 {
381 Uniform info;
382 const char kName[] = "gl_DepthRange";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500383 info.name = kName;
384 info.mappedName = kName;
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400385 info.type = GL_NONE;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500386 info.precision = GL_NONE;
387 info.staticUse = true;
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;
Jamie Madill55def582015-05-04 11:24:57 -0400395
Olli Etuahoe7c28572017-10-23 16:29:33 +0300396 ShaderVariable farInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400397 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500398 farInfo.name = kFarName;
399 farInfo.mappedName = kFarName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500400 farInfo.precision = GL_HIGH_FLOAT;
401 farInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400402
Olli Etuahoe7c28572017-10-23 16:29:33 +0300403 ShaderVariable diffInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400404 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500405 diffInfo.name = kDiffName;
406 diffInfo.mappedName = kDiffName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500407 diffInfo.precision = GL_HIGH_FLOAT;
408 diffInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400409
410 info.fields.push_back(nearInfo);
411 info.fields.push_back(farInfo);
412 info.fields.push_back(diffInfo);
413
414 mUniforms->push_back(info);
415 mDepthRangeAdded = true;
416 }
417 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400418 else
Jamie Madill4667c452014-07-08 15:02:36 -0400419 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200420 switch (qualifier)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400421 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500422 case EvqAttribute:
423 case EvqVertexIn:
424 var = FindVariable(symbolName, mAttribs);
425 break;
426 case EvqFragmentOut:
427 var = FindVariable(symbolName, mOutputVariables);
428 break;
429 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400430 {
431 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
432 if (interfaceBlock)
433 {
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800434 var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400435 }
436 else
437 {
438 var = FindVariable(symbolName, mUniforms);
439 }
440
441 // It's an internal error to reference an undefined user uniform
Olli Etuahofbb1c792018-01-19 16:26:59 +0200442 ASSERT(!symbolName.beginsWith("gl_") || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400443 }
Jamie Madill4667c452014-07-08 15:02:36 -0400444 break;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800445 case EvqBuffer:
446 {
447 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
448 var =
449 FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
450 }
451 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500452 case EvqFragCoord:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200453 recordBuiltInVaryingUsed(ImmutableString("gl_FragCoord"), &mFragCoordAdded,
454 mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500455 return;
456 case EvqFrontFacing:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200457 recordBuiltInVaryingUsed(ImmutableString("gl_FrontFacing"), &mFrontFacingAdded,
458 mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500459 return;
460 case EvqPointCoord:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200461 recordBuiltInVaryingUsed(ImmutableString("gl_PointCoord"), &mPointCoordAdded,
462 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
467 // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
468 // which makes it necessary to populate the type information explicitly instead of
469 // extracting it from the symbol table.
470 if (!mInstanceIDAdded)
471 {
472 Attribute info;
473 const char kName[] = "gl_InstanceID";
474 info.name = kName;
475 info.mappedName = kName;
476 info.type = GL_INT;
Martin Radev115fc552017-07-05 17:11:06 +0300477 info.precision = GL_HIGH_INT; // Defined by spec.
478 info.staticUse = true;
479 info.location = -1;
480 mAttribs->push_back(info);
481 mInstanceIDAdded = true;
482 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500483 return;
484 case EvqVertexID:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200485 recordBuiltInAttributeUsed(ImmutableString("gl_VertexID"), &mVertexIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500486 return;
487 case EvqPosition:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200488 recordBuiltInVaryingUsed(ImmutableString("gl_Position"), &mPositionAdded,
489 mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500490 return;
491 case EvqPointSize:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200492 recordBuiltInVaryingUsed(ImmutableString("gl_PointSize"), &mPointSizeAdded,
493 mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500494 return;
495 case EvqLastFragData:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200496 recordBuiltInVaryingUsed(ImmutableString("gl_LastFragData"), &mLastFragDataAdded,
497 mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500498 return;
499 case EvqFragColor:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200500 recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragColor"), &mFragColorAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500501 return;
502 case EvqFragData:
503 if (!mFragDataAdded)
504 {
505 OutputVariable info;
Olli Etuahofbb1c792018-01-19 16:26:59 +0200506 setBuiltInInfoFromSymbolTable(ImmutableString("gl_FragData"), &info);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300507 if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500508 {
Olli Etuaho465835d2017-09-26 13:34:10 +0300509 ASSERT(info.arraySizes.size() == 1u);
510 info.arraySizes.back() = 1u;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500511 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500512 info.staticUse = true;
513 mOutputVariables->push_back(info);
514 mFragDataAdded = true;
515 }
516 return;
517 case EvqFragDepthEXT:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200518 recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepthEXT"),
519 &mFragDepthEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500520 return;
521 case EvqFragDepth:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200522 recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepth"), &mFragDepthAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500523 return;
524 case EvqSecondaryFragColorEXT:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200525 recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragColorEXT"),
Olli Etuaho19515012017-06-26 18:00:17 +0300526 &mSecondaryFragColorEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500527 return;
528 case EvqSecondaryFragDataEXT:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200529 recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragDataEXT"),
Olli Etuaho19515012017-06-26 18:00:17 +0300530 &mSecondaryFragDataEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500531 return;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800532 case EvqInvocationID:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200533 recordBuiltInVaryingUsed(ImmutableString("gl_InvocationID"), &mInvocationIDAdded,
534 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800535 break;
536 case EvqPrimitiveIDIn:
Olli Etuahofbb1c792018-01-19 16:26:59 +0200537 recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveIDIn"), &mPrimitiveIDInAdded,
538 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800539 break;
540 case EvqPrimitiveID:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800541 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800542 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200543 recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded,
544 mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800545 }
546 else
547 {
548 ASSERT(mShaderType == GL_FRAGMENT_SHADER);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200549 recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded,
550 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800551 }
552 break;
553 case EvqLayer:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800554 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800555 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200556 recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded,
557 mOutputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800558 }
559 else if (mShaderType == GL_FRAGMENT_SHADER)
560 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200561 recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded,
562 mInputVaryings);
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800563 }
564 else
565 {
566 ASSERT(mShaderType == GL_VERTEX_SHADER &&
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300567 IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800568 }
569 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500570 default:
571 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400572 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400573 }
574 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400575 {
Olli Etuaho06a06f52017-07-12 12:22:15 +0300576 MarkStaticallyUsed(var);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400577 }
578}
579
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200580void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
581 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400582{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000583 ASSERT(variableOut);
584
585 const TStructure *structure = type.getStruct();
Olli Etuahoa55102c2017-02-24 12:36:50 +0000586 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500587 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000588 variableOut->type = GLVariableType(type);
589 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500590 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000591 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400592 {
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400593 // Structures use a NONE type that isn't exposed outside ANGLE.
594 variableOut->type = GL_NONE;
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100595 if (structure->symbolType() != SymbolType::Empty)
596 {
Olli Etuahofbb1c792018-01-19 16:26:59 +0200597 variableOut->structName = structure->name().data();
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100598 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000599
600 const TFieldList &fields = structure->fields();
601
Olli Etuaho378c3a52017-12-04 11:32:13 +0200602 for (const TField *field : fields)
Olli Etuahoa55102c2017-02-24 12:36:50 +0000603 {
604 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
605 // ShaderVariable objects.
606 ShaderVariable fieldVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200607 setFieldProperties(*field->type(), field->name(), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000608 variableOut->fields.push_back(fieldVariable);
609 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400610 }
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800611 if (auto *arraySizes = type.getArraySizes())
612 {
613 variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
614 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000615}
Jamie Madill23a8a432014-07-09 13:27:42 -0400616
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200617void CollectVariablesTraverser::setFieldProperties(const TType &type,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200618 const ImmutableString &name,
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200619 ShaderVariable *variableOut) const
620{
621 ASSERT(variableOut);
622 setFieldOrVariableProperties(type, variableOut);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200623 variableOut->name.assign(name.data(), name.length());
624 variableOut->mappedName = HashName(name, mHashFunction, nullptr).data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200625}
626
627void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
628 const TVariable &variable,
629 ShaderVariable *variableOut) const
630{
631 ASSERT(variableOut);
632
633 setFieldOrVariableProperties(type, variableOut);
634 ASSERT(variable.symbolType() != SymbolType::Empty);
Olli Etuahofbb1c792018-01-19 16:26:59 +0200635 variableOut->name.assign(variable.name().data(), variable.name().length());
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200636 variableOut->mappedName = getMappedName(&variable);
637}
638
Olli Etuaho19515012017-06-26 18:00:17 +0300639Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400640{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000641 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400642 ASSERT(!type.getStruct());
643
Jamie Madilla2fbb842014-09-03 09:40:47 -0400644 Attribute attribute;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200645 setCommonVariableProperties(type, variable.variable(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400646
Olli Etuahoa55102c2017-02-24 12:36:50 +0000647 attribute.location = type.getLayoutQualifier().location;
648 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400649}
650
Olli Etuaho19515012017-06-26 18:00:17 +0300651OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400652{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000653 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400654 ASSERT(!type.getStruct());
655
Olli Etuahoa55102c2017-02-24 12:36:50 +0000656 OutputVariable outputVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200657 setCommonVariableProperties(type, variable.variable(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400658
Olli Etuahoa55102c2017-02-24 12:36:50 +0000659 outputVariable.location = type.getLayoutQualifier().location;
660 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400661}
662
Olli Etuaho19515012017-06-26 18:00:17 +0300663Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400664{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000665 const TType &type = variable.getType();
666
667 Varying varying;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200668 setCommonVariableProperties(type, variable.variable(), &varying);
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800669 varying.location = type.getLayoutQualifier().location;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000670
671 switch (type.getQualifier())
672 {
673 case EvqVaryingIn:
674 case EvqVaryingOut:
675 case EvqVertexOut:
676 case EvqSmoothOut:
677 case EvqFlatOut:
678 case EvqCentroidOut:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800679 case EvqGeometryOut:
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200680 if (mSymbolTable->isVaryingInvariant(varying.name) || type.isInvariant())
Olli Etuahoa55102c2017-02-24 12:36:50 +0000681 {
682 varying.isInvariant = true;
683 }
684 break;
685 default:
686 break;
687 }
688
689 varying.interpolation = GetInterpolationType(type.getQualifier());
690 return varying;
691}
692
Jiawei Shaobd924af2017-11-16 15:28:04 +0800693// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200694void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName,
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200695 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800696 InterfaceBlock *interfaceBlock) const
Olli Etuahoa55102c2017-02-24 12:36:50 +0000697{
Jiawei Shaod8105a02017-08-08 09:54:36 +0800698 ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
699 ASSERT(interfaceBlock);
700
701 const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400702 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400703
Olli Etuahofbb1c792018-01-19 16:26:59 +0200704 interfaceBlock->name = blockType->name().data();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200705 interfaceBlock->mappedName = getMappedName(blockType);
706 if (instanceName != nullptr)
707 {
708 interfaceBlock->instanceName = instanceName;
709 }
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300710 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
711 interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800712
713 interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
714 if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
715 interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
716 {
Olli Etuaho3de27032017-11-30 12:16:47 +0200717 // TODO(oetuaho): Remove setting isRowMajorLayout.
718 interfaceBlock->isRowMajorLayout = false;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800719 interfaceBlock->binding = blockType->blockBinding();
720 interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
721 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400722
Jamie Madilla6f267f2014-08-27 11:44:15 -0400723 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500724 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400725 {
Jamie Madill39046162016-02-08 15:05:17 -0500726 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400727
Olli Etuahoa55102c2017-02-24 12:36:50 +0000728 InterfaceBlockField fieldVariable;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200729 setFieldProperties(fieldType, field->name(), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000730 fieldVariable.isRowMajorLayout =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500731 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800732 interfaceBlock->fields.push_back(fieldVariable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400733 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400734}
735
Olli Etuaho19515012017-06-26 18:00:17 +0300736Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400737{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000738 Uniform uniform;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200739 setCommonVariableProperties(variable.getType(), variable.variable(), &uniform);
Olli Etuaho78ed6cd2017-08-09 16:19:00 +0300740 uniform.binding = variable.getType().getLayoutQualifier().binding;
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000741 uniform.location = variable.getType().getLayoutQualifier().location;
jchen104cdac9e2017-05-08 11:01:20 +0800742 uniform.offset = variable.getType().getLayoutQualifier().offset;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800743 uniform.readonly = variable.getType().getMemoryQualifier().readonly;
744 uniform.writeonly = variable.getType().getMemoryQualifier().writeonly;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000745 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000746}
747
Olli Etuaho19515012017-06-26 18:00:17 +0300748bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000749{
Olli Etuaho13389b62016-10-16 11:48:18 +0100750 const TIntermSequence &sequence = *(node->getSequence());
751 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000752
Olli Etuaho13389b62016-10-16 11:48:18 +0100753 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
754 TQualifier qualifier = typedNode.getQualifier();
755
Olli Etuahoa55102c2017-02-24 12:36:50 +0000756 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
757 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
758 IsVarying(qualifier);
759
760 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000761 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000762 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100763 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000764
765 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100766 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000767 // The only case in which the sequence will not contain a TIntermSymbol node is
768 // initialization. It will contain a TInterBinary node in that case. Since attributes,
769 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
770 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
771 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200772 if (variable.variable().symbolType() == SymbolType::AngleInternal)
Olli Etuaho34d20072017-07-18 20:07:18 +0300773 {
774 // Internal variables are not collected.
775 continue;
776 }
777
Jiawei Shaobd924af2017-11-16 15:28:04 +0800778 // TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuahoa55102c2017-02-24 12:36:50 +0000779 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000780 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800781 InterfaceBlock interfaceBlock;
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200782 recordInterfaceBlock(variable.variable().symbolType() != SymbolType::Empty
Olli Etuahofbb1c792018-01-19 16:26:59 +0200783 ? variable.getName().data()
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200784 : nullptr,
785 variable.getType(), &interfaceBlock);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800786
787 switch (qualifier)
Jiajia Qinbc585152017-06-23 15:42:17 +0800788 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800789 case EvqUniform:
790 mUniformBlocks->push_back(interfaceBlock);
791 break;
792 case EvqBuffer:
793 mShaderStorageBlocks->push_back(interfaceBlock);
794 break;
795 default:
796 UNREACHABLE();
Jiajia Qinbc585152017-06-23 15:42:17 +0800797 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000798 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000799 else
800 {
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +0200801 ASSERT(variable.variable().symbolType() != SymbolType::Empty);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000802 switch (qualifier)
803 {
804 case EvqAttribute:
805 case EvqVertexIn:
806 mAttribs->push_back(recordAttribute(variable));
807 break;
808 case EvqFragmentOut:
809 mOutputVariables->push_back(recordOutputVariable(variable));
810 break;
811 case EvqUniform:
812 mUniforms->push_back(recordUniform(variable));
813 break;
814 default:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800815 if (IsVaryingIn(qualifier))
816 {
817 mInputVaryings->push_back(recordVarying(variable));
818 }
819 else
820 {
821 ASSERT(IsVaryingOut(qualifier));
822 mOutputVaryings->push_back(recordVarying(variable));
823 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000824 break;
825 }
826 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000827 }
828
Olli Etuahoa55102c2017-02-24 12:36:50 +0000829 // None of the recorded variables can have initializers, so we don't need to traverse the
830 // declarators.
831 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000832}
Jamie Madill23a8a432014-07-09 13:27:42 -0400833
Jiawei Shaod8105a02017-08-08 09:54:36 +0800834// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
Jiawei Shaobd924af2017-11-16 15:28:04 +0800835// GL_EXT_shader_io_blocks.
Olli Etuahofbb1c792018-01-19 16:26:59 +0200836InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(
837 const ImmutableString &blockName) const
Jiawei Shaod8105a02017-08-08 09:54:36 +0800838{
839 InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
840 if (!namedBlock)
841 {
842 namedBlock = FindVariable(blockName, mShaderStorageBlocks);
843 }
844 return namedBlock;
845}
846
Olli Etuaho19515012017-06-26 18:00:17 +0300847bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
Jamie Madillb547ddf2014-08-25 16:20:46 -0400848{
849 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
850 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400851 // NOTE: we do not determine static use for individual blocks of an array
852 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
853 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400854
855 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
856 ASSERT(constantUnion);
857
Jiawei Shaod8105a02017-08-08 09:54:36 +0800858 InterfaceBlock *namedBlock = nullptr;
859
860 bool traverseIndexExpression = false;
861 TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
862 if (interfaceIndexingNode)
863 {
864 TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
865 ASSERT(interfaceNode);
866
867 const TType &interfaceType = interfaceNode->getType();
868 if (interfaceType.getQualifier() == EvqPerVertexIn)
869 {
870 namedBlock = recordGLInUsed(interfaceType);
871 ASSERT(namedBlock);
872
873 // We need to continue traversing to collect useful variables in the index
874 // expression of gl_in.
875 traverseIndexExpression = true;
876 }
877 }
878
Jamie Madilla6f267f2014-08-27 11:44:15 -0400879 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800880 if (!namedBlock)
Jiajia Qinbc585152017-06-23 15:42:17 +0800881 {
Olli Etuahobed35d72017-12-20 16:36:26 +0200882 namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
Jiajia Qinbc585152017-06-23 15:42:17 +0800883 }
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800884 ASSERT(namedBlock);
885 namedBlock->staticUse = true;
886 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
887 ASSERT(fieldIndex < namedBlock->fields.size());
888 namedBlock->fields[fieldIndex].staticUse = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800889
890 if (traverseIndexExpression)
891 {
892 ASSERT(interfaceIndexingNode);
893 interfaceIndexingNode->getRight()->traverse(this);
894 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400895 return false;
896 }
897
898 return true;
899}
900
Olli Etuaho19515012017-06-26 18:00:17 +0300901} // anonymous namespace
902
903void CollectVariables(TIntermBlock *root,
904 std::vector<Attribute> *attributes,
905 std::vector<OutputVariable> *outputVariables,
906 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800907 std::vector<Varying> *inputVaryings,
908 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800909 std::vector<InterfaceBlock> *uniformBlocks,
910 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800911 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300912 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300913 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300914 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800915 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300916 const TExtensionBehavior &extensionBehavior)
917{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800918 CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800919 outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800920 hashFunction, symbolTable, shaderVersion, shaderType,
921 extensionBehavior);
Olli Etuaho19515012017-06-26 18:00:17 +0300922 root->traverse(&collect);
923}
924
Olli Etuaho19515012017-06-26 18:00:17 +0300925} // namespace sh