blob: 7a8750b9f8fdf034f9a31cb76a88f43f9399eda0 [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>
Jamie Madilld7b1ab52016-12-12 14:42:19 -050059VarT *FindVariable(const TString &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 {
Jamie Madill23a8a432014-07-09 13:27:42 -040064 if ((*infoList)[ii].name.c_str() == 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
Jiajia Qin3a9090f2017-09-27 14:37:04 +080089ShaderVariable *FindVariableInInterfaceBlock(const TString &name,
90 const TInterfaceBlock *interfaceBlock,
91 std::vector<InterfaceBlock> *infoList)
92{
93 ASSERT(interfaceBlock);
Olli Etuahoae4dbf32017-12-08 20:49:00 +010094 ASSERT(interfaceBlock->name());
95 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;
100 return FindVariable(name, &namedBlock->fields);
101}
102
Olli Etuaho19515012017-06-26 18:00:17 +0300103// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
104// and interface blocks.
105class CollectVariablesTraverser : public TIntermTraverser
106{
107 public:
108 CollectVariablesTraverser(std::vector<Attribute> *attribs,
109 std::vector<OutputVariable> *outputVariables,
110 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800111 std::vector<Varying> *inputVaryings,
112 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800113 std::vector<InterfaceBlock> *uniformBlocks,
114 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800115 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300116 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300117 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300118 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800119 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300120 const TExtensionBehavior &extensionBehavior);
121
122 void visitSymbol(TIntermSymbol *symbol) override;
123 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
124 bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
125
126 private:
Olli Etuaho855d9642017-05-17 14:05:06 +0300127 std::string getMappedName(const TName &name) const;
128
Olli Etuaho19515012017-06-26 18:00:17 +0300129 void setCommonVariableProperties(const TType &type,
Olli Etuaho855d9642017-05-17 14:05:06 +0300130 const TName &name,
Olli Etuaho19515012017-06-26 18:00:17 +0300131 ShaderVariable *variableOut) const;
132
133 Attribute recordAttribute(const TIntermSymbol &variable) const;
134 OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
135 Varying recordVarying(const TIntermSymbol &variable) const;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200136 void recordInterfaceBlock(const TString &instanceName,
137 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800138 InterfaceBlock *interfaceBlock) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300139 Uniform recordUniform(const TIntermSymbol &variable) const;
140
141 void setBuiltInInfoFromSymbolTable(const char *name, ShaderVariable *info);
142
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800143 void recordBuiltInVaryingUsed(const char *name,
144 bool *addedFlag,
145 std::vector<Varying> *varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300146 void recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag);
147 void recordBuiltInAttributeUsed(const char *name, bool *addedFlag);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800148 InterfaceBlock *recordGLInUsed(const TType &glInType);
149 InterfaceBlock *findNamedInterfaceBlock(const TString &name) const;
Olli Etuaho19515012017-06-26 18:00:17 +0300150
151 std::vector<Attribute> *mAttribs;
152 std::vector<OutputVariable> *mOutputVariables;
153 std::vector<Uniform> *mUniforms;
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800154 std::vector<Varying> *mInputVaryings;
155 std::vector<Varying> *mOutputVaryings;
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800156 std::vector<InterfaceBlock> *mUniformBlocks;
157 std::vector<InterfaceBlock> *mShaderStorageBlocks;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800158 std::vector<InterfaceBlock> *mInBlocks;
Olli Etuaho19515012017-06-26 18:00:17 +0300159
160 std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
161
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800162 // Shader uniforms
Olli Etuaho19515012017-06-26 18:00:17 +0300163 bool mDepthRangeAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800164
165 // Vertex Shader builtins
166 bool mInstanceIDAdded;
167 bool mVertexIDAdded;
168 bool mPointSizeAdded;
169
170 // Vertex Shader and Geometry Shader builtins
171 bool mPositionAdded;
172
173 // Fragment Shader builtins
Olli Etuaho19515012017-06-26 18:00:17 +0300174 bool mPointCoordAdded;
175 bool mFrontFacingAdded;
176 bool mFragCoordAdded;
Olli Etuaho19515012017-06-26 18:00:17 +0300177 bool mLastFragDataAdded;
178 bool mFragColorAdded;
179 bool mFragDataAdded;
180 bool mFragDepthEXTAdded;
181 bool mFragDepthAdded;
182 bool mSecondaryFragColorEXTAdded;
183 bool mSecondaryFragDataEXTAdded;
184
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800185 // Geometry Shader builtins
Jiawei Shaod8105a02017-08-08 09:54:36 +0800186 bool mPerVertexInAdded;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800187 bool mPrimitiveIDInAdded;
188 bool mInvocationIDAdded;
189
190 // Geometry Shader and Fragment Shader builtins
191 bool mPrimitiveIDAdded;
192 bool mLayerAdded;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800193
Olli Etuaho19515012017-06-26 18:00:17 +0300194 ShHashFunction64 mHashFunction;
195
Olli Etuaho19515012017-06-26 18:00:17 +0300196 int mShaderVersion;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800197 GLenum mShaderType;
Olli Etuaho19515012017-06-26 18:00:17 +0300198 const TExtensionBehavior &mExtensionBehavior;
199};
200
201CollectVariablesTraverser::CollectVariablesTraverser(
202 std::vector<sh::Attribute> *attribs,
203 std::vector<sh::OutputVariable> *outputVariables,
204 std::vector<sh::Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800205 std::vector<sh::Varying> *inputVaryings,
206 std::vector<sh::Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800207 std::vector<sh::InterfaceBlock> *uniformBlocks,
208 std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800209 std::vector<sh::InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300210 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300211 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300212 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800213 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300214 const TExtensionBehavior &extensionBehavior)
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300215 : TIntermTraverser(true, false, false, symbolTable),
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300216 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400217 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000218 mUniforms(uniforms),
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800219 mInputVaryings(inputVaryings),
220 mOutputVaryings(outputVaryings),
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800221 mUniformBlocks(uniformBlocks),
222 mShaderStorageBlocks(shaderStorageBlocks),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800223 mInBlocks(inBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400224 mDepthRangeAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800225 mInstanceIDAdded(false),
226 mVertexIDAdded(false),
227 mPointSizeAdded(false),
228 mPositionAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400229 mPointCoordAdded(false),
230 mFrontFacingAdded(false),
231 mFragCoordAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100232 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300233 mFragColorAdded(false),
234 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300235 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300236 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300237 mSecondaryFragColorEXTAdded(false),
238 mSecondaryFragDataEXTAdded(false),
Jiawei Shaod8105a02017-08-08 09:54:36 +0800239 mPerVertexInAdded(false),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800240 mPrimitiveIDInAdded(false),
241 mInvocationIDAdded(false),
242 mPrimitiveIDAdded(false),
243 mLayerAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700244 mHashFunction(hashFunction),
Olli Etuaho19515012017-06-26 18:00:17 +0300245 mShaderVersion(shaderVersion),
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800246 mShaderType(shaderType),
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700247 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000248{
249}
250
Olli Etuaho855d9642017-05-17 14:05:06 +0300251std::string CollectVariablesTraverser::getMappedName(const TName &name) const
252{
253 return HashName(name, mHashFunction, nullptr).c_str();
254}
255
Olli Etuaho19515012017-06-26 18:00:17 +0300256void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
257 ShaderVariable *info)
258{
259 TVariable *symbolTableVar =
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300260 reinterpret_cast<TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
Olli Etuaho19515012017-06-26 18:00:17 +0300261 ASSERT(symbolTableVar);
262 const TType &type = symbolTableVar->getType();
263
264 info->name = name;
265 info->mappedName = name;
266 info->type = GLVariableType(type);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300267 info->precision = GLVariablePrecision(type);
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800268 if (auto *arraySizes = type.getArraySizes())
269 {
270 info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
271 }
Olli Etuaho19515012017-06-26 18:00:17 +0300272}
273
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800274void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name,
275 bool *addedFlag,
276 std::vector<Varying> *varyings)
Olli Etuaho19515012017-06-26 18:00:17 +0300277{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800278 ASSERT(varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300279 if (!(*addedFlag))
280 {
281 Varying info;
282 setBuiltInInfoFromSymbolTable(name, &info);
283 info.staticUse = true;
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300284 info.isInvariant = mSymbolTable->isVaryingInvariant(name);
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800285 varyings->push_back(info);
Olli Etuaho19515012017-06-26 18:00:17 +0300286 (*addedFlag) = true;
287 }
288}
289
290void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag)
291{
292 if (!(*addedFlag))
293 {
294 OutputVariable info;
295 setBuiltInInfoFromSymbolTable(name, &info);
296 info.staticUse = true;
297 mOutputVariables->push_back(info);
298 (*addedFlag) = true;
299 }
300}
301
302void CollectVariablesTraverser::recordBuiltInAttributeUsed(const char *name, bool *addedFlag)
303{
304 if (!(*addedFlag))
305 {
306 Attribute info;
307 setBuiltInInfoFromSymbolTable(name, &info);
308 info.staticUse = true;
309 info.location = -1;
310 mAttribs->push_back(info);
311 (*addedFlag) = true;
312 }
313}
314
Jiawei Shaod8105a02017-08-08 09:54:36 +0800315InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
316{
317 if (!mPerVertexInAdded)
318 {
319 ASSERT(glInType.getQualifier() == EvqPerVertexIn);
320 InterfaceBlock info;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200321 recordInterfaceBlock("gl_in", glInType, &info);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800322 info.staticUse = true;
323
324 mPerVertexInAdded = true;
325 mInBlocks->push_back(info);
326 return &mInBlocks->back();
327 }
328 else
329 {
330 return FindVariable("gl_PerVertex", mInBlocks);
331 }
332}
333
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400334// We want to check whether a uniform/varying is statically used
335// because we only count the used ones in packing computing.
336// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
337// toward varying counting if they are statically used in a fragment
338// shader.
Olli Etuaho19515012017-06-26 18:00:17 +0300339void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000340{
Yunchao He4f285442017-04-21 12:15:49 +0800341 ASSERT(symbol != nullptr);
Olli Etuaho34d20072017-07-18 20:07:18 +0300342
343 if (symbol->getName().isInternal())
344 {
345 // Internal variables are not collected.
346 return;
347 }
348
Yunchao Hed7297bf2017-04-19 15:27:10 +0800349 ShaderVariable *var = nullptr;
Olli Etuaho34d20072017-07-18 20:07:18 +0300350 const TString &symbolName = symbol->getName().getString();
Jamie Madill4667c452014-07-08 15:02:36 -0400351
Olli Etuahob8cb9392017-12-20 14:23:19 +0200352 // Check the qualifier from the variable, not from the symbol node. The node may have a
353 // different qualifier if it's the result of a folded ternary node.
354 TQualifier qualifier = symbol->variable().getType().getQualifier();
355
356 if (IsVaryingIn(qualifier))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400357 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800358 var = FindVariable(symbolName, mInputVaryings);
359 }
Olli Etuahob8cb9392017-12-20 14:23:19 +0200360 else if (IsVaryingOut(qualifier))
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800361 {
362 var = FindVariable(symbolName, mOutputVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400363 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400364 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
365 {
366 UNREACHABLE();
367 }
Jamie Madill55def582015-05-04 11:24:57 -0400368 else if (symbolName == "gl_DepthRange")
369 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200370 ASSERT(qualifier == EvqUniform);
Jamie Madill55def582015-05-04 11:24:57 -0400371
372 if (!mDepthRangeAdded)
373 {
374 Uniform info;
375 const char kName[] = "gl_DepthRange";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500376 info.name = kName;
377 info.mappedName = kName;
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400378 info.type = GL_NONE;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500379 info.precision = GL_NONE;
380 info.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400381
Olli Etuahoe7c28572017-10-23 16:29:33 +0300382 ShaderVariable nearInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400383 const char kNearName[] = "near";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500384 nearInfo.name = kNearName;
385 nearInfo.mappedName = kNearName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500386 nearInfo.precision = GL_HIGH_FLOAT;
387 nearInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400388
Olli Etuahoe7c28572017-10-23 16:29:33 +0300389 ShaderVariable farInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400390 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500391 farInfo.name = kFarName;
392 farInfo.mappedName = kFarName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500393 farInfo.precision = GL_HIGH_FLOAT;
394 farInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400395
Olli Etuahoe7c28572017-10-23 16:29:33 +0300396 ShaderVariable diffInfo(GL_FLOAT);
Jamie Madill55def582015-05-04 11:24:57 -0400397 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500398 diffInfo.name = kDiffName;
399 diffInfo.mappedName = kDiffName;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500400 diffInfo.precision = GL_HIGH_FLOAT;
401 diffInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400402
403 info.fields.push_back(nearInfo);
404 info.fields.push_back(farInfo);
405 info.fields.push_back(diffInfo);
406
407 mUniforms->push_back(info);
408 mDepthRangeAdded = true;
409 }
410 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400411 else
Jamie Madill4667c452014-07-08 15:02:36 -0400412 {
Olli Etuahob8cb9392017-12-20 14:23:19 +0200413 switch (qualifier)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400414 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500415 case EvqAttribute:
416 case EvqVertexIn:
417 var = FindVariable(symbolName, mAttribs);
418 break;
419 case EvqFragmentOut:
420 var = FindVariable(symbolName, mOutputVariables);
421 break;
422 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400423 {
424 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
425 if (interfaceBlock)
426 {
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800427 var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400428 }
429 else
430 {
431 var = FindVariable(symbolName, mUniforms);
432 }
433
434 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400435 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400436 }
Jamie Madill4667c452014-07-08 15:02:36 -0400437 break;
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800438 case EvqBuffer:
439 {
440 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
441 var =
442 FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
443 }
444 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500445 case EvqFragCoord:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800446 recordBuiltInVaryingUsed("gl_FragCoord", &mFragCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500447 return;
448 case EvqFrontFacing:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800449 recordBuiltInVaryingUsed("gl_FrontFacing", &mFrontFacingAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500450 return;
451 case EvqPointCoord:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800452 recordBuiltInVaryingUsed("gl_PointCoord", &mPointCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500453 return;
454 case EvqInstanceID:
Martin Radev115fc552017-07-05 17:11:06 +0300455 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
456 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
457 // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
458 // which makes it necessary to populate the type information explicitly instead of
459 // extracting it from the symbol table.
460 if (!mInstanceIDAdded)
461 {
462 Attribute info;
463 const char kName[] = "gl_InstanceID";
464 info.name = kName;
465 info.mappedName = kName;
466 info.type = GL_INT;
Martin Radev115fc552017-07-05 17:11:06 +0300467 info.precision = GL_HIGH_INT; // Defined by spec.
468 info.staticUse = true;
469 info.location = -1;
470 mAttribs->push_back(info);
471 mInstanceIDAdded = true;
472 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500473 return;
474 case EvqVertexID:
Olli Etuaho19515012017-06-26 18:00:17 +0300475 recordBuiltInAttributeUsed("gl_VertexID", &mVertexIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500476 return;
477 case EvqPosition:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800478 recordBuiltInVaryingUsed("gl_Position", &mPositionAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500479 return;
480 case EvqPointSize:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800481 recordBuiltInVaryingUsed("gl_PointSize", &mPointSizeAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500482 return;
483 case EvqLastFragData:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800484 recordBuiltInVaryingUsed("gl_LastFragData", &mLastFragDataAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500485 return;
486 case EvqFragColor:
Olli Etuaho19515012017-06-26 18:00:17 +0300487 recordBuiltInFragmentOutputUsed("gl_FragColor", &mFragColorAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500488 return;
489 case EvqFragData:
490 if (!mFragDataAdded)
491 {
492 OutputVariable info;
Olli Etuaho19515012017-06-26 18:00:17 +0300493 setBuiltInInfoFromSymbolTable("gl_FragData", &info);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300494 if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500495 {
Olli Etuaho465835d2017-09-26 13:34:10 +0300496 ASSERT(info.arraySizes.size() == 1u);
497 info.arraySizes.back() = 1u;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500498 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500499 info.staticUse = true;
500 mOutputVariables->push_back(info);
501 mFragDataAdded = true;
502 }
503 return;
504 case EvqFragDepthEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300505 recordBuiltInFragmentOutputUsed("gl_FragDepthEXT", &mFragDepthEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500506 return;
507 case EvqFragDepth:
Olli Etuaho19515012017-06-26 18:00:17 +0300508 recordBuiltInFragmentOutputUsed("gl_FragDepth", &mFragDepthAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500509 return;
510 case EvqSecondaryFragColorEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300511 recordBuiltInFragmentOutputUsed("gl_SecondaryFragColorEXT",
512 &mSecondaryFragColorEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500513 return;
514 case EvqSecondaryFragDataEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300515 recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT",
516 &mSecondaryFragDataEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500517 return;
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800518 case EvqInvocationID:
519 recordBuiltInVaryingUsed("gl_InvocationID", &mInvocationIDAdded, mInputVaryings);
520 break;
521 case EvqPrimitiveIDIn:
522 recordBuiltInVaryingUsed("gl_PrimitiveIDIn", &mPrimitiveIDInAdded, mInputVaryings);
523 break;
524 case EvqPrimitiveID:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800525 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800526 {
527 recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mOutputVaryings);
528 }
529 else
530 {
531 ASSERT(mShaderType == GL_FRAGMENT_SHADER);
532 recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mInputVaryings);
533 }
534 break;
535 case EvqLayer:
Jiawei Shaobd924af2017-11-16 15:28:04 +0800536 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800537 {
538 recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mOutputVaryings);
539 }
540 else if (mShaderType == GL_FRAGMENT_SHADER)
541 {
542 recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mInputVaryings);
543 }
544 else
545 {
546 ASSERT(mShaderType == GL_VERTEX_SHADER &&
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300547 IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800548 }
549 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500550 default:
551 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400552 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400553 }
554 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400555 {
Olli Etuaho06a06f52017-07-12 12:22:15 +0300556 MarkStaticallyUsed(var);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400557 }
558}
559
Olli Etuaho19515012017-06-26 18:00:17 +0300560void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
Olli Etuaho855d9642017-05-17 14:05:06 +0300561 const TName &name,
Olli Etuaho19515012017-06-26 18:00:17 +0300562 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400563{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000564 ASSERT(variableOut);
565
566 const TStructure *structure = type.getStruct();
567
568 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500569 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000570 variableOut->type = GLVariableType(type);
571 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500572 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000573 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400574 {
Jamie Madillf00f7ff2017-08-31 14:39:15 -0400575 // Structures use a NONE type that isn't exposed outside ANGLE.
576 variableOut->type = GL_NONE;
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100577 if (structure->symbolType() != SymbolType::Empty)
578 {
579 variableOut->structName = structure->name()->c_str();
580 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000581
582 const TFieldList &fields = structure->fields();
583
Olli Etuaho378c3a52017-12-04 11:32:13 +0200584 for (const TField *field : fields)
Olli Etuahoa55102c2017-02-24 12:36:50 +0000585 {
586 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
587 // ShaderVariable objects.
588 ShaderVariable fieldVariable;
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100589 setCommonVariableProperties(*field->type(), TName(&field->name()), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000590 variableOut->fields.push_back(fieldVariable);
591 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400592 }
Olli Etuaho855d9642017-05-17 14:05:06 +0300593 variableOut->name = name.getString().c_str();
594 variableOut->mappedName = getMappedName(name);
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300595
Kai Ninomiya57ea5332017-11-22 14:04:48 -0800596 if (auto *arraySizes = type.getArraySizes())
597 {
598 variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
599 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000600}
Jamie Madill23a8a432014-07-09 13:27:42 -0400601
Olli Etuaho19515012017-06-26 18:00:17 +0300602Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400603{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000604 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400605 ASSERT(!type.getStruct());
606
Jamie Madilla2fbb842014-09-03 09:40:47 -0400607 Attribute attribute;
Olli Etuaho855d9642017-05-17 14:05:06 +0300608 setCommonVariableProperties(type, variable.getName(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400609
Olli Etuahoa55102c2017-02-24 12:36:50 +0000610 attribute.location = type.getLayoutQualifier().location;
611 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400612}
613
Olli Etuaho19515012017-06-26 18:00:17 +0300614OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400615{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000616 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400617 ASSERT(!type.getStruct());
618
Olli Etuahoa55102c2017-02-24 12:36:50 +0000619 OutputVariable outputVariable;
Olli Etuaho855d9642017-05-17 14:05:06 +0300620 setCommonVariableProperties(type, variable.getName(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400621
Olli Etuahoa55102c2017-02-24 12:36:50 +0000622 outputVariable.location = type.getLayoutQualifier().location;
623 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400624}
625
Olli Etuaho19515012017-06-26 18:00:17 +0300626Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400627{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000628 const TType &type = variable.getType();
629
630 Varying varying;
Olli Etuaho855d9642017-05-17 14:05:06 +0300631 setCommonVariableProperties(type, variable.getName(), &varying);
Jiawei Shao4cc89e22017-08-31 14:25:54 +0800632 varying.location = type.getLayoutQualifier().location;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000633
634 switch (type.getQualifier())
635 {
636 case EvqVaryingIn:
637 case EvqVaryingOut:
638 case EvqVertexOut:
639 case EvqSmoothOut:
640 case EvqFlatOut:
641 case EvqCentroidOut:
Jiawei Shao8e4b3552017-08-30 14:20:58 +0800642 case EvqGeometryOut:
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300643 if (mSymbolTable->isVaryingInvariant(std::string(variable.getSymbol().c_str())) ||
Olli Etuahoa55102c2017-02-24 12:36:50 +0000644 type.isInvariant())
645 {
646 varying.isInvariant = true;
647 }
648 break;
649 default:
650 break;
651 }
652
653 varying.interpolation = GetInterpolationType(type.getQualifier());
654 return varying;
655}
656
Jiawei Shaobd924af2017-11-16 15:28:04 +0800657// TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200658void CollectVariablesTraverser::recordInterfaceBlock(const TString &instanceName,
659 const TType &interfaceBlockType,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800660 InterfaceBlock *interfaceBlock) const
Olli Etuahoa55102c2017-02-24 12:36:50 +0000661{
Jiawei Shaod8105a02017-08-08 09:54:36 +0800662 ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
663 ASSERT(interfaceBlock);
664
665 const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400666 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400667
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100668 interfaceBlock->name = blockType->name()->c_str();
Olli Etuaho855d9642017-05-17 14:05:06 +0300669 interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200670 interfaceBlock->instanceName = instanceName.c_str();
Olli Etuaho96f6adf2017-08-16 11:18:54 +0300671 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
672 interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800673
674 interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
675 if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
676 interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
677 {
Olli Etuaho3de27032017-11-30 12:16:47 +0200678 // TODO(oetuaho): Remove setting isRowMajorLayout.
679 interfaceBlock->isRowMajorLayout = false;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800680 interfaceBlock->binding = blockType->blockBinding();
681 interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
682 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400683
Jamie Madilla6f267f2014-08-27 11:44:15 -0400684 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500685 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400686 {
Jamie Madill39046162016-02-08 15:05:17 -0500687 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400688
Olli Etuahoa55102c2017-02-24 12:36:50 +0000689 InterfaceBlockField fieldVariable;
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100690 setCommonVariableProperties(fieldType, TName(&field->name()), &fieldVariable);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000691 fieldVariable.isRowMajorLayout =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500692 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800693 interfaceBlock->fields.push_back(fieldVariable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400694 }
Jamie Madilld5512cd2014-07-10 17:50:08 -0400695}
696
Olli Etuaho19515012017-06-26 18:00:17 +0300697Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400698{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000699 Uniform uniform;
Olli Etuaho855d9642017-05-17 14:05:06 +0300700 setCommonVariableProperties(variable.getType(), variable.getName(), &uniform);
Olli Etuaho78ed6cd2017-08-09 16:19:00 +0300701 uniform.binding = variable.getType().getLayoutQualifier().binding;
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000702 uniform.location = variable.getType().getLayoutQualifier().location;
jchen104cdac9e2017-05-08 11:01:20 +0800703 uniform.offset = variable.getType().getLayoutQualifier().offset;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800704 uniform.readonly = variable.getType().getMemoryQualifier().readonly;
705 uniform.writeonly = variable.getType().getMemoryQualifier().writeonly;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000706 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000707}
708
Olli Etuaho19515012017-06-26 18:00:17 +0300709bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000710{
Olli Etuaho13389b62016-10-16 11:48:18 +0100711 const TIntermSequence &sequence = *(node->getSequence());
712 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000713
Olli Etuaho13389b62016-10-16 11:48:18 +0100714 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
715 TQualifier qualifier = typedNode.getQualifier();
716
Olli Etuahoa55102c2017-02-24 12:36:50 +0000717 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
718 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
719 IsVarying(qualifier);
720
721 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000722 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000723 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100724 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000725
726 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100727 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000728 // The only case in which the sequence will not contain a TIntermSymbol node is
729 // initialization. It will contain a TInterBinary node in that case. Since attributes,
730 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
731 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
732 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
Olli Etuaho34d20072017-07-18 20:07:18 +0300733 if (variable.getName().isInternal())
734 {
735 // Internal variables are not collected.
736 continue;
737 }
738
Jiawei Shaobd924af2017-11-16 15:28:04 +0800739 // TODO(jiawei.shao@intel.com): implement GL_EXT_shader_io_blocks.
Olli Etuahoa55102c2017-02-24 12:36:50 +0000740 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000741 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800742 InterfaceBlock interfaceBlock;
Olli Etuaho12a18ad2017-12-01 16:59:47 +0200743 recordInterfaceBlock(variable.getSymbol(), variable.getType(), &interfaceBlock);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800744
745 switch (qualifier)
Jiajia Qinbc585152017-06-23 15:42:17 +0800746 {
Jiawei Shaod8105a02017-08-08 09:54:36 +0800747 case EvqUniform:
748 mUniformBlocks->push_back(interfaceBlock);
749 break;
750 case EvqBuffer:
751 mShaderStorageBlocks->push_back(interfaceBlock);
752 break;
753 default:
754 UNREACHABLE();
Jiajia Qinbc585152017-06-23 15:42:17 +0800755 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000756 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000757 else
758 {
759 switch (qualifier)
760 {
761 case EvqAttribute:
762 case EvqVertexIn:
763 mAttribs->push_back(recordAttribute(variable));
764 break;
765 case EvqFragmentOut:
766 mOutputVariables->push_back(recordOutputVariable(variable));
767 break;
768 case EvqUniform:
769 mUniforms->push_back(recordUniform(variable));
770 break;
771 default:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800772 if (IsVaryingIn(qualifier))
773 {
774 mInputVaryings->push_back(recordVarying(variable));
775 }
776 else
777 {
778 ASSERT(IsVaryingOut(qualifier));
779 mOutputVaryings->push_back(recordVarying(variable));
780 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000781 break;
782 }
783 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000784 }
785
Olli Etuahoa55102c2017-02-24 12:36:50 +0000786 // None of the recorded variables can have initializers, so we don't need to traverse the
787 // declarators.
788 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000789}
Jamie Madill23a8a432014-07-09 13:27:42 -0400790
Jiawei Shaod8105a02017-08-08 09:54:36 +0800791// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
Jiawei Shaobd924af2017-11-16 15:28:04 +0800792// GL_EXT_shader_io_blocks.
Jiawei Shaod8105a02017-08-08 09:54:36 +0800793InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(const TString &blockName) const
794{
795 InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
796 if (!namedBlock)
797 {
798 namedBlock = FindVariable(blockName, mShaderStorageBlocks);
799 }
800 return namedBlock;
801}
802
Olli Etuaho19515012017-06-26 18:00:17 +0300803bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
Jamie Madillb547ddf2014-08-25 16:20:46 -0400804{
805 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
806 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400807 // NOTE: we do not determine static use for individual blocks of an array
808 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
809 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400810
811 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
812 ASSERT(constantUnion);
813
Jiawei Shaod8105a02017-08-08 09:54:36 +0800814 InterfaceBlock *namedBlock = nullptr;
815
816 bool traverseIndexExpression = false;
817 TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
818 if (interfaceIndexingNode)
819 {
820 TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
821 ASSERT(interfaceNode);
822
823 const TType &interfaceType = interfaceNode->getType();
824 if (interfaceType.getQualifier() == EvqPerVertexIn)
825 {
826 namedBlock = recordGLInUsed(interfaceType);
827 ASSERT(namedBlock);
828
829 // We need to continue traversing to collect useful variables in the index
830 // expression of gl_in.
831 traverseIndexExpression = true;
832 }
833 }
834
Jamie Madilla6f267f2014-08-27 11:44:15 -0400835 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800836 if (!namedBlock)
Jiajia Qinbc585152017-06-23 15:42:17 +0800837 {
Olli Etuahoae4dbf32017-12-08 20:49:00 +0100838 namedBlock = findNamedInterfaceBlock(*interfaceBlock->name());
Jiajia Qinbc585152017-06-23 15:42:17 +0800839 }
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800840 ASSERT(namedBlock);
841 namedBlock->staticUse = true;
842 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
843 ASSERT(fieldIndex < namedBlock->fields.size());
844 namedBlock->fields[fieldIndex].staticUse = true;
Jiawei Shaod8105a02017-08-08 09:54:36 +0800845
846 if (traverseIndexExpression)
847 {
848 ASSERT(interfaceIndexingNode);
849 interfaceIndexingNode->getRight()->traverse(this);
850 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400851 return false;
852 }
853
854 return true;
855}
856
Olli Etuaho19515012017-06-26 18:00:17 +0300857} // anonymous namespace
858
859void CollectVariables(TIntermBlock *root,
860 std::vector<Attribute> *attributes,
861 std::vector<OutputVariable> *outputVariables,
862 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800863 std::vector<Varying> *inputVaryings,
864 std::vector<Varying> *outputVaryings,
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800865 std::vector<InterfaceBlock> *uniformBlocks,
866 std::vector<InterfaceBlock> *shaderStorageBlocks,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800867 std::vector<InterfaceBlock> *inBlocks,
Olli Etuaho19515012017-06-26 18:00:17 +0300868 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300869 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300870 int shaderVersion,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800871 GLenum shaderType,
Olli Etuaho19515012017-06-26 18:00:17 +0300872 const TExtensionBehavior &extensionBehavior)
873{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800874 CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
Jiawei Shaod8105a02017-08-08 09:54:36 +0800875 outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800876 hashFunction, symbolTable, shaderVersion, shaderType,
877 extensionBehavior);
Olli Etuaho19515012017-06-26 18:00:17 +0300878 root->traverse(&collect);
879}
880
Olli Etuaho19515012017-06-26 18:00:17 +0300881} // namespace sh