Bug Summary

File:root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp
Warning:line 1241, column 13
Access to field 'staticUse' results in a dereference of a null pointer (loaded from variable 'namedBlock')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CollectVariables.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +sse2 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/angle/targets/translator -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/angle/targets/translator -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D ANGLE_PLATFORM_EXPORT= -D __NDK_FPABI__= -D ANGLE_SKIP_DXGI_1_2_CHECK -D ANGLE_ENABLE_KEYEDMUTEX -D ANGLE_TRANSLATOR_ESSL_ONLY -D ANGLE_DISABLE_POOL_ALLOC -D ANGLE_ENABLE_APPLE_WORKAROUNDS -D ANGLE_ENABLE_ESSL -D ANGLE_ENABLE_GLSL -D ANGLE_ENABLE_HLSL -D ANGLE_ENABLE_SHARE_CONTEXT_LOCK=1 -D ANGLE_VMA_VERSION=2003000 -D CR_CLANG_REVISION="llvmorg-16-init-6578-g0d30e92f-2" -D DYNAMIC_ANNOTATIONS_ENABLED=0 -D NOMINMAX -D UNICODE -D WINVER=0x0A00 -D _ATL_NO_OPENGL -D _CRT_NONSTDC_NO_WARNINGS -D _CRT_RAND_S -D _CRT_SECURE_NO_DEPRECATE -D _HAS_EXCEPTIONS=0 -D _SCL_SECURE_NO_DEPRECATE -D _SECURE_ATL -D _UNICODE -D _WINSOCK_DEPRECATED_NO_WARNINGS -I /root/firefox-clang/gfx/angle/targets/translator -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/angle/targets/translator -I /root/firefox-clang/gfx/angle/checkout/include -I /root/firefox-clang/gfx/angle/checkout/src -I /root/firefox-clang/gfx/angle/checkout/src/common/third_party/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-final-dtor-non-final-class -Wno-implicit-const-int-float-conversion -Wno-range-loop-construct -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-1 -x c++ /root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp
1//
2// Copyright 2002 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// CollectVariables.cpp: Collect lists of shader interface variables based on the AST.
7
8#include "compiler/translator/CollectVariables.h"
9
10#include "angle_gl.h"
11#include "common/utilities.h"
12#include "compiler/translator/HashNames.h"
13#include "compiler/translator/SymbolTable.h"
14#include "compiler/translator/tree_util/IntermTraverse.h"
15#include "compiler/translator/util.h"
16
17namespace sh
18{
19
20namespace
21{
22
23BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
24{
25 switch (blockStorage)
26 {
27 case EbsPacked:
28 return BLOCKLAYOUT_PACKED;
29 case EbsShared:
30 return BLOCKLAYOUT_SHARED;
31 case EbsStd140:
32 return BLOCKLAYOUT_STD140;
33 case EbsStd430:
34 return BLOCKLAYOUT_STD430;
35 default:
36 UNREACHABLE()do { !((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 36, ::gl::LOG_FATAL).stream()) << "\t! Unreachable reached: "
<< __FUNCTION__ << "(" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 36 << ")"; } while (0)
;
37 return BLOCKLAYOUT_SHARED;
38 }
39}
40
41BlockType GetBlockType(TQualifier qualifier)
42{
43 switch (qualifier)
44 {
45 case EvqUniform:
46 return BlockType::BLOCK_UNIFORM;
47 case EvqBuffer:
48 return BlockType::BLOCK_BUFFER;
49 default:
50 UNREACHABLE()do { !((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 50, ::gl::LOG_FATAL).stream()) << "\t! Unreachable reached: "
<< __FUNCTION__ << "(" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 50 << ")"; } while (0)
;
51 return BlockType::BLOCK_UNIFORM;
52 }
53}
54
55template <class VarT>
56VarT *FindVariable(const ImmutableString &name, std::vector<VarT> *infoList)
57{
58 // TODO(zmo): optimize this function.
59 for (size_t ii = 0; ii < infoList->size(); ++ii)
22
Assuming the condition is false
23
Loop condition is false. Execution continues on line 65
60 {
61 if (name == (*infoList)[ii].name)
62 return &((*infoList)[ii]);
63 }
64
65 return nullptr;
24
Returning null pointer, which participates in a condition later
66}
67
68void MarkActive(ShaderVariable *variable)
69{
70 if (!variable->active)
71 {
72 if (variable->isStruct())
73 {
74 // Conservatively assume all fields are statically used as well.
75 for (auto &field : variable->fields)
76 {
77 MarkActive(&field);
78 }
79 }
80 variable->staticUse = true;
81 variable->active = true;
82 }
83}
84
85ShaderVariable *FindVariableInInterfaceBlock(const ImmutableString &name,
86 const TInterfaceBlock *interfaceBlock,
87 std::vector<InterfaceBlock> *infoList)
88{
89 ASSERT(interfaceBlock)(interfaceBlock ? static_cast<void>(0) : (!((::gl::priv
::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 89, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 89 << "): " << "interfaceBlock"
))
;
90 InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
91 ASSERT(namedBlock)(namedBlock ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 91, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 91 << "): " << "namedBlock"
))
;
92
93 // Set static use on the parent interface block here
94 namedBlock->staticUse = true;
95 namedBlock->active = true;
96 return FindVariable(name, &namedBlock->fields);
97}
98
99ShaderVariable *FindShaderIOBlockVariable(const ImmutableString &blockName,
100 std::vector<ShaderVariable> *infoList)
101{
102 for (size_t index = 0; index < infoList->size(); ++index)
14
Assuming the condition is false
15
Loop condition is false. Execution continues on line 108
103 {
104 if (blockName == (*infoList)[index].structOrBlockName)
105 return &(*infoList)[index];
106 }
107
108 return nullptr;
16
Returning null pointer, which participates in a condition later
109}
110
111// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
112// shared data and interface blocks.
113class CollectVariablesTraverser : public TIntermTraverser
114{
115 public:
116 CollectVariablesTraverser(std::vector<ShaderVariable> *attribs,
117 std::vector<ShaderVariable> *outputVariables,
118 std::vector<ShaderVariable> *uniforms,
119 std::vector<ShaderVariable> *inputVaryings,
120 std::vector<ShaderVariable> *outputVaryings,
121 std::vector<ShaderVariable> *sharedVariables,
122 std::vector<InterfaceBlock> *uniformBlocks,
123 std::vector<InterfaceBlock> *shaderStorageBlocks,
124 ShHashFunction64 hashFunction,
125 TSymbolTable *symbolTable,
126 GLenum shaderType,
127 const TExtensionBehavior &extensionBehavior,
128 const ShBuiltInResources &resources,
129 int tessControlShaderOutputVertices);
130
131 bool visitGlobalQualifierDeclaration(Visit visit,
132 TIntermGlobalQualifierDeclaration *node) override;
133 void visitSymbol(TIntermSymbol *symbol) override;
134 bool visitDeclaration(Visit, TIntermDeclaration *node) override;
135 bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
136
137 private:
138 std::string getMappedName(const TSymbol *symbol) const;
139
140 void setFieldOrVariableProperties(const TType &type,
141 bool staticUse,
142 bool isShaderIOBlock,
143 bool isPatch,
144 ShaderVariable *variableOut) const;
145 void setFieldProperties(const TType &type,
146 const ImmutableString &name,
147 bool staticUse,
148 bool isShaderIOBlock,
149 bool isPatch,
150 SymbolType symbolType,
151 ShaderVariable *variableOut) const;
152 void setCommonVariableProperties(const TType &type,
153 const TVariable &variable,
154 ShaderVariable *variableOut) const;
155
156 ShaderVariable recordAttribute(const TIntermSymbol &variable) const;
157 ShaderVariable recordOutputVariable(const TIntermSymbol &variable) const;
158 ShaderVariable recordVarying(const TIntermSymbol &variable) const;
159 void recordInterfaceBlock(const char *instanceName,
160 const TType &interfaceBlockType,
161 InterfaceBlock *interfaceBlock) const;
162 ShaderVariable recordUniform(const TIntermSymbol &variable) const;
163
164 void setBuiltInInfoFromSymbol(const TVariable &variable, ShaderVariable *info);
165
166 void recordBuiltInVaryingUsed(const TVariable &variable,
167 bool *addedFlag,
168 std::vector<ShaderVariable> *varyings);
169 void recordBuiltInFragmentOutputUsed(const TVariable &variable, bool *addedFlag);
170 void recordBuiltInAttributeUsed(const TVariable &variable, bool *addedFlag);
171 InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
172
173 std::vector<ShaderVariable> *mAttribs;
174 std::vector<ShaderVariable> *mOutputVariables;
175 std::vector<ShaderVariable> *mUniforms;
176 std::vector<ShaderVariable> *mInputVaryings;
177 std::vector<ShaderVariable> *mOutputVaryings;
178 std::vector<ShaderVariable> *mSharedVariables;
179 std::vector<InterfaceBlock> *mUniformBlocks;
180 std::vector<InterfaceBlock> *mShaderStorageBlocks;
181
182 std::map<std::string, ShaderVariable *> mInterfaceBlockFields;
183
184 // Shader uniforms
185 bool mDepthRangeAdded;
186 bool mNumSamplesAdded;
187
188 // Compute Shader builtins
189 bool mNumWorkGroupsAdded;
190 bool mWorkGroupIDAdded;
191 bool mLocalInvocationIDAdded;
192 bool mGlobalInvocationIDAdded;
193 bool mLocalInvocationIndexAdded;
194
195 // Vertex Shader builtins
196 bool mInstanceIDAdded;
197 bool mVertexIDAdded;
198 bool mPointSizeAdded;
199 bool mDrawIDAdded;
200
201 // Vertex Shader and Geometry Shader builtins
202 bool mPositionAdded;
203 bool mClipDistanceAdded;
204 bool mCullDistanceAdded;
205
206 // Fragment Shader builtins
207 bool mPointCoordAdded;
208 bool mFrontFacingAdded;
209 bool mHelperInvocationAdded;
210 bool mFragCoordAdded;
211 bool mLastFragDataAdded;
212 bool mFragColorAdded;
213 bool mFragDataAdded;
214 bool mFragDepthAdded;
215 bool mSecondaryFragColorEXTAdded;
216 bool mSecondaryFragDataEXTAdded;
217 bool mSampleIDAdded;
218 bool mSamplePositionAdded;
219 bool mSampleMaskAdded;
220 bool mSampleMaskInAdded;
221
222 // Geometry and Tessellation Shader builtins
223 bool mPerVertexInAdded;
224 bool mPerVertexOutAdded;
225
226 // Geometry Shader builtins
227 bool mPrimitiveIDInAdded;
228 bool mInvocationIDAdded;
229
230 // Geometry Shader and Fragment Shader builtins
231 bool mPrimitiveIDAdded;
232 bool mLayerAdded;
233
234 // Shared memory variables
235 bool mSharedVariableAdded;
236
237 // Tessellation Shader builtins
238 bool mPatchVerticesInAdded;
239 bool mTessLevelOuterAdded;
240 bool mTessLevelInnerAdded;
241 bool mBoundingBoxAdded;
242 bool mTessCoordAdded;
243 const int mTessControlShaderOutputVertices;
244
245 ShHashFunction64 mHashFunction;
246
247 GLenum mShaderType;
248 const TExtensionBehavior &mExtensionBehavior;
249 const ShBuiltInResources &mResources;
250};
251
252CollectVariablesTraverser::CollectVariablesTraverser(
253 std::vector<sh::ShaderVariable> *attribs,
254 std::vector<sh::ShaderVariable> *outputVariables,
255 std::vector<sh::ShaderVariable> *uniforms,
256 std::vector<sh::ShaderVariable> *inputVaryings,
257 std::vector<sh::ShaderVariable> *outputVaryings,
258 std::vector<sh::ShaderVariable> *sharedVariables,
259 std::vector<sh::InterfaceBlock> *uniformBlocks,
260 std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
261 ShHashFunction64 hashFunction,
262 TSymbolTable *symbolTable,
263 GLenum shaderType,
264 const TExtensionBehavior &extensionBehavior,
265 const ShBuiltInResources &resources,
266 int tessControlShaderOutputVertices)
267 : TIntermTraverser(true, false, false, symbolTable),
268 mAttribs(attribs),
269 mOutputVariables(outputVariables),
270 mUniforms(uniforms),
271 mInputVaryings(inputVaryings),
272 mOutputVaryings(outputVaryings),
273 mSharedVariables(sharedVariables),
274 mUniformBlocks(uniformBlocks),
275 mShaderStorageBlocks(shaderStorageBlocks),
276 mDepthRangeAdded(false),
277 mNumSamplesAdded(false),
278 mNumWorkGroupsAdded(false),
279 mWorkGroupIDAdded(false),
280 mLocalInvocationIDAdded(false),
281 mGlobalInvocationIDAdded(false),
282 mLocalInvocationIndexAdded(false),
283 mInstanceIDAdded(false),
284 mVertexIDAdded(false),
285 mPointSizeAdded(false),
286 mDrawIDAdded(false),
287 mPositionAdded(false),
288 mClipDistanceAdded(false),
289 mCullDistanceAdded(false),
290 mPointCoordAdded(false),
291 mFrontFacingAdded(false),
292 mHelperInvocationAdded(false),
293 mFragCoordAdded(false),
294 mLastFragDataAdded(false),
295 mFragColorAdded(false),
296 mFragDataAdded(false),
297 mFragDepthAdded(false),
298 mSecondaryFragColorEXTAdded(false),
299 mSecondaryFragDataEXTAdded(false),
300 mSampleIDAdded(false),
301 mSamplePositionAdded(false),
302 mSampleMaskAdded(false),
303 mSampleMaskInAdded(false),
304 mPerVertexInAdded(false),
305 mPerVertexOutAdded(false),
306 mPrimitiveIDInAdded(false),
307 mInvocationIDAdded(false),
308 mPrimitiveIDAdded(false),
309 mLayerAdded(false),
310 mSharedVariableAdded(false),
311 mPatchVerticesInAdded(false),
312 mTessLevelOuterAdded(false),
313 mTessLevelInnerAdded(false),
314 mBoundingBoxAdded(false),
315 mTessCoordAdded(false),
316 mTessControlShaderOutputVertices(tessControlShaderOutputVertices),
317 mHashFunction(hashFunction),
318 mShaderType(shaderType),
319 mExtensionBehavior(extensionBehavior),
320 mResources(resources)
321{}
322
323std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const
324{
325 return HashName(symbol, mHashFunction, nullptr).data();
326}
327
328void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable,
329 ShaderVariable *info)
330{
331 const TType &type = variable.getType();
332
333 info->name = variable.name().data();
334 info->mappedName = variable.name().data();
335
336 bool isShaderIOBlock =
337 IsShaderIoBlock(type.getQualifier()) && type.getInterfaceBlock() != nullptr;
338 bool isPatch = type.getQualifier() == EvqTessLevelInner ||
339 type.getQualifier() == EvqTessLevelOuter ||
340 type.getQualifier() == EvqBoundingBox;
341
342 setFieldOrVariableProperties(type, true, isShaderIOBlock, isPatch, info);
343}
344
345void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable,
346 bool *addedFlag,
347 std::vector<ShaderVariable> *varyings)
348{
349 ASSERT(varyings)(varyings ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 349, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 349 << "): " << "varyings"
))
;
350 if (!(*addedFlag))
351 {
352 ShaderVariable info;
353 setBuiltInInfoFromSymbol(variable, &info);
354 info.active = true;
355 info.isInvariant = mSymbolTable->isVaryingInvariant(variable);
356
357 varyings->push_back(info);
358 (*addedFlag) = true;
359 }
360}
361
362void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const TVariable &variable,
363 bool *addedFlag)
364{
365 if (!(*addedFlag))
366 {
367 ShaderVariable info;
368 setBuiltInInfoFromSymbol(variable, &info);
369 info.active = true;
370 mOutputVariables->push_back(info);
371 (*addedFlag) = true;
372 }
373}
374
375void CollectVariablesTraverser::recordBuiltInAttributeUsed(const TVariable &variable,
376 bool *addedFlag)
377{
378 if (!(*addedFlag))
379 {
380 ShaderVariable info;
381 setBuiltInInfoFromSymbol(variable, &info);
382 info.active = true;
383 info.location = -1;
384 mAttribs->push_back(info);
385 (*addedFlag) = true;
386 }
387}
388
389bool CollectVariablesTraverser::visitGlobalQualifierDeclaration(
390 Visit visit,
391 TIntermGlobalQualifierDeclaration *node)
392{
393 // We should not mark variables as active just based on an invariant/precise declaration, so we
394 // don't traverse the symbols declared invariant.
395 return false;
396}
397
398// We want to check whether a uniform/varying is active because we need to skip updating inactive
399// ones. We also only count the active ones in packing computing. Also, gl_FragCoord, gl_PointCoord,
400// and gl_FrontFacing count toward varying counting if they are active in a fragment shader.
401void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
402{
403 ASSERT(symbol != nullptr)(symbol != nullptr ? static_cast<void>(0) : (!((::gl::priv
::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 403, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 403 << "): " << "symbol != nullptr"
))
;
404
405 if (symbol->variable().symbolType() == SymbolType::AngleInternal ||
406 symbol->variable().symbolType() == SymbolType::Empty)
407 {
408 // Internal variables or nameless variables are not collected.
409 return;
410 }
411
412 ShaderVariable *var = nullptr;
413
414 const ImmutableString &symbolName = symbol->getName();
415
416 // Check the qualifier from the variable, not from the symbol node. The node may have a
417 // different qualifier if it's the result of a folded ternary node.
418 TQualifier qualifier = symbol->variable().getType().getQualifier();
419 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
420
421 if (IsVaryingIn(qualifier))
422 {
423 if (interfaceBlock)
424 {
425 var = FindShaderIOBlockVariable(interfaceBlock->name(), mInputVaryings);
426 }
427 else
428 {
429 var = FindVariable(symbolName, mInputVaryings);
430 }
431 }
432 else if (IsVaryingOut(qualifier))
433 {
434 if (interfaceBlock)
435 {
436 var = FindShaderIOBlockVariable(interfaceBlock->name(), mOutputVaryings);
437 }
438 else
439 {
440 var = FindVariable(symbolName, mOutputVaryings);
441 }
442 }
443 else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
444 {
445 UNREACHABLE()do { !((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 445, ::gl::LOG_FATAL).stream()) << "\t! Unreachable reached: "
<< __FUNCTION__ << "(" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 445 << ")"; } while (0)
;
446 }
447 else if (symbolName == "gl_DepthRange")
448 {
449 ASSERT(qualifier == EvqUniform)(qualifier == EvqUniform ? static_cast<void>(0) : (!((::
gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ?
static_cast<void>(0) : ::gl::priv::LogMessageVoidify()
& (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 449, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 449 << "): " << "qualifier == EvqUniform"
))
;
450
451 if (!mDepthRangeAdded)
452 {
453 ShaderVariable info;
454 const char kName[] = "gl_DepthRange";
455 info.name = kName;
456 info.mappedName = kName;
457 info.type = GL_NONE0;
458 info.precision = GL_NONE0;
459 info.staticUse = true;
460 info.active = true;
461
462 ShaderVariable nearInfo(GL_FLOAT0x1406);
463 const char kNearName[] = "near";
464 nearInfo.name = kNearName;
465 nearInfo.mappedName = kNearName;
466 nearInfo.precision = GL_HIGH_FLOAT0x8DF2;
467 nearInfo.staticUse = true;
468 nearInfo.active = true;
469
470 ShaderVariable farInfo(GL_FLOAT0x1406);
471 const char kFarName[] = "far";
472 farInfo.name = kFarName;
473 farInfo.mappedName = kFarName;
474 farInfo.precision = GL_HIGH_FLOAT0x8DF2;
475 farInfo.staticUse = true;
476 farInfo.active = true;
477
478 ShaderVariable diffInfo(GL_FLOAT0x1406);
479 const char kDiffName[] = "diff";
480 diffInfo.name = kDiffName;
481 diffInfo.mappedName = kDiffName;
482 diffInfo.precision = GL_HIGH_FLOAT0x8DF2;
483 diffInfo.staticUse = true;
484 diffInfo.active = true;
485
486 info.fields.push_back(nearInfo);
487 info.fields.push_back(farInfo);
488 info.fields.push_back(diffInfo);
489
490 mUniforms->push_back(info);
491 mDepthRangeAdded = true;
492 }
493 }
494 else if (symbolName == "gl_NumSamples")
495 {
496 ASSERT(qualifier == EvqUniform)(qualifier == EvqUniform ? static_cast<void>(0) : (!((::
gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ?
static_cast<void>(0) : ::gl::priv::LogMessageVoidify()
& (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 496, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 496 << "): " << "qualifier == EvqUniform"
))
;
497
498 if (!mNumSamplesAdded)
499 {
500 ShaderVariable info;
501 const char kName[] = "gl_NumSamples";
502 info.name = kName;
503 info.mappedName = kName;
504 info.type = GL_INT0x1404;
505 info.precision = GL_LOW_INT0x8DF3;
506 info.staticUse = true;
507 info.active = true;
508
509 mUniforms->push_back(info);
510 mNumSamplesAdded = true;
511 }
512 }
513 else
514 {
515 switch (qualifier)
516 {
517 case EvqAttribute:
518 case EvqVertexIn:
519 var = FindVariable(symbolName, mAttribs);
520 break;
521 case EvqFragmentOut:
522 case EvqFragmentInOut:
523 var = FindVariable(symbolName, mOutputVariables);
524 var->isFragmentInOut = qualifier == EvqFragmentInOut;
525 break;
526 case EvqUniform:
527 {
528 if (interfaceBlock)
529 {
530 var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
531 }
532 else
533 {
534 var = FindVariable(symbolName, mUniforms);
535 }
536
537 // It's an internal error to reference an undefined user uniform
538 ASSERT(!gl::IsBuiltInName(symbolName.data()) || var)(!gl::IsBuiltInName(symbolName.data()) || var ? static_cast<
void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(
::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv::
LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 538, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 538 << "): " << "!gl::IsBuiltInName(symbolName.data()) || var"
))
;
539 }
540 break;
541 case EvqBuffer:
542 {
543 var =
544 FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
545 }
546 break;
547 case EvqFragCoord:
548 recordBuiltInVaryingUsed(symbol->variable(), &mFragCoordAdded, mInputVaryings);
549 return;
550 case EvqFrontFacing:
551 recordBuiltInVaryingUsed(symbol->variable(), &mFrontFacingAdded, mInputVaryings);
552 return;
553 case EvqHelperInvocation:
554 recordBuiltInVaryingUsed(symbol->variable(), &mHelperInvocationAdded,
555 mInputVaryings);
556 return;
557 case EvqPointCoord:
558 recordBuiltInVaryingUsed(symbol->variable(), &mPointCoordAdded, mInputVaryings);
559 return;
560 case EvqNumWorkGroups:
561 recordBuiltInAttributeUsed(symbol->variable(), &mNumWorkGroupsAdded);
562 return;
563 case EvqWorkGroupID:
564 recordBuiltInAttributeUsed(symbol->variable(), &mWorkGroupIDAdded);
565 return;
566 case EvqLocalInvocationID:
567 recordBuiltInAttributeUsed(symbol->variable(), &mLocalInvocationIDAdded);
568 return;
569 case EvqGlobalInvocationID:
570 recordBuiltInAttributeUsed(symbol->variable(), &mGlobalInvocationIDAdded);
571 return;
572 case EvqLocalInvocationIndex:
573 recordBuiltInAttributeUsed(symbol->variable(), &mLocalInvocationIndexAdded);
574 return;
575 case EvqInstanceID:
576 // Whenever the initializeBuiltinsForInstancedMultiview option is set,
577 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
578 // InstanceID. Note that gl_InstanceID is not added to the symbol table for ESSL1
579 // shaders.
580 recordBuiltInAttributeUsed(symbol->variable(), &mInstanceIDAdded);
581 return;
582 case EvqVertexID:
583 recordBuiltInAttributeUsed(symbol->variable(), &mVertexIDAdded);
584 return;
585 case EvqPosition:
586 recordBuiltInVaryingUsed(symbol->variable(), &mPositionAdded, mOutputVaryings);
587 return;
588 case EvqPointSize:
589 recordBuiltInVaryingUsed(symbol->variable(), &mPointSizeAdded, mOutputVaryings);
590 return;
591 case EvqDrawID:
592 recordBuiltInAttributeUsed(symbol->variable(), &mDrawIDAdded);
593 return;
594 case EvqLastFragData:
595 recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings);
596 return;
597 case EvqFragColor:
598 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragColorAdded);
599 return;
600 case EvqFragData:
601 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDataAdded);
602 return;
603 case EvqFragDepth:
604 recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthAdded);
605 return;
606 case EvqSecondaryFragColorEXT:
607 recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragColorEXTAdded);
608 return;
609 case EvqSecondaryFragDataEXT:
610 recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragDataEXTAdded);
611 return;
612 case EvqInvocationID:
613 recordBuiltInVaryingUsed(symbol->variable(), &mInvocationIDAdded, mInputVaryings);
614 break;
615 case EvqPrimitiveIDIn:
616 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDInAdded, mInputVaryings);
617 break;
618 case EvqPrimitiveID:
619 if (mShaderType == GL_GEOMETRY_SHADER_EXT0x8DD9)
620 {
621 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
622 mOutputVaryings);
623 }
624 else
625 {
626 ASSERT(mShaderType == GL_FRAGMENT_SHADER ||(mShaderType == 0x8B30 || mShaderType == 0x8E88 || mShaderType
== 0x8E87 ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 628, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 628 << "): " << "mShaderType == GL_FRAGMENT_SHADER || mShaderType == GL_TESS_CONTROL_SHADER || mShaderType == GL_TESS_EVALUATION_SHADER"
))
627 mShaderType == GL_TESS_CONTROL_SHADER ||(mShaderType == 0x8B30 || mShaderType == 0x8E88 || mShaderType
== 0x8E87 ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 628, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 628 << "): " << "mShaderType == GL_FRAGMENT_SHADER || mShaderType == GL_TESS_CONTROL_SHADER || mShaderType == GL_TESS_EVALUATION_SHADER"
))
628 mShaderType == GL_TESS_EVALUATION_SHADER)(mShaderType == 0x8B30 || mShaderType == 0x8E88 || mShaderType
== 0x8E87 ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 628, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 628 << "): " << "mShaderType == GL_FRAGMENT_SHADER || mShaderType == GL_TESS_CONTROL_SHADER || mShaderType == GL_TESS_EVALUATION_SHADER"
))
;
629 recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
630 mInputVaryings);
631 }
632 break;
633 case EvqLayerOut:
634 if (mShaderType == GL_GEOMETRY_SHADER_EXT0x8DD9)
635 {
636 recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mOutputVaryings);
637 }
638 else
639 {
640 ASSERT(mShaderType == GL_VERTEX_SHADER &&(mShaderType == 0x8B31 && (IsExtensionEnabled(mExtensionBehavior
, TExtension::OVR_multiview2) || IsExtensionEnabled(mExtensionBehavior
, TExtension::OVR_multiview)) ? static_cast<void>(0) : (
!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 642, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 642 << "): " << "mShaderType == GL_VERTEX_SHADER && (IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview2) || IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview))"
))
641 (IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview2) ||(mShaderType == 0x8B31 && (IsExtensionEnabled(mExtensionBehavior
, TExtension::OVR_multiview2) || IsExtensionEnabled(mExtensionBehavior
, TExtension::OVR_multiview)) ? static_cast<void>(0) : (
!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 642, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 642 << "): " << "mShaderType == GL_VERTEX_SHADER && (IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview2) || IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview))"
))
642 IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview)))(mShaderType == 0x8B31 && (IsExtensionEnabled(mExtensionBehavior
, TExtension::OVR_multiview2) || IsExtensionEnabled(mExtensionBehavior
, TExtension::OVR_multiview)) ? static_cast<void>(0) : (
!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 642, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 642 << "): " << "mShaderType == GL_VERTEX_SHADER && (IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview2) || IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview))"
))
;
643 }
644 break;
645 case EvqLayerIn:
646 ASSERT(mShaderType == GL_FRAGMENT_SHADER)(mShaderType == 0x8B30 ? static_cast<void>(0) : (!((::gl
::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 646, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 646 << "): " << "mShaderType == GL_FRAGMENT_SHADER"
))
;
647 recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mInputVaryings);
648 break;
649 case EvqShared:
650 if (mShaderType == GL_COMPUTE_SHADER0x91B9)
651 {
652 recordBuiltInVaryingUsed(symbol->variable(), &mSharedVariableAdded,
653 mSharedVariables);
654 }
655 break;
656 case EvqClipDistance:
657 recordBuiltInVaryingUsed(
658 symbol->variable(), &mClipDistanceAdded,
659 mShaderType == GL_FRAGMENT_SHADER0x8B30 ? mInputVaryings : mOutputVaryings);
660 return;
661 case EvqCullDistance:
662 recordBuiltInVaryingUsed(
663 symbol->variable(), &mCullDistanceAdded,
664 mShaderType == GL_FRAGMENT_SHADER0x8B30 ? mInputVaryings : mOutputVaryings);
665 return;
666 case EvqSampleID:
667 recordBuiltInVaryingUsed(symbol->variable(), &mSampleIDAdded, mInputVaryings);
668 return;
669 case EvqSamplePosition:
670 recordBuiltInVaryingUsed(symbol->variable(), &mSamplePositionAdded, mInputVaryings);
671 return;
672 case EvqSampleMaskIn:
673 recordBuiltInVaryingUsed(symbol->variable(), &mSampleMaskInAdded, mInputVaryings);
674 return;
675 case EvqSampleMask:
676 recordBuiltInFragmentOutputUsed(symbol->variable(), &mSampleMaskAdded);
677 return;
678 case EvqPatchVerticesIn:
679 recordBuiltInVaryingUsed(symbol->variable(), &mPatchVerticesInAdded,
680 mInputVaryings);
681 break;
682 case EvqTessCoord:
683 recordBuiltInVaryingUsed(symbol->variable(), &mTessCoordAdded, mInputVaryings);
684 break;
685 case EvqTessLevelOuter:
686 if (mShaderType == GL_TESS_CONTROL_SHADER0x8E88)
687 {
688 recordBuiltInVaryingUsed(symbol->variable(), &mTessLevelOuterAdded,
689 mOutputVaryings);
690 }
691 else
692 {
693 ASSERT(mShaderType == GL_TESS_EVALUATION_SHADER)(mShaderType == 0x8E87 ? static_cast<void>(0) : (!((::gl
::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 693, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 693 << "): " << "mShaderType == GL_TESS_EVALUATION_SHADER"
))
;
694 recordBuiltInVaryingUsed(symbol->variable(), &mTessLevelOuterAdded,
695 mInputVaryings);
696 }
697 break;
698 case EvqTessLevelInner:
699 if (mShaderType == GL_TESS_CONTROL_SHADER0x8E88)
700 {
701 recordBuiltInVaryingUsed(symbol->variable(), &mTessLevelInnerAdded,
702 mOutputVaryings);
703 }
704 else
705 {
706 ASSERT(mShaderType == GL_TESS_EVALUATION_SHADER)(mShaderType == 0x8E87 ? static_cast<void>(0) : (!((::gl
::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 706, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 706 << "): " << "mShaderType == GL_TESS_EVALUATION_SHADER"
))
;
707 recordBuiltInVaryingUsed(symbol->variable(), &mTessLevelInnerAdded,
708 mInputVaryings);
709 }
710 break;
711 case EvqBoundingBox:
712 recordBuiltInVaryingUsed(symbol->variable(), &mBoundingBoxAdded, mOutputVaryings);
713 break;
714 default:
715 break;
716 }
717 }
718 if (var)
719 {
720 MarkActive(var);
721 }
722}
723
724void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
725 bool staticUse,
726 bool isShaderIOBlock,
727 bool isPatch,
728 ShaderVariable *variableOut) const
729{
730 ASSERT(variableOut)(variableOut ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 730, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 730 << "): " << "variableOut"
))
;
731
732 variableOut->staticUse = staticUse;
733 variableOut->isShaderIOBlock = isShaderIOBlock;
734 variableOut->isPatch = isPatch;
735
736 const TStructure *structure = type.getStruct();
737 const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
738 if (structure)
739 {
740 // Structures use a NONE type that isn't exposed outside ANGLE.
741 variableOut->type = GL_NONE0;
742 if (structure->symbolType() != SymbolType::Empty)
743 {
744 variableOut->structOrBlockName = structure->name().data();
745 }
746
747 const TFieldList &fields = structure->fields();
748
749 for (const TField *field : fields)
750 {
751 // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
752 // ShaderVariable objects.
753 ShaderVariable fieldVariable;
754 setFieldProperties(*field->type(), field->name(), staticUse, isShaderIOBlock, isPatch,
755 field->symbolType(), &fieldVariable);
756 variableOut->fields.push_back(fieldVariable);
757 }
758 }
759 else if (interfaceBlock && isShaderIOBlock)
760 {
761 const bool isPerVertex = (interfaceBlock->name() == "gl_PerVertex");
762 variableOut->type = GL_NONE0;
763 if (interfaceBlock->symbolType() != SymbolType::Empty)
764 {
765 variableOut->structOrBlockName = interfaceBlock->name().data();
766 variableOut->mappedStructOrBlockName =
767 isPerVertex ? interfaceBlock->name().data()
768 : HashName(interfaceBlock->name(), mHashFunction, nullptr).data();
769 }
770 const TFieldList &fields = interfaceBlock->fields();
771 for (const TField *field : fields)
772 {
773 ShaderVariable fieldVariable;
774
775 setFieldProperties(*field->type(), field->name(), staticUse, true, isPatch,
776 field->symbolType(), &fieldVariable);
777 fieldVariable.isShaderIOBlock = true;
778 variableOut->fields.push_back(fieldVariable);
779 }
780 }
781 else
782 {
783 variableOut->type = GLVariableType(type);
784 variableOut->precision = GLVariablePrecision(type);
785 }
786
787 const TSpan<const unsigned int> &arraySizes = type.getArraySizes();
788 if (!arraySizes.empty())
789 {
790 variableOut->arraySizes.assign(arraySizes.begin(), arraySizes.end());
791
792 if (arraySizes[0] == 0)
793 {
794 // Tessellation Control & Evaluation shader inputs:
795 // Declaring an array size is optional. If no size is specified, it will be taken from
796 // the implementation-dependent maximum patch size (gl_MaxPatchVertices).
797 if (type.getQualifier() == EvqTessControlIn ||
798 type.getQualifier() == EvqTessEvaluationIn)
799 {
800 variableOut->arraySizes[0] = mResources.MaxPatchVertices;
801 }
802
803 // Tessellation Control shader outputs:
804 // Declaring an array size is optional. If no size is specified, it will be taken from
805 // output patch size declared in the shader.
806 if (type.getQualifier() == EvqTessControlOut)
807 {
808 ASSERT(mTessControlShaderOutputVertices > 0)(mTessControlShaderOutputVertices > 0 ? static_cast<void
>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl
::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 808, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 808 << "): " << "mTessControlShaderOutputVertices > 0"
))
;
809 variableOut->arraySizes[0] = mTessControlShaderOutputVertices;
810 }
811 }
812 }
813}
814
815void CollectVariablesTraverser::setFieldProperties(const TType &type,
816 const ImmutableString &name,
817 bool staticUse,
818 bool isShaderIOBlock,
819 bool isPatch,
820 SymbolType symbolType,
821 ShaderVariable *variableOut) const
822{
823 ASSERT(variableOut)(variableOut ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 823, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 823 << "): " << "variableOut"
))
;
824 setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut);
825 variableOut->name.assign(name.data(), name.length());
826 variableOut->mappedName = (symbolType == SymbolType::BuiltIn)
827 ? name.data()
828 : HashName(name, mHashFunction, nullptr).data();
829}
830
831void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
832 const TVariable &variable,
833 ShaderVariable *variableOut) const
834{
835 ASSERT(variableOut)(variableOut ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 835, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 835 << "): " << "variableOut"
))
;
836 ASSERT(type.getInterfaceBlock() == nullptr || IsShaderIoBlock(type.getQualifier()) ||(type.getInterfaceBlock() == nullptr || IsShaderIoBlock(type.
getQualifier()) || type.getQualifier() == EvqPatchIn || type.
getQualifier() == EvqPatchOut ? static_cast<void>(0) : (
!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 837, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 837 << "): " << "type.getInterfaceBlock() == nullptr || IsShaderIoBlock(type.getQualifier()) || type.getQualifier() == EvqPatchIn || type.getQualifier() == EvqPatchOut"
))
837 type.getQualifier() == EvqPatchIn || type.getQualifier() == EvqPatchOut)(type.getInterfaceBlock() == nullptr || IsShaderIoBlock(type.
getQualifier()) || type.getQualifier() == EvqPatchIn || type.
getQualifier() == EvqPatchOut ? static_cast<void>(0) : (
!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 837, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 837 << "): " << "type.getInterfaceBlock() == nullptr || IsShaderIoBlock(type.getQualifier()) || type.getQualifier() == EvqPatchIn || type.getQualifier() == EvqPatchOut"
))
;
838
839 const bool staticUse = mSymbolTable->isStaticallyUsed(variable);
840 const bool isShaderIOBlock = type.getInterfaceBlock() != nullptr;
841 const bool isPatch = type.getQualifier() == EvqPatchIn || type.getQualifier() == EvqPatchOut;
842
843 setFieldOrVariableProperties(type, staticUse, isShaderIOBlock, isPatch, variableOut);
844
845 const bool isNamed = variable.symbolType() != SymbolType::Empty;
846
847 ASSERT(isNamed || isShaderIOBlock)(isNamed || isShaderIOBlock ? static_cast<void>(0) : (!
((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL)
)) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 847, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 847 << "): " << "isNamed || isShaderIOBlock"
))
;
848 if (isNamed)
849 {
850 variableOut->name.assign(variable.name().data(), variable.name().length());
851 variableOut->mappedName = getMappedName(&variable);
852 }
853
854 // For I/O blocks, additionally store the name of the block as blockName. If the variable is
855 // unnamed, this name will be used instead for the purpose of interface matching.
856 if (isShaderIOBlock)
857 {
858 const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
859 ASSERT(interfaceBlock)(interfaceBlock ? static_cast<void>(0) : (!((::gl::priv
::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 859, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 859 << "): " << "interfaceBlock"
))
;
860
861 variableOut->structOrBlockName.assign(interfaceBlock->name().data(),
862 interfaceBlock->name().length());
863 variableOut->mappedStructOrBlockName =
864 HashName(interfaceBlock->name(), mHashFunction, nullptr).data();
865 variableOut->isShaderIOBlock = true;
866 }
867}
868
869ShaderVariable CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
870{
871 const TType &type = variable.getType();
872 ASSERT(!type.getStruct())(!type.getStruct() ? static_cast<void>(0) : (!((::gl::priv
::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 872, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 872 << "): " << "!type.getStruct()"
))
;
873
874 ShaderVariable attribute;
875 setCommonVariableProperties(type, variable.variable(), &attribute);
876
877 attribute.location = type.getLayoutQualifier().location;
878 return attribute;
879}
880
881ShaderVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
882{
883 const TType &type = variable.getType();
884 ASSERT(!type.getStruct())(!type.getStruct() ? static_cast<void>(0) : (!((::gl::priv
::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 884, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 884 << "): " << "!type.getStruct()"
))
;
885
886 ShaderVariable outputVariable;
887 setCommonVariableProperties(type, variable.variable(), &outputVariable);
888
889 outputVariable.location = type.getLayoutQualifier().location;
890 outputVariable.index = type.getLayoutQualifier().index;
891 outputVariable.yuv = type.getLayoutQualifier().yuv;
892 return outputVariable;
893}
894
895ShaderVariable CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
896{
897 const TType &type = variable.getType();
898
899 ShaderVariable varying;
900 setCommonVariableProperties(type, variable.variable(), &varying);
901 varying.location = type.getLayoutQualifier().location;
902
903 switch (type.getQualifier())
904 {
905 case EvqVaryingIn:
906 case EvqVaryingOut:
907 case EvqVertexOut:
908 case EvqSmoothOut:
909 case EvqFlatOut:
910 case EvqNoPerspectiveOut:
911 case EvqCentroidOut:
912 case EvqGeometryOut:
913 case EvqSampleOut:
914 if (mSymbolTable->isVaryingInvariant(variable.variable()) || type.isInvariant())
915 {
916 varying.isInvariant = true;
917 }
918 break;
919 case EvqPatchIn:
920 case EvqPatchOut:
921 varying.isPatch = true;
922 break;
923 default:
924 break;
925 }
926
927 varying.interpolation = GetInterpolationType(type.getQualifier());
928
929 // Shader I/O block properties
930 if (type.getBasicType() == EbtInterfaceBlock)
931 {
932 bool isBlockImplicitLocation = false;
933 int location = type.getLayoutQualifier().location;
934
935 // when a interface has not location in layout, assign to the zero.
936 if (location < 0)
937 {
938 location = 0;
939 isBlockImplicitLocation = true;
940 }
941
942 const TInterfaceBlock *blockType = type.getInterfaceBlock();
943 ASSERT(blockType->fields().size() == varying.fields.size())(blockType->fields().size() == varying.fields.size() ? static_cast
<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 943, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 943 << "): " << "blockType->fields().size() == varying.fields.size()"
))
;
944
945 for (size_t fieldIndex = 0; fieldIndex < varying.fields.size(); ++fieldIndex)
946 {
947 const TField *blockField = blockType->fields()[fieldIndex];
948 ShaderVariable &fieldVariable = varying.fields[fieldIndex];
949 const TType &fieldType = *blockField->type();
950
951 fieldVariable.hasImplicitLocation = isBlockImplicitLocation;
952 fieldVariable.isPatch = varying.isPatch;
953
954 int fieldLocation = fieldType.getLayoutQualifier().location;
955 if (fieldLocation >= 0)
956 {
957 fieldVariable.hasImplicitLocation = false;
958 fieldVariable.location = fieldLocation;
959 location = fieldLocation;
960 }
961 else
962 {
963 fieldVariable.location = location;
964 location += fieldType.getLocationCount();
965 }
966
967 if (fieldType.getQualifier() != EvqGlobal)
968 {
969 fieldVariable.interpolation = GetFieldInterpolationType(fieldType.getQualifier());
970 }
971 }
972 }
973
974 return varying;
975}
976
977void CollectVariablesTraverser::recordInterfaceBlock(const char *instanceName,
978 const TType &interfaceBlockType,
979 InterfaceBlock *interfaceBlock) const
980{
981 ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock)(interfaceBlockType.getBasicType() == EbtInterfaceBlock ? static_cast
<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 981, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 981 << "): " << "interfaceBlockType.getBasicType() == EbtInterfaceBlock"
))
;
982 ASSERT(interfaceBlock)(interfaceBlock ? static_cast<void>(0) : (!((::gl::priv
::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 982, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 982 << "): " << "interfaceBlock"
))
;
983
984 const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
985 ASSERT(blockType)(blockType ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 985, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 985 << "): " << "blockType"
))
;
986
987 interfaceBlock->name = blockType->name().data();
988 interfaceBlock->mappedName = getMappedName(blockType);
989
990 const bool isGLInBuiltin = (instanceName != nullptr) && strncmp(instanceName, "gl_in", 5u) == 0;
991 if (instanceName != nullptr)
992 {
993 interfaceBlock->instanceName = instanceName;
994 const TSymbol *blockSymbol = nullptr;
995 if (isGLInBuiltin)
996 {
997 blockSymbol = mSymbolTable->getGlInVariableWithArraySize();
998 }
999 else
1000 {
1001 blockSymbol = mSymbolTable->findGlobal(ImmutableString(instanceName));
1002 }
1003 ASSERT(blockSymbol && blockSymbol->isVariable())(blockSymbol && blockSymbol->isVariable() ? static_cast
<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1003, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1003 << "): " << "blockSymbol && blockSymbol->isVariable()"
))
;
1004 interfaceBlock->staticUse =
1005 mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(blockSymbol));
1006 }
1007
1008 ASSERT(!interfaceBlockType.isArrayOfArrays())(!interfaceBlockType.isArrayOfArrays() ? static_cast<void>
(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1008, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1008 << "): " << "!interfaceBlockType.isArrayOfArrays()"
))
; // Disallowed by GLSL ES 3.10 section 4.3.9
1009 interfaceBlock->arraySize =
1010 interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
1011
1012 interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
1013 if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
1014 interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
1015 {
1016 // TODO(oetuaho): Remove setting isRowMajorLayout.
1017 interfaceBlock->isRowMajorLayout = false;
1018 interfaceBlock->binding = blockType->blockBinding();
1019 interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
1020 }
1021
1022 // Gather field information
1023 bool anyFieldStaticallyUsed = false;
1024
1025 for (const TField *field : blockType->fields())
1026 {
1027 const TType &fieldType = *field->type();
1028
1029 bool staticUse = false;
1030 if (instanceName == nullptr)
1031 {
1032 // Static use of individual fields has been recorded, since they are present in the
1033 // symbol table as variables.
1034 const TSymbol *fieldSymbol = mSymbolTable->findGlobal(field->name());
1035 ASSERT(fieldSymbol && fieldSymbol->isVariable())(fieldSymbol && fieldSymbol->isVariable() ? static_cast
<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1035, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1035 << "): " << "fieldSymbol && fieldSymbol->isVariable()"
))
;
1036 staticUse =
1037 mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(fieldSymbol));
1038 if (staticUse)
1039 {
1040 anyFieldStaticallyUsed = true;
1041 }
1042 }
1043
1044 ShaderVariable fieldVariable;
1045 setFieldProperties(fieldType, field->name(), staticUse, false, false, field->symbolType(),
1046 &fieldVariable);
1047 fieldVariable.isRowMajorLayout =
1048 (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
1049 interfaceBlock->fields.push_back(fieldVariable);
1050 }
1051 if (anyFieldStaticallyUsed)
1052 {
1053 interfaceBlock->staticUse = true;
1054 }
1055}
1056
1057ShaderVariable CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
1058{
1059 ShaderVariable uniform;
1060 setCommonVariableProperties(variable.getType(), variable.variable(), &uniform);
1061 uniform.binding = variable.getType().getLayoutQualifier().binding;
1062 uniform.imageUnitFormat =
1063 GetImageInternalFormatType(variable.getType().getLayoutQualifier().imageInternalFormat);
1064 uniform.location = variable.getType().getLayoutQualifier().location;
1065 uniform.offset = variable.getType().getLayoutQualifier().offset;
1066 uniform.rasterOrdered = variable.getType().getLayoutQualifier().rasterOrdered;
1067 uniform.readonly = variable.getType().getMemoryQualifier().readonly;
1068 uniform.writeonly = variable.getType().getMemoryQualifier().writeonly;
1069 return uniform;
1070}
1071
1072bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
1073{
1074 const TIntermSequence &sequence = *(node->getSequence());
1075 ASSERT(!sequence.empty())(!sequence.empty() ? static_cast<void>(0) : (!((::gl::priv
::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1075, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1075 << "): " << "!sequence.empty()"
))
;
1076
1077 const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
1078 TQualifier qualifier = typedNode.getQualifier();
1079
1080 bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
1081 qualifier == EvqFragmentOut || qualifier == EvqFragmentInOut ||
1082 qualifier == EvqUniform || IsVarying(qualifier);
1083
1084 if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
1085 {
1086 return true;
1087 }
1088
1089 for (TIntermNode *variableNode : sequence)
1090 {
1091 // The only case in which the sequence will not contain a TIntermSymbol node is
1092 // initialization. It will contain a TInterBinary node in that case. Since attributes,
1093 // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
1094 // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
1095 const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
1096 if (variable.variable().symbolType() == SymbolType::AngleInternal)
1097 {
1098 // Internal variables are not collected.
1099 continue;
1100 }
1101
1102 // SpirvTransformer::transform uses a map of ShaderVariables, it needs member variables and
1103 // (named or unnamed) structure as ShaderVariable. at link between two shaders, validation
1104 // between of named and unnamed, needs the same structure, its members, and members order
1105 // except instance name.
1106 if (typedNode.getBasicType() == EbtInterfaceBlock && !IsShaderIoBlock(qualifier) &&
1107 qualifier != EvqPatchIn && qualifier != EvqPatchOut)
1108 {
1109 InterfaceBlock interfaceBlock;
1110 bool isUnnamed = variable.variable().symbolType() == SymbolType::Empty;
1111 const TType &type = variable.getType();
1112 recordInterfaceBlock(isUnnamed ? nullptr : variable.getName().data(), type,
1113 &interfaceBlock);
1114
1115 // all fields in interface block will be added for updating interface variables because
1116 // the temporal structure variable will be ignored.
1117 switch (qualifier)
1118 {
1119 case EvqUniform:
1120 mUniformBlocks->push_back(interfaceBlock);
1121 break;
1122 case EvqBuffer:
1123 mShaderStorageBlocks->push_back(interfaceBlock);
1124 break;
1125 default:
1126 UNREACHABLE()do { !((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1126, ::gl::LOG_FATAL).stream()) << "\t! Unreachable reached: "
<< __FUNCTION__ << "(" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1126 << ")"; } while (0)
;
1127 }
1128 }
1129 else
1130 {
1131 ASSERT(variable.variable().symbolType() != SymbolType::Empty ||(variable.variable().symbolType() != SymbolType::Empty || IsShaderIoBlock
(qualifier) || qualifier == EvqPatchIn || qualifier == EvqPatchOut
? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1133, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1133 << "): " << "variable.variable().symbolType() != SymbolType::Empty || IsShaderIoBlock(qualifier) || qualifier == EvqPatchIn || qualifier == EvqPatchOut"
))
1132 IsShaderIoBlock(qualifier) || qualifier == EvqPatchIn ||(variable.variable().symbolType() != SymbolType::Empty || IsShaderIoBlock
(qualifier) || qualifier == EvqPatchIn || qualifier == EvqPatchOut
? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1133, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1133 << "): " << "variable.variable().symbolType() != SymbolType::Empty || IsShaderIoBlock(qualifier) || qualifier == EvqPatchIn || qualifier == EvqPatchOut"
))
1133 qualifier == EvqPatchOut)(variable.variable().symbolType() != SymbolType::Empty || IsShaderIoBlock
(qualifier) || qualifier == EvqPatchIn || qualifier == EvqPatchOut
? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1133, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1133 << "): " << "variable.variable().symbolType() != SymbolType::Empty || IsShaderIoBlock(qualifier) || qualifier == EvqPatchIn || qualifier == EvqPatchOut"
))
;
1134 switch (qualifier)
1135 {
1136 case EvqAttribute:
1137 case EvqVertexIn:
1138 mAttribs->push_back(recordAttribute(variable));
1139 break;
1140 case EvqFragmentOut:
1141 case EvqFragmentInOut:
1142 mOutputVariables->push_back(recordOutputVariable(variable));
1143 break;
1144 case EvqUniform:
1145 mUniforms->push_back(recordUniform(variable));
1146 break;
1147 default:
1148 if (IsVaryingIn(qualifier))
1149 {
1150 mInputVaryings->push_back(recordVarying(variable));
1151 }
1152 else
1153 {
1154 ASSERT(IsVaryingOut(qualifier))(IsVaryingOut(qualifier) ? static_cast<void>(0) : (!((::
gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ?
static_cast<void>(0) : ::gl::priv::LogMessageVoidify()
& (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1154, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1154 << "): " << "IsVaryingOut(qualifier)"
))
;
1155 mOutputVaryings->push_back(recordVarying(variable));
1156 }
1157 break;
1158 }
1159 }
1160 }
1161
1162 // None of the recorded variables can have initializers, so we don't need to traverse the
1163 // declarators.
1164 return false;
1165}
1166
1167InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(
1168 const ImmutableString &blockName) const
1169{
1170 InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
21
Calling 'FindVariable<sh::InterfaceBlock>'
25
Returning from 'FindVariable<sh::InterfaceBlock>'
1171 if (!namedBlock
25.1
'namedBlock' is null
)
26
Taking true branch
1172 {
1173 namedBlock = FindVariable(blockName, mShaderStorageBlocks);
27
Value assigned to 'namedBlock'
1174 }
1175 return namedBlock;
28
Returning pointer (loaded from 'namedBlock')
1176}
1177
1178bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
1179{
1180 if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
1
Assuming the condition is true
2
Taking true branch
1181 {
1182 // NOTE: we do not determine static use / activeness for individual blocks of an array.
1183 TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
1184 ASSERT(blockNode)(blockNode ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1184, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1184 << "): " << "blockNode"
))
;
3
Assuming 'blockNode' is non-null
4
'?' condition is true
1185
1186 TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
1187 ASSERT(constantUnion)(constantUnion ? static_cast<void>(0) : (!((::gl::priv::
ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1187, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1187 << "): " << "constantUnion"
))
;
5
Assuming 'constantUnion' is non-null
6
'?' condition is true
1188
1189 InterfaceBlock *namedBlock = nullptr;
1190
1191 bool traverseIndexExpression = false;
1192 TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
1193 if (interfaceIndexingNode)
7
Assuming 'interfaceIndexingNode' is null
8
Taking false branch
1194 {
1195 ASSERT(interfaceIndexingNode->getOp() == EOpIndexDirect ||(interfaceIndexingNode->getOp() == EOpIndexDirect || interfaceIndexingNode
->getOp() == EOpIndexIndirect ? static_cast<void>(0)
: (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1196, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1196 << "): " << "interfaceIndexingNode->getOp() == EOpIndexDirect || interfaceIndexingNode->getOp() == EOpIndexIndirect"
))
1196 interfaceIndexingNode->getOp() == EOpIndexIndirect)(interfaceIndexingNode->getOp() == EOpIndexDirect || interfaceIndexingNode
->getOp() == EOpIndexIndirect ? static_cast<void>(0)
: (!((::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL
))) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1196, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1196 << "): " << "interfaceIndexingNode->getOp() == EOpIndexDirect || interfaceIndexingNode->getOp() == EOpIndexIndirect"
))
;
1197 traverseIndexExpression = true;
1198 blockNode = interfaceIndexingNode->getLeft();
1199 }
1200
1201 const TType &interfaceNodeType = blockNode->getType();
1202 const TInterfaceBlock *interfaceBlock = interfaceNodeType.getInterfaceBlock();
1203 const TQualifier qualifier = interfaceNodeType.getQualifier();
1204
1205 // If it's a shader I/O block, look in varyings
1206 ShaderVariable *ioBlockVar = nullptr;
1207 if (qualifier == EvqPerVertexIn)
9
Assuming 'qualifier' is not equal to EvqPerVertexIn
10
Taking false branch
1208 {
1209 TIntermSymbol *symbolNode = blockNode->getAsSymbolNode();
1210 ASSERT(symbolNode)(symbolNode ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1210, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1210 << "): " << "symbolNode"
))
;
1211 recordBuiltInVaryingUsed(symbolNode->variable(), &mPerVertexInAdded, mInputVaryings);
1212 ioBlockVar = FindShaderIOBlockVariable(interfaceBlock->name(), mInputVaryings);
1213 }
1214 else if (IsVaryingIn(qualifier))
11
Assuming the condition is true
12
Taking true branch
1215 {
1216 ioBlockVar = FindShaderIOBlockVariable(interfaceBlock->name(), mInputVaryings);
13
Calling 'FindShaderIOBlockVariable'
17
Returning from 'FindShaderIOBlockVariable'
1217 }
1218 else if (qualifier == EvqPerVertexOut)
1219 {
1220 TIntermSymbol *symbolNode = blockNode->getAsSymbolNode();
1221 ASSERT(symbolNode)(symbolNode ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1221, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1221 << "): " << "symbolNode"
))
;
1222 recordBuiltInVaryingUsed(symbolNode->variable(), &mPerVertexOutAdded, mOutputVaryings);
1223 ioBlockVar = FindShaderIOBlockVariable(interfaceBlock->name(), mOutputVaryings);
1224 }
1225 else if (IsVaryingOut(qualifier))
1226 {
1227 ioBlockVar = FindShaderIOBlockVariable(interfaceBlock->name(), mOutputVaryings);
1228 }
1229
1230 if (ioBlockVar
17.1
'ioBlockVar' is null
)
18
Taking false branch
1231 {
1232 MarkActive(ioBlockVar);
1233 }
1234 else
1235 {
1236 if (!namedBlock
18.1
'namedBlock' is null
)
19
Taking true branch
1237 {
1238 namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
20
Calling 'CollectVariablesTraverser::findNamedInterfaceBlock'
29
Returning from 'CollectVariablesTraverser::findNamedInterfaceBlock'
30
Value assigned to 'namedBlock'
1239 }
1240 ASSERT(namedBlock)(namedBlock ? static_cast<void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage
(::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv
::LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1240, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1240 << "): " << "namedBlock"
))
;
31
Assuming 'namedBlock' is null
32
'?' condition is false
33
Assuming the condition is true
34
'?' condition is true
1241 ASSERT(namedBlock->staticUse)(namedBlock->staticUse ? static_cast<void>(0) : (!((
::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL)))
? static_cast<void>(0) : ::gl::priv::LogMessageVoidify
() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1241, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1241 << "): " << "namedBlock->staticUse"
))
;
35
Access to field 'staticUse' results in a dereference of a null pointer (loaded from variable 'namedBlock')
1242 namedBlock->active = true;
1243 unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
1244 ASSERT(fieldIndex < namedBlock->fields.size())(fieldIndex < namedBlock->fields.size() ? static_cast<
void>(0) : (!((::gl::priv::ShouldCreatePlatformLogMessage(
::gl::LOG_FATAL))) ? static_cast<void>(0) : ::gl::priv::
LogMessageVoidify() & (::gl::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1244, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1244 << "): " << "fieldIndex < namedBlock->fields.size()"
))
;
1245 // TODO(oetuaho): Would be nicer to record static use of fields of named interface
1246 // blocks more accurately at parse time - now we only mark the fields statically used if
1247 // they are active. http://anglebug.com/2440 We need to mark this field and all of its
1248 // sub-fields, as static/active
1249 MarkActive(&namedBlock->fields[fieldIndex]);
1250 }
1251
1252 if (traverseIndexExpression)
1253 {
1254 ASSERT(interfaceIndexingNode)(interfaceIndexingNode ? static_cast<void>(0) : (!((::gl
::priv::ShouldCreatePlatformLogMessage(::gl::LOG_FATAL))) ? static_cast
<void>(0) : ::gl::priv::LogMessageVoidify() & (::gl
::LogMessage("/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
, __FUNCTION__, 1254, ::gl::LOG_FATAL).stream()) << "\t! Assert failed in "
<< __FUNCTION__ << " (" << "/root/firefox-clang/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp"
<< ":" << 1254 << "): " << "interfaceIndexingNode"
))
;
1255 interfaceIndexingNode->getRight()->traverse(this);
1256 }
1257 return false;
1258 }
1259
1260 return true;
1261}
1262
1263} // anonymous namespace
1264
1265void CollectVariables(TIntermBlock *root,
1266 std::vector<ShaderVariable> *attributes,
1267 std::vector<ShaderVariable> *outputVariables,
1268 std::vector<ShaderVariable> *uniforms,
1269 std::vector<ShaderVariable> *inputVaryings,
1270 std::vector<ShaderVariable> *outputVaryings,
1271 std::vector<ShaderVariable> *sharedVariables,
1272 std::vector<InterfaceBlock> *uniformBlocks,
1273 std::vector<InterfaceBlock> *shaderStorageBlocks,
1274 ShHashFunction64 hashFunction,
1275 TSymbolTable *symbolTable,
1276 GLenum shaderType,
1277 const TExtensionBehavior &extensionBehavior,
1278 const ShBuiltInResources &resources,
1279 int tessControlShaderOutputVertices)
1280{
1281 CollectVariablesTraverser collect(
1282 attributes, outputVariables, uniforms, inputVaryings, outputVaryings, sharedVariables,
1283 uniformBlocks, shaderStorageBlocks, hashFunction, symbolTable, shaderType,
1284 extensionBehavior, resources, tessControlShaderOutputVertices);
1285 root->traverse(&collect);
1286}
1287
1288} // namespace sh