blob: 06e9d0bdabf020b996979c463db601a3245c06e5 [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//
6
Geoff Lang17732822013-08-29 13:46:49 -04007#include "compiler/translator/VariableInfo.h"
Olli Etuaho19515012017-06-26 18:00:17 +03008
9#include "angle_gl.h"
Jamie Madilld5512cd2014-07-10 17:50:08 -040010#include "common/utilities.h"
Olli Etuahocccf2b02017-07-05 14:50:54 +030011#include "compiler/translator/HashNames.h"
12#include "compiler/translator/IntermTraverse.h"
Olli Etuaho19515012017-06-26 18:00:17 +030013#include "compiler/translator/SymbolTable.h"
14#include "compiler/translator/util.h"
alokp@chromium.org07620a52010-09-23 17:53:56 +000015
Jamie Madilla2fbb842014-09-03 09:40:47 -040016namespace sh
17{
18
Jamie Madill54ad4f82014-09-03 09:40:46 -040019namespace
20{
Zhenyao Mod2d340b2013-09-23 14:57:05 -040021
Jamie Madilla2fbb842014-09-03 09:40:47 -040022BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
Jamie Madill54ad4f82014-09-03 09:40:46 -040023{
24 switch (blockStorage)
25 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -050026 case EbsPacked:
27 return BLOCKLAYOUT_PACKED;
28 case EbsShared:
29 return BLOCKLAYOUT_SHARED;
30 case EbsStd140:
31 return BLOCKLAYOUT_STANDARD;
32 default:
33 UNREACHABLE();
34 return BLOCKLAYOUT_SHARED;
Jamie Madill54ad4f82014-09-03 09:40:46 -040035 }
36}
37
Jamie Madilla2fbb842014-09-03 09:40:47 -040038void ExpandUserDefinedVariable(const ShaderVariable &variable,
Jamie Madill54ad4f82014-09-03 09:40:46 -040039 const std::string &name,
40 const std::string &mappedName,
41 bool markStaticUse,
Jamie Madilla2fbb842014-09-03 09:40:47 -040042 std::vector<ShaderVariable> *expanded)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000043{
Jamie Madill23a8a432014-07-09 13:27:42 -040044 ASSERT(variable.isStruct());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000045
Jamie Madilla2fbb842014-09-03 09:40:47 -040046 const std::vector<ShaderVariable> &fields = variable.fields;
Jamie Madill23a8a432014-07-09 13:27:42 -040047
48 for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
Jamie Madill4667c452014-07-08 15:02:36 -040049 {
Jamie Madilla2fbb842014-09-03 09:40:47 -040050 const ShaderVariable &field = fields[fieldIndex];
Jamie Madilld7b1ab52016-12-12 14:42:19 -050051 ExpandVariable(field, name + "." + field.name, mappedName + "." + field.mappedName,
52 markStaticUse, expanded);
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +000053 }
54}
55
Jamie Madilla718c1e2014-07-02 15:31:22 -040056template <class VarT>
Jamie Madilld7b1ab52016-12-12 14:42:19 -050057VarT *FindVariable(const TString &name, std::vector<VarT> *infoList)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040058{
59 // TODO(zmo): optimize this function.
Jamie Madilla718c1e2014-07-02 15:31:22 -040060 for (size_t ii = 0; ii < infoList->size(); ++ii)
Zhenyao Mod2d340b2013-09-23 14:57:05 -040061 {
Jamie Madill23a8a432014-07-09 13:27:42 -040062 if ((*infoList)[ii].name.c_str() == name)
Jamie Madilla718c1e2014-07-02 15:31:22 -040063 return &((*infoList)[ii]);
Zhenyao Mod2d340b2013-09-23 14:57:05 -040064 }
Jamie Madilld5512cd2014-07-10 17:50:08 -040065
Yunchao Hef81ce4a2017-04-24 10:49:17 +080066 return nullptr;
Zhenyao Mod2d340b2013-09-23 14:57:05 -040067}
Jamie Madill54ad4f82014-09-03 09:40:46 -040068
Olli Etuaho06a06f52017-07-12 12:22:15 +030069// Note that this shouldn't be called for interface blocks - static use information is collected for
70// individual fields in case of interface blocks.
71void MarkStaticallyUsed(ShaderVariable *variable)
72{
73 if (!variable->staticUse)
74 {
75 if (variable->isStruct())
76 {
77 // Conservatively assume all fields are statically used as well.
78 for (auto &field : variable->fields)
79 {
80 MarkStaticallyUsed(&field);
81 }
82 }
83 variable->staticUse = true;
84 }
85}
86
Olli Etuaho19515012017-06-26 18:00:17 +030087// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
88// and interface blocks.
89class CollectVariablesTraverser : public TIntermTraverser
90{
91 public:
92 CollectVariablesTraverser(std::vector<Attribute> *attribs,
93 std::vector<OutputVariable> *outputVariables,
94 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +080095 std::vector<Varying> *inputVaryings,
96 std::vector<Varying> *outputVaryings,
Olli Etuaho19515012017-06-26 18:00:17 +030097 std::vector<InterfaceBlock> *interfaceBlocks,
98 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +030099 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300100 int shaderVersion,
101 const TExtensionBehavior &extensionBehavior);
102
103 void visitSymbol(TIntermSymbol *symbol) override;
104 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
105 bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
106
107 private:
108 void setCommonVariableProperties(const TType &type,
109 const TString &name,
110 ShaderVariable *variableOut) const;
111
112 Attribute recordAttribute(const TIntermSymbol &variable) const;
113 OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
114 Varying recordVarying(const TIntermSymbol &variable) const;
115 InterfaceBlock recordInterfaceBlock(const TIntermSymbol &variable) const;
116 Uniform recordUniform(const TIntermSymbol &variable) const;
117
118 void setBuiltInInfoFromSymbolTable(const char *name, ShaderVariable *info);
119
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800120 void recordBuiltInVaryingUsed(const char *name,
121 bool *addedFlag,
122 std::vector<Varying> *varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300123 void recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag);
124 void recordBuiltInAttributeUsed(const char *name, bool *addedFlag);
125
126 std::vector<Attribute> *mAttribs;
127 std::vector<OutputVariable> *mOutputVariables;
128 std::vector<Uniform> *mUniforms;
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800129 std::vector<Varying> *mInputVaryings;
130 std::vector<Varying> *mOutputVaryings;
Olli Etuaho19515012017-06-26 18:00:17 +0300131 std::vector<InterfaceBlock> *mInterfaceBlocks;
132
133 std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
134
135 bool mDepthRangeAdded;
136 bool mPointCoordAdded;
137 bool mFrontFacingAdded;
138 bool mFragCoordAdded;
139
140 bool mInstanceIDAdded;
141 bool mVertexIDAdded;
142 bool mPositionAdded;
143 bool mPointSizeAdded;
144 bool mLastFragDataAdded;
145 bool mFragColorAdded;
146 bool mFragDataAdded;
147 bool mFragDepthEXTAdded;
148 bool mFragDepthAdded;
149 bool mSecondaryFragColorEXTAdded;
150 bool mSecondaryFragDataEXTAdded;
151
152 ShHashFunction64 mHashFunction;
153
Olli Etuaho19515012017-06-26 18:00:17 +0300154 int mShaderVersion;
155 const TExtensionBehavior &mExtensionBehavior;
156};
157
158CollectVariablesTraverser::CollectVariablesTraverser(
159 std::vector<sh::Attribute> *attribs,
160 std::vector<sh::OutputVariable> *outputVariables,
161 std::vector<sh::Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800162 std::vector<sh::Varying> *inputVaryings,
163 std::vector<sh::Varying> *outputVaryings,
Olli Etuaho19515012017-06-26 18:00:17 +0300164 std::vector<sh::InterfaceBlock> *interfaceBlocks,
165 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300166 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300167 int shaderVersion,
168 const TExtensionBehavior &extensionBehavior)
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300169 : TIntermTraverser(true, false, false, symbolTable),
Olli Etuaho3d0d9a42015-06-01 12:16:36 +0300170 mAttribs(attribs),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400171 mOutputVariables(outputVariables),
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000172 mUniforms(uniforms),
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800173 mInputVaryings(inputVaryings),
174 mOutputVaryings(outputVaryings),
Jamie Madilld5512cd2014-07-10 17:50:08 -0400175 mInterfaceBlocks(interfaceBlocks),
Jamie Madill55def582015-05-04 11:24:57 -0400176 mDepthRangeAdded(false),
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400177 mPointCoordAdded(false),
178 mFrontFacingAdded(false),
179 mFragCoordAdded(false),
Gregoire Payen de La Garanderieb3dced22015-01-12 14:54:55 +0000180 mInstanceIDAdded(false),
Corentin Wallezb076add2016-01-11 16:45:46 -0500181 mVertexIDAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700182 mPositionAdded(false),
183 mPointSizeAdded(false),
Erik Dahlströmea7a2122014-11-17 16:15:57 +0100184 mLastFragDataAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300185 mFragColorAdded(false),
186 mFragDataAdded(false),
Kimmo Kinnunen5f0246c2015-07-22 10:30:35 +0300187 mFragDepthEXTAdded(false),
Kimmo Kinnunen0932df62015-07-21 14:35:11 +0300188 mFragDepthAdded(false),
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300189 mSecondaryFragColorEXTAdded(false),
190 mSecondaryFragDataEXTAdded(false),
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700191 mHashFunction(hashFunction),
Olli Etuaho19515012017-06-26 18:00:17 +0300192 mShaderVersion(shaderVersion),
Zhenyao Mof178d0b2016-07-23 06:59:00 -0700193 mExtensionBehavior(extensionBehavior)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000194{
195}
196
Olli Etuaho19515012017-06-26 18:00:17 +0300197void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
198 ShaderVariable *info)
199{
200 TVariable *symbolTableVar =
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300201 reinterpret_cast<TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
Olli Etuaho19515012017-06-26 18:00:17 +0300202 ASSERT(symbolTableVar);
203 const TType &type = symbolTableVar->getType();
204
205 info->name = name;
206 info->mappedName = name;
207 info->type = GLVariableType(type);
208 info->arraySize = type.isArray() ? type.getArraySize() : 0;
209 info->precision = GLVariablePrecision(type);
210}
211
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800212void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name,
213 bool *addedFlag,
214 std::vector<Varying> *varyings)
Olli Etuaho19515012017-06-26 18:00:17 +0300215{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800216 ASSERT(varyings);
Olli Etuaho19515012017-06-26 18:00:17 +0300217 if (!(*addedFlag))
218 {
219 Varying info;
220 setBuiltInInfoFromSymbolTable(name, &info);
221 info.staticUse = true;
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300222 info.isInvariant = mSymbolTable->isVaryingInvariant(name);
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800223 varyings->push_back(info);
Olli Etuaho19515012017-06-26 18:00:17 +0300224 (*addedFlag) = true;
225 }
226}
227
228void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag)
229{
230 if (!(*addedFlag))
231 {
232 OutputVariable info;
233 setBuiltInInfoFromSymbolTable(name, &info);
234 info.staticUse = true;
235 mOutputVariables->push_back(info);
236 (*addedFlag) = true;
237 }
238}
239
240void CollectVariablesTraverser::recordBuiltInAttributeUsed(const char *name, bool *addedFlag)
241{
242 if (!(*addedFlag))
243 {
244 Attribute info;
245 setBuiltInInfoFromSymbolTable(name, &info);
246 info.staticUse = true;
247 info.location = -1;
248 mAttribs->push_back(info);
249 (*addedFlag) = true;
250 }
251}
252
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400253// We want to check whether a uniform/varying is statically used
254// because we only count the used ones in packing computing.
255// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
256// toward varying counting if they are statically used in a fragment
257// shader.
Olli Etuaho19515012017-06-26 18:00:17 +0300258void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
alokp@chromium.org07620a52010-09-23 17:53:56 +0000259{
Yunchao He4f285442017-04-21 12:15:49 +0800260 ASSERT(symbol != nullptr);
Olli Etuaho34d20072017-07-18 20:07:18 +0300261
262 if (symbol->getName().isInternal())
263 {
264 // Internal variables are not collected.
265 return;
266 }
267
Yunchao Hed7297bf2017-04-19 15:27:10 +0800268 ShaderVariable *var = nullptr;
Olli Etuaho34d20072017-07-18 20:07:18 +0300269 const TString &symbolName = symbol->getName().getString();
Jamie Madill4667c452014-07-08 15:02:36 -0400270
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800271 if (IsVaryingIn(symbol->getQualifier()))
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400272 {
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800273 var = FindVariable(symbolName, mInputVaryings);
274 }
275 else if (IsVaryingOut(symbol->getQualifier()))
276 {
277 var = FindVariable(symbolName, mOutputVaryings);
Jamie Madill4667c452014-07-08 15:02:36 -0400278 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400279 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
280 {
281 UNREACHABLE();
282 }
Jamie Madill55def582015-05-04 11:24:57 -0400283 else if (symbolName == "gl_DepthRange")
284 {
285 ASSERT(symbol->getQualifier() == EvqUniform);
286
287 if (!mDepthRangeAdded)
288 {
289 Uniform info;
290 const char kName[] = "gl_DepthRange";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500291 info.name = kName;
292 info.mappedName = kName;
293 info.type = GL_STRUCT_ANGLEX;
294 info.arraySize = 0;
295 info.precision = GL_NONE;
296 info.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400297
298 ShaderVariable nearInfo;
299 const char kNearName[] = "near";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500300 nearInfo.name = kNearName;
301 nearInfo.mappedName = kNearName;
302 nearInfo.type = GL_FLOAT;
303 nearInfo.arraySize = 0;
304 nearInfo.precision = GL_HIGH_FLOAT;
305 nearInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400306
307 ShaderVariable farInfo;
308 const char kFarName[] = "far";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500309 farInfo.name = kFarName;
310 farInfo.mappedName = kFarName;
311 farInfo.type = GL_FLOAT;
312 farInfo.arraySize = 0;
313 farInfo.precision = GL_HIGH_FLOAT;
314 farInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400315
316 ShaderVariable diffInfo;
317 const char kDiffName[] = "diff";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500318 diffInfo.name = kDiffName;
319 diffInfo.mappedName = kDiffName;
320 diffInfo.type = GL_FLOAT;
321 diffInfo.arraySize = 0;
322 diffInfo.precision = GL_HIGH_FLOAT;
323 diffInfo.staticUse = true;
Jamie Madill55def582015-05-04 11:24:57 -0400324
325 info.fields.push_back(nearInfo);
326 info.fields.push_back(farInfo);
327 info.fields.push_back(diffInfo);
328
329 mUniforms->push_back(info);
330 mDepthRangeAdded = true;
331 }
332 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400333 else
Jamie Madill4667c452014-07-08 15:02:36 -0400334 {
335 switch (symbol->getQualifier())
Jamie Madilla718c1e2014-07-02 15:31:22 -0400336 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500337 case EvqAttribute:
338 case EvqVertexIn:
339 var = FindVariable(symbolName, mAttribs);
340 break;
341 case EvqFragmentOut:
342 var = FindVariable(symbolName, mOutputVariables);
343 break;
344 case EvqUniform:
Jamie Madilld5512cd2014-07-10 17:50:08 -0400345 {
346 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
347 if (interfaceBlock)
348 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500349 InterfaceBlock *namedBlock =
350 FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400351 ASSERT(namedBlock);
352 var = FindVariable(symbolName, &namedBlock->fields);
353
354 // Set static use on the parent interface block here
355 namedBlock->staticUse = true;
356 }
357 else
358 {
359 var = FindVariable(symbolName, mUniforms);
360 }
361
362 // It's an internal error to reference an undefined user uniform
Jamie Madill55def582015-05-04 11:24:57 -0400363 ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400364 }
Jamie Madill4667c452014-07-08 15:02:36 -0400365 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500366 case EvqFragCoord:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800367 recordBuiltInVaryingUsed("gl_FragCoord", &mFragCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500368 return;
369 case EvqFrontFacing:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800370 recordBuiltInVaryingUsed("gl_FrontFacing", &mFrontFacingAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500371 return;
372 case EvqPointCoord:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800373 recordBuiltInVaryingUsed("gl_PointCoord", &mPointCoordAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500374 return;
375 case EvqInstanceID:
Martin Radev115fc552017-07-05 17:11:06 +0300376 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
377 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
378 // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
379 // which makes it necessary to populate the type information explicitly instead of
380 // extracting it from the symbol table.
381 if (!mInstanceIDAdded)
382 {
383 Attribute info;
384 const char kName[] = "gl_InstanceID";
385 info.name = kName;
386 info.mappedName = kName;
387 info.type = GL_INT;
388 info.arraySize = 0;
389 info.precision = GL_HIGH_INT; // Defined by spec.
390 info.staticUse = true;
391 info.location = -1;
392 mAttribs->push_back(info);
393 mInstanceIDAdded = true;
394 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500395 return;
396 case EvqVertexID:
Olli Etuaho19515012017-06-26 18:00:17 +0300397 recordBuiltInAttributeUsed("gl_VertexID", &mVertexIDAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500398 return;
399 case EvqPosition:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800400 recordBuiltInVaryingUsed("gl_Position", &mPositionAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500401 return;
402 case EvqPointSize:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800403 recordBuiltInVaryingUsed("gl_PointSize", &mPointSizeAdded, mOutputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500404 return;
405 case EvqLastFragData:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800406 recordBuiltInVaryingUsed("gl_LastFragData", &mLastFragDataAdded, mInputVaryings);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500407 return;
408 case EvqFragColor:
Olli Etuaho19515012017-06-26 18:00:17 +0300409 recordBuiltInFragmentOutputUsed("gl_FragColor", &mFragColorAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500410 return;
411 case EvqFragData:
412 if (!mFragDataAdded)
413 {
414 OutputVariable info;
Olli Etuaho19515012017-06-26 18:00:17 +0300415 setBuiltInInfoFromSymbolTable("gl_FragData", &info);
416 if (!::IsExtensionEnabled(mExtensionBehavior, "GL_EXT_draw_buffers"))
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500417 {
418 info.arraySize = 1;
419 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500420 info.staticUse = true;
421 mOutputVariables->push_back(info);
422 mFragDataAdded = true;
423 }
424 return;
425 case EvqFragDepthEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300426 recordBuiltInFragmentOutputUsed("gl_FragDepthEXT", &mFragDepthEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500427 return;
428 case EvqFragDepth:
Olli Etuaho19515012017-06-26 18:00:17 +0300429 recordBuiltInFragmentOutputUsed("gl_FragDepth", &mFragDepthAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500430 return;
431 case EvqSecondaryFragColorEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300432 recordBuiltInFragmentOutputUsed("gl_SecondaryFragColorEXT",
433 &mSecondaryFragColorEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500434 return;
435 case EvqSecondaryFragDataEXT:
Olli Etuaho19515012017-06-26 18:00:17 +0300436 recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT",
437 &mSecondaryFragDataEXTAdded);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500438 return;
439 default:
440 break;
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400441 }
Zhenyao Mod2d340b2013-09-23 14:57:05 -0400442 }
443 if (var)
Jamie Madilla718c1e2014-07-02 15:31:22 -0400444 {
Olli Etuaho06a06f52017-07-12 12:22:15 +0300445 MarkStaticallyUsed(var);
Jamie Madilla718c1e2014-07-02 15:31:22 -0400446 }
447}
448
Olli Etuaho19515012017-06-26 18:00:17 +0300449void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
450 const TString &name,
451 ShaderVariable *variableOut) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400452{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000453 ASSERT(variableOut);
454
455 const TStructure *structure = type.getStruct();
456
457 if (!structure)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500458 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000459 variableOut->type = GLVariableType(type);
460 variableOut->precision = GLVariablePrecision(type);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500461 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000462 else
Jamie Madill23a8a432014-07-09 13:27:42 -0400463 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000464 // Note: this enum value is not exposed outside ANGLE
465 variableOut->type = GL_STRUCT_ANGLEX;
466 variableOut->structName = structure->name().c_str();
467
468 const TFieldList &fields = structure->fields();
469
470 for (TField *field : fields)
471 {
472 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
473 // ShaderVariable objects.
474 ShaderVariable fieldVariable;
475 setCommonVariableProperties(*field->type(), field->name(), &fieldVariable);
476 variableOut->fields.push_back(fieldVariable);
477 }
Jamie Madill23a8a432014-07-09 13:27:42 -0400478 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000479 variableOut->name = name.c_str();
Olli Etuahocccf2b02017-07-05 14:50:54 +0300480 variableOut->mappedName = HashName(name, mHashFunction).c_str();
Olli Etuahoa55102c2017-02-24 12:36:50 +0000481 variableOut->arraySize = type.getArraySize();
482}
Jamie Madill23a8a432014-07-09 13:27:42 -0400483
Olli Etuaho19515012017-06-26 18:00:17 +0300484Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
Jamie Madill23a8a432014-07-09 13:27:42 -0400485{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000486 const TType &type = variable.getType();
Jamie Madill23a8a432014-07-09 13:27:42 -0400487 ASSERT(!type.getStruct());
488
Jamie Madilla2fbb842014-09-03 09:40:47 -0400489 Attribute attribute;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000490 setCommonVariableProperties(type, variable.getSymbol(), &attribute);
Jamie Madill23a8a432014-07-09 13:27:42 -0400491
Olli Etuahoa55102c2017-02-24 12:36:50 +0000492 attribute.location = type.getLayoutQualifier().location;
493 return attribute;
Jamie Madill23a8a432014-07-09 13:27:42 -0400494}
495
Olli Etuaho19515012017-06-26 18:00:17 +0300496OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
Jamie Madilla0a9e122015-09-02 15:54:30 -0400497{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000498 const TType &type = variable.getType();
Jamie Madilla0a9e122015-09-02 15:54:30 -0400499 ASSERT(!type.getStruct());
500
Olli Etuahoa55102c2017-02-24 12:36:50 +0000501 OutputVariable outputVariable;
502 setCommonVariableProperties(type, variable.getSymbol(), &outputVariable);
Jamie Madilla0a9e122015-09-02 15:54:30 -0400503
Olli Etuahoa55102c2017-02-24 12:36:50 +0000504 outputVariable.location = type.getLayoutQualifier().location;
505 return outputVariable;
Jamie Madilla0a9e122015-09-02 15:54:30 -0400506}
507
Olli Etuaho19515012017-06-26 18:00:17 +0300508Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
Jamie Madilld5512cd2014-07-10 17:50:08 -0400509{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000510 const TType &type = variable.getType();
511
512 Varying varying;
513 setCommonVariableProperties(type, variable.getSymbol(), &varying);
514
515 switch (type.getQualifier())
516 {
517 case EvqVaryingIn:
518 case EvqVaryingOut:
519 case EvqVertexOut:
520 case EvqSmoothOut:
521 case EvqFlatOut:
522 case EvqCentroidOut:
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300523 if (mSymbolTable->isVaryingInvariant(std::string(variable.getSymbol().c_str())) ||
Olli Etuahoa55102c2017-02-24 12:36:50 +0000524 type.isInvariant())
525 {
526 varying.isInvariant = true;
527 }
528 break;
529 default:
530 break;
531 }
532
533 varying.interpolation = GetInterpolationType(type.getQualifier());
534 return varying;
535}
536
Olli Etuaho19515012017-06-26 18:00:17 +0300537InterfaceBlock CollectVariablesTraverser::recordInterfaceBlock(const TIntermSymbol &variable) const
Olli Etuahoa55102c2017-02-24 12:36:50 +0000538{
539 const TInterfaceBlock *blockType = variable.getType().getInterfaceBlock();
Jamie Madill42bcf322014-08-25 16:20:46 -0400540 ASSERT(blockType);
Jamie Madilld5512cd2014-07-10 17:50:08 -0400541
Olli Etuahoa55102c2017-02-24 12:36:50 +0000542 InterfaceBlock interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400543 interfaceBlock.name = blockType->name().c_str();
Olli Etuahocccf2b02017-07-05 14:50:54 +0300544 interfaceBlock.mappedName = HashName(blockType->name().c_str(), mHashFunction).c_str();
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500545 interfaceBlock.instanceName =
546 (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
Olli Etuahoa55102c2017-02-24 12:36:50 +0000547 interfaceBlock.arraySize = variable.getArraySize();
Jamie Madill42bcf322014-08-25 16:20:46 -0400548 interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
jchen10af713a22017-04-19 09:10:56 +0800549 interfaceBlock.binding = blockType->blockBinding();
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500550 interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
Jamie Madilld5512cd2014-07-10 17:50:08 -0400551
Jamie Madilla6f267f2014-08-27 11:44:15 -0400552 // Gather field information
Jamie Madill39046162016-02-08 15:05:17 -0500553 for (const TField *field : blockType->fields())
Jamie Madill54ad4f82014-09-03 09:40:46 -0400554 {
Jamie Madill39046162016-02-08 15:05:17 -0500555 const TType &fieldType = *field->type();
Jamie Madill54ad4f82014-09-03 09:40:46 -0400556
Olli Etuahoa55102c2017-02-24 12:36:50 +0000557 InterfaceBlockField fieldVariable;
558 setCommonVariableProperties(fieldType, field->name(), &fieldVariable);
559 fieldVariable.isRowMajorLayout =
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500560 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
Olli Etuahoa55102c2017-02-24 12:36:50 +0000561 interfaceBlock.fields.push_back(fieldVariable);
Jamie Madill54ad4f82014-09-03 09:40:46 -0400562 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000563 return interfaceBlock;
Jamie Madilld5512cd2014-07-10 17:50:08 -0400564}
565
Olli Etuaho19515012017-06-26 18:00:17 +0300566Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
Jamie Madill4667c452014-07-08 15:02:36 -0400567{
Olli Etuahoa55102c2017-02-24 12:36:50 +0000568 Uniform uniform;
569 setCommonVariableProperties(variable.getType(), variable.getSymbol(), &uniform);
Olli Etuaho547cbd42017-02-27 11:54:00 +0200570 uniform.binding = variable.getType().getLayoutQualifier().binding;
Olli Etuaho6ca2b652017-02-19 18:05:10 +0000571 uniform.location = variable.getType().getLayoutQualifier().location;
jchen104cdac9e2017-05-08 11:01:20 +0800572 uniform.offset = variable.getType().getLayoutQualifier().offset;
Olli Etuahoa55102c2017-02-24 12:36:50 +0000573 return uniform;
alokp@chromium.org07620a52010-09-23 17:53:56 +0000574}
575
Olli Etuaho19515012017-06-26 18:00:17 +0300576bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000577{
Olli Etuaho13389b62016-10-16 11:48:18 +0100578 const TIntermSequence &sequence = *(node->getSequence());
579 ASSERT(!sequence.empty());
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000580
Olli Etuaho13389b62016-10-16 11:48:18 +0100581 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
582 TQualifier qualifier = typedNode.getQualifier();
583
Olli Etuahoa55102c2017-02-24 12:36:50 +0000584 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
585 qualifier == EvqFragmentOut || qualifier == EvqUniform ||
586 IsVarying(qualifier);
587
588 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000589 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000590 return true;
Olli Etuaho13389b62016-10-16 11:48:18 +0100591 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000592
593 for (TIntermNode *variableNode : sequence)
Olli Etuaho13389b62016-10-16 11:48:18 +0100594 {
Olli Etuahoa55102c2017-02-24 12:36:50 +0000595 // The only case in which the sequence will not contain a TIntermSymbol node is
596 // initialization. It will contain a TInterBinary node in that case. Since attributes,
597 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
598 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
599 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
Olli Etuaho34d20072017-07-18 20:07:18 +0300600 if (variable.getName().isInternal())
601 {
602 // Internal variables are not collected.
603 continue;
604 }
605
Olli Etuahoa55102c2017-02-24 12:36:50 +0000606 if (typedNode.getBasicType() == EbtInterfaceBlock)
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000607 {
Jiajia Qinbc585152017-06-23 15:42:17 +0800608 // TODO(jiajia.qin@intel.com): In order not to affect the old set of mInterfaceBlocks,
609 // only uniform blocks are added into mInterfaceBlocks. Refactor it to gather
610 // uniformBlocks and shaderStorageBlocks separately.
611 if (qualifier == EvqUniform)
612 {
613 mInterfaceBlocks->push_back(recordInterfaceBlock(variable));
614 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000615 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000616 else
617 {
618 switch (qualifier)
619 {
620 case EvqAttribute:
621 case EvqVertexIn:
622 mAttribs->push_back(recordAttribute(variable));
623 break;
624 case EvqFragmentOut:
625 mOutputVariables->push_back(recordOutputVariable(variable));
626 break;
627 case EvqUniform:
628 mUniforms->push_back(recordUniform(variable));
629 break;
630 default:
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800631 if (IsVaryingIn(qualifier))
632 {
633 mInputVaryings->push_back(recordVarying(variable));
634 }
635 else
636 {
637 ASSERT(IsVaryingOut(qualifier));
638 mOutputVaryings->push_back(recordVarying(variable));
639 }
Olli Etuahoa55102c2017-02-24 12:36:50 +0000640 break;
641 }
642 }
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000643 }
644
Olli Etuahoa55102c2017-02-24 12:36:50 +0000645 // None of the recorded variables can have initializers, so we don't need to traverse the
646 // declarators.
647 return false;
alokp@chromium.orgee76f6a2010-09-27 19:28:55 +0000648}
Jamie Madill23a8a432014-07-09 13:27:42 -0400649
Olli Etuaho19515012017-06-26 18:00:17 +0300650bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
Jamie Madillb547ddf2014-08-25 16:20:46 -0400651{
652 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
653 {
Jamie Madilla6f267f2014-08-27 11:44:15 -0400654 // NOTE: we do not determine static use for individual blocks of an array
655 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
656 ASSERT(blockNode);
Jamie Madillb547ddf2014-08-25 16:20:46 -0400657
658 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
659 ASSERT(constantUnion);
660
Jamie Madilla6f267f2014-08-27 11:44:15 -0400661 const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
Jamie Madilla2fbb842014-09-03 09:40:47 -0400662 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
Jiajia Qinbc585152017-06-23 15:42:17 +0800663 // TODO(jiajia.qin@intel.com): Currently, only uniform blocks are added into
664 // mInterfaceBlocks.
665 if (namedBlock)
666 {
667 namedBlock->staticUse = true;
668 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
669 ASSERT(fieldIndex < namedBlock->fields.size());
670 namedBlock->fields[fieldIndex].staticUse = true;
671 }
Jamie Madillb547ddf2014-08-25 16:20:46 -0400672 return false;
673 }
674
675 return true;
676}
677
Olli Etuaho19515012017-06-26 18:00:17 +0300678} // anonymous namespace
679
680void CollectVariables(TIntermBlock *root,
681 std::vector<Attribute> *attributes,
682 std::vector<OutputVariable> *outputVariables,
683 std::vector<Uniform> *uniforms,
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800684 std::vector<Varying> *inputVaryings,
685 std::vector<Varying> *outputVaryings,
Olli Etuaho19515012017-06-26 18:00:17 +0300686 std::vector<InterfaceBlock> *interfaceBlocks,
687 ShHashFunction64 hashFunction,
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300688 TSymbolTable *symbolTable,
Olli Etuaho19515012017-06-26 18:00:17 +0300689 int shaderVersion,
690 const TExtensionBehavior &extensionBehavior)
691{
Jiawei-Shaodf7d7c92017-07-31 09:34:04 +0800692 CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
693 outputVaryings, interfaceBlocks, hashFunction, symbolTable,
694 shaderVersion, extensionBehavior);
Olli Etuaho19515012017-06-26 18:00:17 +0300695 root->traverse(&collect);
696}
697
Corentin Walleze58e1412016-07-18 16:40:46 -0400698void ExpandVariable(const ShaderVariable &variable,
699 const std::string &name,
700 const std::string &mappedName,
701 bool markStaticUse,
702 std::vector<ShaderVariable> *expanded)
703{
704 if (variable.isStruct())
705 {
706 if (variable.isArray())
707 {
708 for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
709 elementIndex++)
710 {
711 std::string lname = name + ::ArrayString(elementIndex);
712 std::string lmappedName = mappedName + ::ArrayString(elementIndex);
713 ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
714 }
715 }
716 else
717 {
718 ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
719 }
720 }
721 else
722 {
723 ShaderVariable expandedVar = variable;
724
725 expandedVar.name = name;
726 expandedVar.mappedName = mappedName;
727
728 // Mark all expanded fields as used if the parent is used
729 if (markStaticUse)
730 {
731 expandedVar.staticUse = true;
732 }
733
734 if (expandedVar.isArray())
735 {
736 expandedVar.name += "[0]";
737 expandedVar.mappedName += "[0]";
738 }
739
740 expanded->push_back(expandedVar);
741 }
742}
743
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500744void ExpandUniforms(const std::vector<Uniform> &compact, std::vector<ShaderVariable> *expanded)
Jamie Madill23a8a432014-07-09 13:27:42 -0400745{
Olli Etuaho19515012017-06-26 18:00:17 +0300746 for (const Uniform &variable : compact)
Jamie Madill23a8a432014-07-09 13:27:42 -0400747 {
Jamie Madill23a8a432014-07-09 13:27:42 -0400748 ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
749 }
750}
Olli Etuaho19515012017-06-26 18:00:17 +0300751
752} // namespace sh