Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/compiler/translator/Compiler.cpp
1693 views
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
7
#include "compiler/translator/Compiler.h"
8
9
#include <sstream>
10
11
#include "angle_gl.h"
12
#include "common/utilities.h"
13
#include "compiler/translator/CallDAG.h"
14
#include "compiler/translator/CollectVariables.h"
15
#include "compiler/translator/Initialize.h"
16
#include "compiler/translator/IsASTDepthBelowLimit.h"
17
#include "compiler/translator/OutputTree.h"
18
#include "compiler/translator/ParseContext.h"
19
#include "compiler/translator/ValidateBarrierFunctionCall.h"
20
#include "compiler/translator/ValidateClipCullDistance.h"
21
#include "compiler/translator/ValidateLimitations.h"
22
#include "compiler/translator/ValidateMaxParameters.h"
23
#include "compiler/translator/ValidateOutputs.h"
24
#include "compiler/translator/ValidateTypeSizeLimitations.h"
25
#include "compiler/translator/ValidateVaryingLocations.h"
26
#include "compiler/translator/VariablePacker.h"
27
#include "compiler/translator/tree_ops/ClampIndirectIndices.h"
28
#include "compiler/translator/tree_ops/ClampPointSize.h"
29
#include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
30
#include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
31
#include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
32
#include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
33
#include "compiler/translator/tree_ops/FoldExpressions.h"
34
#include "compiler/translator/tree_ops/ForcePrecisionQualifier.h"
35
#include "compiler/translator/tree_ops/InitializeVariables.h"
36
#include "compiler/translator/tree_ops/PruneEmptyCases.h"
37
#include "compiler/translator/tree_ops/PruneNoOps.h"
38
#include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
39
#include "compiler/translator/tree_ops/RemoveDynamicIndexing.h"
40
#include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"
41
#include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"
42
#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h"
43
#include "compiler/translator/tree_ops/SeparateDeclarations.h"
44
#include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
45
#include "compiler/translator/tree_ops/SplitSequenceOperator.h"
46
#include "compiler/translator/tree_ops/apple/AddAndTrueToLoopCondition.h"
47
#include "compiler/translator/tree_ops/apple/RewriteDoWhile.h"
48
#include "compiler/translator/tree_ops/apple/UnfoldShortCircuitAST.h"
49
#include "compiler/translator/tree_ops/gl/ClampFragDepth.h"
50
#include "compiler/translator/tree_ops/gl/RegenerateStructNames.h"
51
#include "compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h"
52
#include "compiler/translator/tree_ops/gl/UseInterfaceBlockFields.h"
53
#include "compiler/translator/tree_ops/vulkan/EarlyFragmentTestsOptimization.h"
54
#include "compiler/translator/tree_util/BuiltIn.h"
55
#include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
56
#include "compiler/translator/tree_util/ReplaceShadowingVariables.h"
57
#include "compiler/translator/util.h"
58
59
namespace sh
60
{
61
62
namespace
63
{
64
65
#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
66
void DumpFuzzerCase(char const *const *shaderStrings,
67
size_t numStrings,
68
uint32_t type,
69
uint32_t spec,
70
uint32_t output,
71
uint64_t options)
72
{
73
static int fileIndex = 0;
74
75
std::ostringstream o = sh::InitializeStream<std::ostringstream>();
76
o << "corpus/" << fileIndex++ << ".sample";
77
std::string s = o.str();
78
79
// Must match the input format of the fuzzer
80
FILE *f = fopen(s.c_str(), "w");
81
fwrite(&type, sizeof(type), 1, f);
82
fwrite(&spec, sizeof(spec), 1, f);
83
fwrite(&output, sizeof(output), 1, f);
84
fwrite(&options, sizeof(options), 1, f);
85
86
char zero[128 - 20] = {0};
87
fwrite(&zero, 128 - 20, 1, f);
88
89
for (size_t i = 0; i < numStrings; i++)
90
{
91
fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
92
}
93
fwrite(&zero, 1, 1, f);
94
95
fclose(f);
96
}
97
#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
98
} // anonymous namespace
99
100
bool IsGLSL130OrNewer(ShShaderOutput output)
101
{
102
return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
103
output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
104
output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
105
output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
106
output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
107
}
108
109
bool IsGLSL420OrNewer(ShShaderOutput output)
110
{
111
return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
112
output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
113
}
114
115
bool IsGLSL410OrOlder(ShShaderOutput output)
116
{
117
return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
118
output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
119
output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
120
}
121
122
bool RemoveInvariant(sh::GLenum shaderType,
123
int shaderVersion,
124
ShShaderOutput outputType,
125
ShCompileOptions compileOptions)
126
{
127
if (shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
128
return true;
129
130
if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
131
shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
132
return true;
133
134
return false;
135
}
136
137
size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
138
{
139
// WebGL defines a max token length of 256, while ES2 leaves max token
140
// size undefined. ES3 defines a max size of 1024 characters.
141
switch (spec)
142
{
143
case SH_WEBGL_SPEC:
144
return 256;
145
default:
146
return 1024;
147
}
148
}
149
150
int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
151
{
152
switch (shaderType)
153
{
154
case GL_VERTEX_SHADER:
155
return resources.MaxVertexUniformVectors;
156
case GL_FRAGMENT_SHADER:
157
return resources.MaxFragmentUniformVectors;
158
159
// TODO ([email protected]): check if we need finer-grained component counting
160
case GL_COMPUTE_SHADER:
161
return resources.MaxComputeUniformComponents / 4;
162
case GL_GEOMETRY_SHADER_EXT:
163
return resources.MaxGeometryUniformComponents / 4;
164
default:
165
UNREACHABLE();
166
return -1;
167
}
168
}
169
170
namespace
171
{
172
173
class TScopedPoolAllocator
174
{
175
public:
176
TScopedPoolAllocator(angle::PoolAllocator *allocator) : mAllocator(allocator)
177
{
178
mAllocator->push();
179
SetGlobalPoolAllocator(mAllocator);
180
}
181
~TScopedPoolAllocator()
182
{
183
SetGlobalPoolAllocator(nullptr);
184
mAllocator->pop();
185
}
186
187
private:
188
angle::PoolAllocator *mAllocator;
189
};
190
191
class TScopedSymbolTableLevel
192
{
193
public:
194
TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
195
{
196
ASSERT(mTable->isEmpty());
197
mTable->push();
198
}
199
~TScopedSymbolTableLevel()
200
{
201
while (!mTable->isEmpty())
202
mTable->pop();
203
}
204
205
private:
206
TSymbolTable *mTable;
207
};
208
209
int GetMaxShaderVersionForSpec(ShShaderSpec spec)
210
{
211
switch (spec)
212
{
213
case SH_GLES2_SPEC:
214
case SH_WEBGL_SPEC:
215
return 100;
216
case SH_GLES3_SPEC:
217
case SH_WEBGL2_SPEC:
218
return 300;
219
case SH_GLES3_1_SPEC:
220
case SH_WEBGL3_SPEC:
221
return 310;
222
case SH_GLES3_2_SPEC:
223
return 320;
224
case SH_GL_CORE_SPEC:
225
case SH_GL_COMPATIBILITY_SPEC:
226
return 460;
227
default:
228
UNREACHABLE();
229
return 0;
230
}
231
}
232
233
bool ValidateFragColorAndFragData(GLenum shaderType,
234
int shaderVersion,
235
const TSymbolTable &symbolTable,
236
TDiagnostics *diagnostics)
237
{
238
if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
239
{
240
return true;
241
}
242
243
bool usesFragColor = false;
244
bool usesFragData = false;
245
// This validation is a bit stricter than the spec - it's only an error to write to
246
// both FragData and FragColor. But because it's better not to have reads from undefined
247
// variables, we always return an error if they are both referenced, rather than only if they
248
// are written.
249
if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
250
symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
251
{
252
usesFragColor = true;
253
}
254
// Extension variables may not always be initialized (saves some time at symbol table init).
255
bool secondaryFragDataUsed =
256
symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
257
symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
258
if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
259
{
260
usesFragData = true;
261
}
262
if (usesFragColor && usesFragData)
263
{
264
const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
265
if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
266
secondaryFragDataUsed)
267
{
268
errorMessage =
269
"cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
270
" and (gl_FragColor, gl_SecondaryFragColorEXT)";
271
}
272
diagnostics->globalError(errorMessage);
273
return false;
274
}
275
return true;
276
}
277
278
} // namespace
279
280
TShHandleBase::TShHandleBase()
281
{
282
allocator.push();
283
SetGlobalPoolAllocator(&allocator);
284
}
285
286
TShHandleBase::~TShHandleBase()
287
{
288
SetGlobalPoolAllocator(nullptr);
289
allocator.popAll();
290
}
291
292
TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
293
: mVariablesCollected(false),
294
mGLPositionInitialized(false),
295
mShaderType(type),
296
mShaderSpec(spec),
297
mOutputType(output),
298
mBuiltInFunctionEmulator(),
299
mDiagnostics(mInfoSink.info),
300
mSourcePath(nullptr),
301
mComputeShaderLocalSizeDeclared(false),
302
mComputeShaderLocalSize(1),
303
mGeometryShaderMaxVertices(-1),
304
mGeometryShaderInvocations(0),
305
mGeometryShaderInputPrimitiveType(EptUndefined),
306
mGeometryShaderOutputPrimitiveType(EptUndefined),
307
mTessControlShaderOutputVertices(0),
308
mTessEvaluationShaderInputPrimitiveType(EtetUndefined),
309
mTessEvaluationShaderInputVertexSpacingType(EtetUndefined),
310
mTessEvaluationShaderInputOrderingType(EtetUndefined),
311
mTessEvaluationShaderInputPointType(EtetUndefined),
312
mHasAnyPreciseType(false),
313
mCompileOptions(0)
314
{}
315
316
TCompiler::~TCompiler() {}
317
318
bool TCompiler::isHighPrecisionSupported() const
319
{
320
return mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER ||
321
mResources.FragmentPrecisionHigh == 1;
322
}
323
324
bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
325
{
326
// If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
327
// validate loop and indexing as well (to verify that the shader only uses minimal functionality
328
// of ESSL 1.00 as in Appendix A of the spec).
329
return (IsWebGLBasedSpec(mShaderSpec) && mShaderVersion == 100) ||
330
(compileOptions & SH_VALIDATE_LOOP_INDEXING) != 0;
331
}
332
333
bool TCompiler::shouldLimitTypeSizes() const
334
{
335
// WebGL shaders limit the size of variables' types in shaders,
336
// including arrays, structs and interface blocks.
337
return IsWebGLBasedSpec(mShaderSpec);
338
}
339
340
bool TCompiler::Init(const ShBuiltInResources &resources)
341
{
342
SetGlobalPoolAllocator(&allocator);
343
344
// Generate built-in symbol table.
345
if (!initBuiltInSymbolTable(resources))
346
return false;
347
348
mResources = resources;
349
setResourceString();
350
351
InitExtensionBehavior(resources, mExtensionBehavior);
352
return true;
353
}
354
355
TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
356
size_t numStrings,
357
ShCompileOptions compileOptions)
358
{
359
return compileTreeImpl(shaderStrings, numStrings, compileOptions);
360
}
361
362
TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
363
size_t numStrings,
364
const ShCompileOptions compileOptions)
365
{
366
// Remember the compile options for helper functions such as validateAST.
367
mCompileOptions = compileOptions;
368
369
clearResults();
370
371
ASSERT(numStrings > 0);
372
ASSERT(GetGlobalPoolAllocator());
373
374
// Reset the extension behavior for each compilation unit.
375
ResetExtensionBehavior(mResources, mExtensionBehavior, compileOptions);
376
377
// If gl_DrawID is not supported, remove it from the available extensions
378
// Currently we only allow emulation of gl_DrawID
379
const bool glDrawIDSupported = (compileOptions & SH_EMULATE_GL_DRAW_ID) != 0;
380
if (!glDrawIDSupported)
381
{
382
auto it = mExtensionBehavior.find(TExtension::ANGLE_multi_draw);
383
if (it != mExtensionBehavior.end())
384
{
385
mExtensionBehavior.erase(it);
386
}
387
}
388
389
const bool glBaseVertexBaseInstanceSupported =
390
(compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0;
391
if (!glBaseVertexBaseInstanceSupported)
392
{
393
auto it = mExtensionBehavior.find(TExtension::ANGLE_base_vertex_base_instance);
394
if (it != mExtensionBehavior.end())
395
{
396
mExtensionBehavior.erase(it);
397
}
398
}
399
400
// First string is path of source file if flag is set. The actual source follows.
401
size_t firstSource = 0;
402
if ((compileOptions & SH_SOURCE_PATH) != 0)
403
{
404
mSourcePath = shaderStrings[0];
405
++firstSource;
406
}
407
408
TParseContext parseContext(mSymbolTable, mExtensionBehavior, mShaderType, mShaderSpec,
409
compileOptions, !IsDesktopGLSpec(mShaderSpec), &mDiagnostics,
410
getResources(), getOutputType());
411
412
parseContext.setFragmentPrecisionHighOnESSL1(mResources.FragmentPrecisionHigh == 1);
413
414
// We preserve symbols at the built-in level from compile-to-compile.
415
// Start pushing the user-defined symbols at global level.
416
TScopedSymbolTableLevel globalLevel(&mSymbolTable);
417
ASSERT(mSymbolTable.atGlobalLevel());
418
419
// Parse shader.
420
if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
421
&parseContext) != 0)
422
{
423
return nullptr;
424
}
425
426
if (parseContext.getTreeRoot() == nullptr)
427
{
428
return nullptr;
429
}
430
431
setASTMetadata(parseContext);
432
433
if (!checkShaderVersion(&parseContext))
434
{
435
return nullptr;
436
}
437
438
TIntermBlock *root = parseContext.getTreeRoot();
439
if (!checkAndSimplifyAST(root, parseContext, compileOptions))
440
{
441
return nullptr;
442
}
443
444
return root;
445
}
446
447
bool TCompiler::checkShaderVersion(TParseContext *parseContext)
448
{
449
if (GetMaxShaderVersionForSpec(mShaderSpec) < mShaderVersion)
450
{
451
mDiagnostics.globalError("unsupported shader version");
452
return false;
453
}
454
455
ASSERT(parseContext);
456
switch (mShaderType)
457
{
458
case GL_COMPUTE_SHADER:
459
if (mShaderVersion < 310)
460
{
461
mDiagnostics.globalError("Compute shader is not supported in this shader version.");
462
return false;
463
}
464
break;
465
466
case GL_GEOMETRY_SHADER_EXT:
467
if (mShaderVersion < 310)
468
{
469
mDiagnostics.globalError(
470
"Geometry shader is not supported in this shader version.");
471
return false;
472
}
473
else if (mShaderVersion == 310)
474
{
475
if (!parseContext->checkCanUseOneOfExtensions(
476
sh::TSourceLoc(),
477
std::array<TExtension, 2u>{
478
{TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}))
479
{
480
return false;
481
}
482
}
483
break;
484
485
case GL_TESS_CONTROL_SHADER_EXT:
486
case GL_TESS_EVALUATION_SHADER_EXT:
487
if (mShaderVersion < 310)
488
{
489
mDiagnostics.globalError(
490
"Tessellation shaders are not supported in this shader version.");
491
return false;
492
}
493
else if (mShaderVersion == 310)
494
{
495
if (!parseContext->checkCanUseExtension(sh::TSourceLoc(),
496
TExtension::EXT_tessellation_shader))
497
{
498
return false;
499
}
500
}
501
break;
502
503
default:
504
break;
505
}
506
507
return true;
508
}
509
510
void TCompiler::setASTMetadata(const TParseContext &parseContext)
511
{
512
mShaderVersion = parseContext.getShaderVersion();
513
514
mPragma = parseContext.pragma();
515
mSymbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
516
517
mEarlyFragmentTestsSpecified = parseContext.isEarlyFragmentTestsSpecified();
518
519
mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
520
mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
521
522
mNumViews = parseContext.getNumViews();
523
524
mHasAnyPreciseType = parseContext.hasAnyPreciseType();
525
526
if (mShaderType == GL_GEOMETRY_SHADER_EXT)
527
{
528
mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType();
529
mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
530
mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices();
531
mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations();
532
}
533
if (mShaderType == GL_TESS_CONTROL_SHADER_EXT)
534
{
535
mTessControlShaderOutputVertices = parseContext.getTessControlShaderOutputVertices();
536
}
537
if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT)
538
{
539
mTessEvaluationShaderInputPrimitiveType =
540
parseContext.getTessEvaluationShaderInputPrimitiveType();
541
mTessEvaluationShaderInputVertexSpacingType =
542
parseContext.getTessEvaluationShaderInputVertexSpacingType();
543
mTessEvaluationShaderInputOrderingType =
544
parseContext.getTessEvaluationShaderInputOrderingType();
545
mTessEvaluationShaderInputPointType = parseContext.getTessEvaluationShaderInputPointType();
546
}
547
}
548
549
unsigned int TCompiler::getSharedMemorySize() const
550
{
551
unsigned int sharedMemSize = 0;
552
for (const sh::ShaderVariable &var : mSharedVariables)
553
{
554
sharedMemSize += var.getExternalSize();
555
}
556
557
return sharedMemSize;
558
}
559
560
bool TCompiler::validateAST(TIntermNode *root)
561
{
562
if ((mCompileOptions & SH_VALIDATE_AST) != 0)
563
{
564
bool valid = ValidateAST(root, &mDiagnostics, mValidateASTOptions);
565
566
#if defined(ANGLE_ENABLE_ASSERTS)
567
if (!valid)
568
{
569
OutputTree(root, mInfoSink.info);
570
fprintf(stderr, "AST validation error(s):\n%s\n", mInfoSink.info.c_str());
571
}
572
#endif
573
// In debug, assert validation. In release, validation errors will be returned back to the
574
// application as internal ANGLE errors.
575
ASSERT(valid);
576
577
return valid;
578
}
579
return true;
580
}
581
582
bool TCompiler::disableValidateFunctionCall()
583
{
584
bool wasEnabled = mValidateASTOptions.validateFunctionCall;
585
mValidateASTOptions.validateFunctionCall = false;
586
return wasEnabled;
587
}
588
589
void TCompiler::restoreValidateFunctionCall(bool enable)
590
{
591
ASSERT(!mValidateASTOptions.validateFunctionCall);
592
mValidateASTOptions.validateFunctionCall = enable;
593
}
594
595
bool TCompiler::disableValidateVariableReferences()
596
{
597
bool wasEnabled = mValidateASTOptions.validateVariableReferences;
598
mValidateASTOptions.validateVariableReferences = false;
599
return wasEnabled;
600
}
601
602
void TCompiler::restoreValidateVariableReferences(bool enable)
603
{
604
ASSERT(!mValidateASTOptions.validateVariableReferences);
605
mValidateASTOptions.validateVariableReferences = enable;
606
}
607
608
void TCompiler::enableValidateNoMoreTransformations()
609
{
610
mValidateASTOptions.validateNoMoreTransformations = true;
611
}
612
613
bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
614
const TParseContext &parseContext,
615
ShCompileOptions compileOptions)
616
{
617
mValidateASTOptions = {};
618
619
// Desktop GLSL shaders don't have precision, so don't expect them to be specified.
620
mValidateASTOptions.validatePrecision = !IsDesktopGLSpec(mShaderSpec);
621
622
if (!validateAST(root))
623
{
624
return false;
625
}
626
627
// Disallow expressions deemed too complex.
628
if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) != 0 && !limitExpressionComplexity(root))
629
{
630
return false;
631
}
632
633
if (shouldRunLoopAndIndexingValidation(compileOptions) &&
634
!ValidateLimitations(root, mShaderType, &mSymbolTable, &mDiagnostics))
635
{
636
return false;
637
}
638
639
if (shouldLimitTypeSizes() && !ValidateTypeSizeLimitations(root, &mSymbolTable, &mDiagnostics))
640
{
641
return false;
642
}
643
644
if (!ValidateFragColorAndFragData(mShaderType, mShaderVersion, mSymbolTable, &mDiagnostics))
645
{
646
return false;
647
}
648
649
// Fold expressions that could not be folded before validation that was done as a part of
650
// parsing.
651
if (!FoldExpressions(this, root, &mDiagnostics))
652
{
653
return false;
654
}
655
// Folding should only be able to generate warnings.
656
ASSERT(mDiagnostics.numErrors() == 0);
657
658
// Validate no barrier() after return before prunning it in |PruneNoOps()| below.
659
if (mShaderType == GL_TESS_CONTROL_SHADER && !ValidateBarrierFunctionCall(root, &mDiagnostics))
660
{
661
return false;
662
}
663
664
// We prune no-ops to work around driver bugs and to keep AST processing and output simple.
665
// The following kinds of no-ops are pruned:
666
// 1. Empty declarations "int;".
667
// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
668
// for float, so float literal statements would end up with no precision which is
669
// invalid ESSL.
670
// 3. Any unreachable statement after a discard, return, break or continue.
671
// After this empty declarations are not allowed in the AST.
672
if (!PruneNoOps(this, root, &mSymbolTable))
673
{
674
return false;
675
}
676
677
// We need to generate globals early if we have non constant initializers enabled
678
bool initializeLocalsAndGlobals = (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) != 0 &&
679
!IsOutputHLSL(getOutputType());
680
bool canUseLoopsToInitialize =
681
(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES) == 0;
682
bool highPrecisionSupported = isHighPrecisionSupported();
683
bool enableNonConstantInitializers = IsExtensionEnabled(
684
mExtensionBehavior, TExtension::EXT_shader_non_constant_global_initializers);
685
// forceDeferGlobalInitializers is needed for MSL
686
// to convert a non-const global. For example:
687
//
688
// int someGlobal = 123;
689
//
690
// to
691
//
692
// int someGlobal;
693
// void main() {
694
// someGlobal = 123;
695
//
696
// This is because MSL doesn't allow statically initialized globals.
697
bool forceDeferGlobalInitializers = getOutputType() == SH_MSL_METAL_OUTPUT;
698
699
if (enableNonConstantInitializers &&
700
!DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
701
highPrecisionSupported, forceDeferGlobalInitializers,
702
&mSymbolTable))
703
{
704
return false;
705
}
706
707
// Create the function DAG and check there is no recursion
708
if (!initCallDag(root))
709
{
710
return false;
711
}
712
713
if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0 && !checkCallDepth())
714
{
715
return false;
716
}
717
718
// Checks which functions are used and if "main" exists
719
mFunctionMetadata.clear();
720
mFunctionMetadata.resize(mCallDag.size());
721
if (!tagUsedFunctions())
722
{
723
return false;
724
}
725
726
pruneUnusedFunctions(root);
727
if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion))
728
{
729
if (!ReplaceShadowingVariables(this, root, &mSymbolTable))
730
{
731
return false;
732
}
733
}
734
735
if (mShaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, mShaderType))
736
{
737
return false;
738
}
739
740
if (mShaderVersion >= 300 && mShaderType == GL_FRAGMENT_SHADER &&
741
!ValidateOutputs(root, getExtensionBehavior(), mResources.MaxDrawBuffers, &mDiagnostics))
742
{
743
return false;
744
}
745
746
if (parseContext.isExtensionEnabled(TExtension::EXT_clip_cull_distance))
747
{
748
if (!ValidateClipCullDistance(root, &mDiagnostics,
749
mResources.MaxCombinedClipAndCullDistances))
750
{
751
return false;
752
}
753
}
754
755
// Clamping uniform array bounds needs to happen after validateLimitations pass.
756
if ((compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS) != 0)
757
{
758
if (!ClampIndirectIndices(this, root, &mSymbolTable))
759
{
760
return false;
761
}
762
}
763
764
if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) != 0 &&
765
(parseContext.isExtensionEnabled(TExtension::OVR_multiview2) ||
766
parseContext.isExtensionEnabled(TExtension::OVR_multiview)) &&
767
getShaderType() != GL_COMPUTE_SHADER)
768
{
769
if (!DeclareAndInitBuiltinsForInstancedMultiview(
770
this, root, mNumViews, mShaderType, compileOptions, mOutputType, &mSymbolTable))
771
{
772
return false;
773
}
774
}
775
776
// This pass might emit short circuits so keep it before the short circuit unfolding
777
if ((compileOptions & SH_REWRITE_DO_WHILE_LOOPS) != 0)
778
{
779
if (!RewriteDoWhile(this, root, &mSymbolTable))
780
{
781
return false;
782
}
783
}
784
785
if ((compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION) != 0)
786
{
787
if (!AddAndTrueToLoopCondition(this, root))
788
{
789
return false;
790
}
791
}
792
793
if ((compileOptions & SH_UNFOLD_SHORT_CIRCUIT) != 0)
794
{
795
if (!UnfoldShortCircuitAST(this, root))
796
{
797
return false;
798
}
799
}
800
801
if ((compileOptions & SH_REGENERATE_STRUCT_NAMES) != 0)
802
{
803
if (!RegenerateStructNames(this, root, &mSymbolTable))
804
{
805
return false;
806
}
807
}
808
809
if (mShaderType == GL_VERTEX_SHADER &&
810
IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw))
811
{
812
if ((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0)
813
{
814
if (!EmulateGLDrawID(this, root, &mSymbolTable, &mUniforms,
815
shouldCollectVariables(compileOptions)))
816
{
817
return false;
818
}
819
}
820
}
821
822
if (mShaderType == GL_VERTEX_SHADER &&
823
IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_base_vertex_base_instance))
824
{
825
if ((compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0)
826
{
827
if (!EmulateGLBaseVertexBaseInstance(
828
this, root, &mSymbolTable, &mUniforms, shouldCollectVariables(compileOptions),
829
(compileOptions & SH_ADD_BASE_VERTEX_TO_VERTEX_ID) != 0))
830
{
831
return false;
832
}
833
}
834
}
835
836
if (mShaderType == GL_FRAGMENT_SHADER && mShaderVersion == 100 && mResources.EXT_draw_buffers &&
837
mResources.MaxDrawBuffers > 1 &&
838
IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
839
{
840
if (!EmulateGLFragColorBroadcast(this, root, mResources.MaxDrawBuffers, &mOutputVariables,
841
&mSymbolTable, mShaderVersion))
842
{
843
return false;
844
}
845
}
846
847
int simplifyScalarized = (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) != 0
848
? IntermNodePatternMatcher::kScalarizedVecOrMatConstructor
849
: 0;
850
851
// Split multi declarations and remove calls to array length().
852
// Note that SimplifyLoopConditions needs to be run before any other AST transformations
853
// that may need to generate new statements from loop conditions or loop expressions.
854
if (!SimplifyLoopConditions(this, root,
855
IntermNodePatternMatcher::kMultiDeclaration |
856
IntermNodePatternMatcher::kArrayLengthMethod |
857
simplifyScalarized,
858
&getSymbolTable()))
859
{
860
return false;
861
}
862
863
// Note that separate declarations need to be run before other AST transformations that
864
// generate new statements from expressions.
865
if (!SeparateDeclarations(this, root, &getSymbolTable()))
866
{
867
return false;
868
}
869
mValidateASTOptions.validateMultiDeclarations = true;
870
871
if (!SplitSequenceOperator(this, root,
872
IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
873
&getSymbolTable()))
874
{
875
return false;
876
}
877
878
if (!RemoveArrayLengthMethod(this, root))
879
{
880
return false;
881
}
882
883
if (!RemoveUnreferencedVariables(this, root, &mSymbolTable))
884
{
885
return false;
886
}
887
888
// In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
889
// drivers may not accept it. In this case we clean up the dead code from the end of switch
890
// statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
891
// left switch statements that only contained an empty declaration inside the final case in an
892
// invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
893
// run.
894
if (!PruneEmptyCases(this, root))
895
{
896
return false;
897
}
898
899
// Built-in function emulation needs to happen after validateLimitations pass.
900
// TODO(jmadill): Remove global pool allocator.
901
GetGlobalPoolAllocator()->lock();
902
initBuiltInFunctionEmulator(&mBuiltInFunctionEmulator, compileOptions);
903
GetGlobalPoolAllocator()->unlock();
904
mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
905
906
if ((compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) != 0)
907
{
908
if (!ScalarizeVecAndMatConstructorArgs(this, root, &mSymbolTable))
909
{
910
return false;
911
}
912
}
913
914
if ((compileOptions & SH_FORCE_SHADER_PRECISION_HIGHP_TO_MEDIUMP) != 0)
915
{
916
if (!ForceShaderPrecisionToMediump(root, &mSymbolTable, mShaderType))
917
{
918
return false;
919
}
920
}
921
922
if (shouldCollectVariables(compileOptions))
923
{
924
ASSERT(!mVariablesCollected);
925
CollectVariables(root, &mAttributes, &mOutputVariables, &mUniforms, &mInputVaryings,
926
&mOutputVaryings, &mSharedVariables, &mUniformBlocks,
927
&mShaderStorageBlocks, mResources.HashFunction, &mSymbolTable, mShaderType,
928
mExtensionBehavior, mResources, mTessControlShaderOutputVertices);
929
collectInterfaceBlocks();
930
mVariablesCollected = true;
931
if ((compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS) != 0)
932
{
933
if (!useAllMembersInUnusedStandardAndSharedBlocks(root))
934
{
935
return false;
936
}
937
}
938
if ((compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) != 0)
939
{
940
int maxUniformVectors = GetMaxUniformVectorsForShaderType(mShaderType, mResources);
941
// Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
942
// Appendix A, section 7, the shader does not use too many uniforms.
943
if (!CheckVariablesInPackingLimits(maxUniformVectors, mUniforms))
944
{
945
mDiagnostics.globalError("too many uniforms");
946
return false;
947
}
948
}
949
bool needInitializeOutputVariables =
950
(compileOptions & SH_INIT_OUTPUT_VARIABLES) != 0 && mShaderType != GL_COMPUTE_SHADER;
951
needInitializeOutputVariables |=
952
(compileOptions & SH_INIT_FRAGMENT_OUTPUT_VARIABLES) != 0 &&
953
mShaderType == GL_FRAGMENT_SHADER;
954
if (needInitializeOutputVariables)
955
{
956
if (!initializeOutputVariables(root))
957
{
958
return false;
959
}
960
}
961
}
962
963
// Removing invariant declarations must be done after collecting variables.
964
// Otherwise, built-in invariant declarations don't apply.
965
if (RemoveInvariant(mShaderType, mShaderVersion, mOutputType, compileOptions))
966
{
967
if (!RemoveInvariantDeclaration(this, root))
968
{
969
return false;
970
}
971
}
972
973
// gl_Position is always written in compatibility output mode.
974
// It may have been already initialized among other output variables, in that case we don't
975
// need to initialize it twice.
976
if (mShaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
977
((compileOptions & SH_INIT_GL_POSITION) != 0 ||
978
mOutputType == SH_GLSL_COMPATIBILITY_OUTPUT))
979
{
980
if (!initializeGLPosition(root))
981
{
982
return false;
983
}
984
mGLPositionInitialized = true;
985
}
986
987
// DeferGlobalInitializers needs to be run before other AST transformations that generate new
988
// statements from expressions. But it's fine to run DeferGlobalInitializers after the above
989
// SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
990
// on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
991
// Exception: if EXT_shader_non_constant_global_initializers is enabled, we must generate global
992
// initializers before we generate the DAG, since initializers may call functions which must not
993
// be optimized out
994
if (!enableNonConstantInitializers &&
995
!DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
996
highPrecisionSupported, forceDeferGlobalInitializers,
997
&mSymbolTable))
998
{
999
return false;
1000
}
1001
1002
if (initializeLocalsAndGlobals)
1003
{
1004
// Initialize uninitialized local variables.
1005
// In some cases initializing can generate extra statements in the parent block, such as
1006
// when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
1007
// we need to first simplify loop conditions. We've already separated declarations
1008
// earlier, which is also required. If we don't follow the Appendix A limitations, loop
1009
// init statements can declare arrays or nameless structs and have multiple
1010
// declarations.
1011
1012
if (!shouldRunLoopAndIndexingValidation(compileOptions))
1013
{
1014
if (!SimplifyLoopConditions(this, root,
1015
IntermNodePatternMatcher::kArrayDeclaration |
1016
IntermNodePatternMatcher::kNamelessStructDeclaration,
1017
&getSymbolTable()))
1018
{
1019
return false;
1020
}
1021
}
1022
1023
if (!InitializeUninitializedLocals(this, root, getShaderVersion(), canUseLoopsToInitialize,
1024
highPrecisionSupported, &getSymbolTable()))
1025
{
1026
return false;
1027
}
1028
}
1029
1030
if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE) != 0)
1031
{
1032
if (!ClampPointSize(this, root, mResources.MaxPointSize, &getSymbolTable()))
1033
{
1034
return false;
1035
}
1036
}
1037
1038
if (getShaderType() == GL_FRAGMENT_SHADER && (compileOptions & SH_CLAMP_FRAG_DEPTH) != 0)
1039
{
1040
if (!ClampFragDepth(this, root, &getSymbolTable()))
1041
{
1042
return false;
1043
}
1044
}
1045
1046
if ((compileOptions & SH_REWRITE_REPEATED_ASSIGN_TO_SWIZZLED) != 0)
1047
{
1048
if (!sh::RewriteRepeatedAssignToSwizzled(this, root))
1049
{
1050
return false;
1051
}
1052
}
1053
1054
if ((compileOptions & SH_REMOVE_DYNAMIC_INDEXING_OF_SWIZZLED_VECTOR) != 0)
1055
{
1056
if (!sh::RemoveDynamicIndexingOfSwizzledVector(this, root, &getSymbolTable(), nullptr))
1057
{
1058
return false;
1059
}
1060
}
1061
1062
mEarlyFragmentTestsOptimized = false;
1063
if ((compileOptions & SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION) != 0)
1064
{
1065
if (mShaderVersion <= 300 && mShaderType == GL_FRAGMENT_SHADER &&
1066
!isEarlyFragmentTestsSpecified())
1067
{
1068
mEarlyFragmentTestsOptimized = CheckEarlyFragmentTestsFeasible(this, root);
1069
}
1070
}
1071
1072
return true;
1073
}
1074
1075
bool TCompiler::compile(const char *const shaderStrings[],
1076
size_t numStrings,
1077
ShCompileOptions compileOptionsIn)
1078
{
1079
#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
1080
DumpFuzzerCase(shaderStrings, numStrings, mShaderType, mShaderSpec, mOutputType,
1081
compileOptionsIn);
1082
#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
1083
1084
if (numStrings == 0)
1085
return true;
1086
1087
ShCompileOptions compileOptions = compileOptionsIn;
1088
1089
// Apply key workarounds.
1090
if (shouldFlattenPragmaStdglInvariantAll())
1091
{
1092
// This should be harmless to do in all cases, but for the moment, do it only conditionally.
1093
compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
1094
}
1095
1096
TScopedPoolAllocator scopedAlloc(&allocator);
1097
TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
1098
1099
if (root)
1100
{
1101
if ((compileOptions & SH_INTERMEDIATE_TREE) != 0)
1102
{
1103
OutputTree(root, mInfoSink.info);
1104
}
1105
1106
if ((compileOptions & SH_OBJECT_CODE) != 0)
1107
{
1108
PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
1109
if (!translate(root, compileOptions, &perfDiagnostics))
1110
{
1111
return false;
1112
}
1113
}
1114
1115
if (mShaderType == GL_VERTEX_SHADER)
1116
{
1117
bool lookForDrawID =
1118
IsExtensionEnabled(mExtensionBehavior, TExtension::ANGLE_multi_draw) &&
1119
(compileOptions & SH_EMULATE_GL_DRAW_ID) != 0;
1120
bool lookForBaseVertexBaseInstance =
1121
IsExtensionEnabled(mExtensionBehavior,
1122
TExtension::ANGLE_base_vertex_base_instance) &&
1123
(compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0;
1124
1125
if (lookForDrawID || lookForBaseVertexBaseInstance)
1126
{
1127
for (auto &uniform : mUniforms)
1128
{
1129
if (lookForDrawID && uniform.name == "angle_DrawID" &&
1130
uniform.mappedName == "angle_DrawID")
1131
{
1132
uniform.name = "gl_DrawID";
1133
}
1134
else if (lookForBaseVertexBaseInstance && uniform.name == "angle_BaseVertex" &&
1135
uniform.mappedName == "angle_BaseVertex")
1136
{
1137
uniform.name = "gl_BaseVertex";
1138
}
1139
else if (lookForBaseVertexBaseInstance &&
1140
uniform.name == "angle_BaseInstance" &&
1141
uniform.mappedName == "angle_BaseInstance")
1142
{
1143
uniform.name = "gl_BaseInstance";
1144
}
1145
}
1146
}
1147
}
1148
1149
// The IntermNode tree doesn't need to be deleted here, since the
1150
// memory will be freed in a big chunk by the PoolAllocator.
1151
return true;
1152
}
1153
return false;
1154
}
1155
1156
bool TCompiler::initBuiltInSymbolTable(const ShBuiltInResources &resources)
1157
{
1158
if (resources.MaxDrawBuffers < 1)
1159
{
1160
return false;
1161
}
1162
if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
1163
{
1164
return false;
1165
}
1166
1167
mSymbolTable.initializeBuiltIns(mShaderType, mShaderSpec, resources);
1168
1169
return true;
1170
}
1171
1172
void TCompiler::setResourceString()
1173
{
1174
std::ostringstream strstream = sh::InitializeStream<std::ostringstream>();
1175
1176
// clang-format off
1177
strstream << ":MaxVertexAttribs:" << mResources.MaxVertexAttribs
1178
<< ":MaxVertexUniformVectors:" << mResources.MaxVertexUniformVectors
1179
<< ":MaxVaryingVectors:" << mResources.MaxVaryingVectors
1180
<< ":MaxVertexTextureImageUnits:" << mResources.MaxVertexTextureImageUnits
1181
<< ":MaxCombinedTextureImageUnits:" << mResources.MaxCombinedTextureImageUnits
1182
<< ":MaxTextureImageUnits:" << mResources.MaxTextureImageUnits
1183
<< ":MaxFragmentUniformVectors:" << mResources.MaxFragmentUniformVectors
1184
<< ":MaxDrawBuffers:" << mResources.MaxDrawBuffers
1185
<< ":OES_standard_derivatives:" << mResources.OES_standard_derivatives
1186
<< ":OES_EGL_image_external:" << mResources.OES_EGL_image_external
1187
<< ":OES_EGL_image_external_essl3:" << mResources.OES_EGL_image_external_essl3
1188
<< ":NV_EGL_stream_consumer_external:" << mResources.NV_EGL_stream_consumer_external
1189
<< ":ARB_texture_rectangle:" << mResources.ARB_texture_rectangle
1190
<< ":EXT_draw_buffers:" << mResources.EXT_draw_buffers
1191
<< ":FragmentPrecisionHigh:" << mResources.FragmentPrecisionHigh
1192
<< ":MaxExpressionComplexity:" << mResources.MaxExpressionComplexity
1193
<< ":MaxCallStackDepth:" << mResources.MaxCallStackDepth
1194
<< ":MaxFunctionParameters:" << mResources.MaxFunctionParameters
1195
<< ":EXT_blend_func_extended:" << mResources.EXT_blend_func_extended
1196
<< ":EXT_frag_depth:" << mResources.EXT_frag_depth
1197
<< ":EXT_primitive_bounding_box:" << mResources.EXT_primitive_bounding_box
1198
<< ":EXT_shader_texture_lod:" << mResources.EXT_shader_texture_lod
1199
<< ":EXT_shader_framebuffer_fetch:" << mResources.EXT_shader_framebuffer_fetch
1200
<< ":EXT_shader_framebuffer_fetch_non_coherent:" << mResources.EXT_shader_framebuffer_fetch_non_coherent
1201
<< ":NV_shader_framebuffer_fetch:" << mResources.NV_shader_framebuffer_fetch
1202
<< ":ARM_shader_framebuffer_fetch:" << mResources.ARM_shader_framebuffer_fetch
1203
<< ":OVR_multiview2:" << mResources.OVR_multiview2
1204
<< ":OVR_multiview:" << mResources.OVR_multiview
1205
<< ":EXT_YUV_target:" << mResources.EXT_YUV_target
1206
<< ":EXT_geometry_shader:" << mResources.EXT_geometry_shader
1207
<< ":OES_geometry_shader:" << mResources.OES_geometry_shader
1208
<< ":OES_shader_io_blocks:" << mResources.OES_shader_io_blocks
1209
<< ":EXT_shader_io_blocks:" << mResources.EXT_shader_io_blocks
1210
<< ":EXT_gpu_shader5:" << mResources.EXT_gpu_shader5
1211
<< ":OES_texture_3D:" << mResources.OES_texture_3D
1212
<< ":MaxVertexOutputVectors:" << mResources.MaxVertexOutputVectors
1213
<< ":MaxFragmentInputVectors:" << mResources.MaxFragmentInputVectors
1214
<< ":MinProgramTexelOffset:" << mResources.MinProgramTexelOffset
1215
<< ":MaxProgramTexelOffset:" << mResources.MaxProgramTexelOffset
1216
<< ":MaxDualSourceDrawBuffers:" << mResources.MaxDualSourceDrawBuffers
1217
<< ":MaxViewsOVR:" << mResources.MaxViewsOVR
1218
<< ":NV_draw_buffers:" << mResources.NV_draw_buffers
1219
<< ":ANGLE_multi_draw:" << mResources.ANGLE_multi_draw
1220
<< ":ANGLE_base_vertex_base_instance:" << mResources.ANGLE_base_vertex_base_instance
1221
<< ":APPLE_clip_distance:" << mResources.APPLE_clip_distance
1222
<< ":OES_texture_cube_map_array:" << mResources.OES_texture_cube_map_array
1223
<< ":EXT_texture_cube_map_array:" << mResources.EXT_texture_cube_map_array
1224
<< ":EXT_shadow_samplers:" << mResources.EXT_shadow_samplers
1225
<< ":OES_shader_multisample_interpolation:" << mResources.OES_shader_multisample_interpolation
1226
<< ":OES_shader_image_atomic:" << mResources.OES_shader_image_atomic
1227
<< ":EXT_tessellation_shader:" << mResources.EXT_tessellation_shader
1228
<< ":OES_texture_buffer:" << mResources.OES_texture_buffer
1229
<< ":EXT_texture_buffer:" << mResources.EXT_texture_buffer
1230
<< ":OES_sample_variables:" << mResources.OES_sample_variables
1231
<< ":EXT_clip_cull_distance:" << mResources.EXT_clip_cull_distance
1232
<< ":MinProgramTextureGatherOffset:" << mResources.MinProgramTextureGatherOffset
1233
<< ":MaxProgramTextureGatherOffset:" << mResources.MaxProgramTextureGatherOffset
1234
<< ":MaxImageUnits:" << mResources.MaxImageUnits
1235
<< ":MaxSamples:" << mResources.MaxSamples
1236
<< ":MaxVertexImageUniforms:" << mResources.MaxVertexImageUniforms
1237
<< ":MaxFragmentImageUniforms:" << mResources.MaxFragmentImageUniforms
1238
<< ":MaxComputeImageUniforms:" << mResources.MaxComputeImageUniforms
1239
<< ":MaxCombinedImageUniforms:" << mResources.MaxCombinedImageUniforms
1240
<< ":MaxCombinedShaderOutputResources:" << mResources.MaxCombinedShaderOutputResources
1241
<< ":MaxComputeWorkGroupCountX:" << mResources.MaxComputeWorkGroupCount[0]
1242
<< ":MaxComputeWorkGroupCountY:" << mResources.MaxComputeWorkGroupCount[1]
1243
<< ":MaxComputeWorkGroupCountZ:" << mResources.MaxComputeWorkGroupCount[2]
1244
<< ":MaxComputeWorkGroupSizeX:" << mResources.MaxComputeWorkGroupSize[0]
1245
<< ":MaxComputeWorkGroupSizeY:" << mResources.MaxComputeWorkGroupSize[1]
1246
<< ":MaxComputeWorkGroupSizeZ:" << mResources.MaxComputeWorkGroupSize[2]
1247
<< ":MaxComputeUniformComponents:" << mResources.MaxComputeUniformComponents
1248
<< ":MaxComputeTextureImageUnits:" << mResources.MaxComputeTextureImageUnits
1249
<< ":MaxComputeAtomicCounters:" << mResources.MaxComputeAtomicCounters
1250
<< ":MaxComputeAtomicCounterBuffers:" << mResources.MaxComputeAtomicCounterBuffers
1251
<< ":MaxVertexAtomicCounters:" << mResources.MaxVertexAtomicCounters
1252
<< ":MaxFragmentAtomicCounters:" << mResources.MaxFragmentAtomicCounters
1253
<< ":MaxCombinedAtomicCounters:" << mResources.MaxCombinedAtomicCounters
1254
<< ":MaxAtomicCounterBindings:" << mResources.MaxAtomicCounterBindings
1255
<< ":MaxVertexAtomicCounterBuffers:" << mResources.MaxVertexAtomicCounterBuffers
1256
<< ":MaxFragmentAtomicCounterBuffers:" << mResources.MaxFragmentAtomicCounterBuffers
1257
<< ":MaxCombinedAtomicCounterBuffers:" << mResources.MaxCombinedAtomicCounterBuffers
1258
<< ":MaxAtomicCounterBufferSize:" << mResources.MaxAtomicCounterBufferSize
1259
<< ":MaxGeometryUniformComponents:" << mResources.MaxGeometryUniformComponents
1260
<< ":MaxGeometryUniformBlocks:" << mResources.MaxGeometryUniformBlocks
1261
<< ":MaxGeometryInputComponents:" << mResources.MaxGeometryInputComponents
1262
<< ":MaxGeometryOutputComponents:" << mResources.MaxGeometryOutputComponents
1263
<< ":MaxGeometryOutputVertices:" << mResources.MaxGeometryOutputVertices
1264
<< ":MaxGeometryTotalOutputComponents:" << mResources.MaxGeometryTotalOutputComponents
1265
<< ":MaxGeometryTextureImageUnits:" << mResources.MaxGeometryTextureImageUnits
1266
<< ":MaxGeometryAtomicCounterBuffers:" << mResources.MaxGeometryAtomicCounterBuffers
1267
<< ":MaxGeometryAtomicCounters:" << mResources.MaxGeometryAtomicCounters
1268
<< ":MaxGeometryShaderStorageBlocks:" << mResources.MaxGeometryShaderStorageBlocks
1269
<< ":MaxGeometryShaderInvocations:" << mResources.MaxGeometryShaderInvocations
1270
<< ":MaxGeometryImageUniforms:" << mResources.MaxGeometryImageUniforms
1271
<< ":MaxClipDistances" << mResources.MaxClipDistances
1272
<< ":MaxCullDistances" << mResources.MaxCullDistances
1273
<< ":MaxCombinedClipAndCullDistances" << mResources.MaxCombinedClipAndCullDistances
1274
<< ":MaxTessControlInputComponents:" << mResources.MaxTessControlInputComponents
1275
<< ":MaxTessControlOutputComponents:" << mResources.MaxTessControlOutputComponents
1276
<< ":MaxTessControlTextureImageUnits:" << mResources.MaxTessControlTextureImageUnits
1277
<< ":MaxTessControlUniformComponents:" << mResources.MaxTessControlUniformComponents
1278
<< ":MaxTessControlTotalOutputComponents:" << mResources.MaxTessControlTotalOutputComponents
1279
<< ":MaxTessControlImageUniforms:" << mResources.MaxTessControlImageUniforms
1280
<< ":MaxTessControlAtomicCounters:" << mResources.MaxTessControlAtomicCounters
1281
<< ":MaxTessControlAtomicCounterBuffers:" << mResources.MaxTessControlAtomicCounterBuffers
1282
<< ":MaxTessPatchComponents:" << mResources.MaxTessPatchComponents
1283
<< ":MaxPatchVertices:" << mResources.MaxPatchVertices
1284
<< ":MaxTessGenLevel:" << mResources.MaxTessGenLevel
1285
<< ":MaxTessEvaluationInputComponents:" << mResources.MaxTessEvaluationInputComponents
1286
<< ":MaxTessEvaluationOutputComponents:" << mResources.MaxTessEvaluationOutputComponents
1287
<< ":MaxTessEvaluationTextureImageUnits:" << mResources.MaxTessEvaluationTextureImageUnits
1288
<< ":MaxTessEvaluationUniformComponents:" << mResources.MaxTessEvaluationUniformComponents
1289
<< ":MaxTessEvaluationImageUniforms:" << mResources.MaxTessEvaluationImageUniforms
1290
<< ":MaxTessEvaluationAtomicCounters:" << mResources.MaxTessEvaluationAtomicCounters
1291
<< ":MaxTessEvaluationAtomicCounterBuffers:" << mResources.MaxTessEvaluationAtomicCounterBuffers;
1292
// clang-format on
1293
1294
mBuiltInResourcesString = strstream.str();
1295
}
1296
1297
void TCompiler::collectInterfaceBlocks()
1298
{
1299
ASSERT(mInterfaceBlocks.empty());
1300
mInterfaceBlocks.reserve(mUniformBlocks.size() + mShaderStorageBlocks.size());
1301
mInterfaceBlocks.insert(mInterfaceBlocks.end(), mUniformBlocks.begin(), mUniformBlocks.end());
1302
mInterfaceBlocks.insert(mInterfaceBlocks.end(), mShaderStorageBlocks.begin(),
1303
mShaderStorageBlocks.end());
1304
}
1305
1306
void TCompiler::clearResults()
1307
{
1308
mInfoSink.info.erase();
1309
mInfoSink.obj.erase();
1310
mInfoSink.debug.erase();
1311
mDiagnostics.resetErrorCount();
1312
1313
mAttributes.clear();
1314
mOutputVariables.clear();
1315
mUniforms.clear();
1316
mInputVaryings.clear();
1317
mOutputVaryings.clear();
1318
mSharedVariables.clear();
1319
mInterfaceBlocks.clear();
1320
mUniformBlocks.clear();
1321
mShaderStorageBlocks.clear();
1322
mVariablesCollected = false;
1323
mGLPositionInitialized = false;
1324
1325
mNumViews = -1;
1326
1327
mGeometryShaderInputPrimitiveType = EptUndefined;
1328
mGeometryShaderOutputPrimitiveType = EptUndefined;
1329
mGeometryShaderInvocations = 0;
1330
mGeometryShaderMaxVertices = -1;
1331
1332
mTessControlShaderOutputVertices = 0;
1333
mTessEvaluationShaderInputPrimitiveType = EtetUndefined;
1334
mTessEvaluationShaderInputVertexSpacingType = EtetUndefined;
1335
mTessEvaluationShaderInputOrderingType = EtetUndefined;
1336
mTessEvaluationShaderInputPointType = EtetUndefined;
1337
1338
mBuiltInFunctionEmulator.cleanup();
1339
1340
mNameMap.clear();
1341
1342
mSourcePath = nullptr;
1343
1344
mSymbolTable.clearCompilationResults();
1345
}
1346
1347
bool TCompiler::initCallDag(TIntermNode *root)
1348
{
1349
mCallDag.clear();
1350
1351
switch (mCallDag.init(root, &mDiagnostics))
1352
{
1353
case CallDAG::INITDAG_SUCCESS:
1354
return true;
1355
case CallDAG::INITDAG_RECURSION:
1356
case CallDAG::INITDAG_UNDEFINED:
1357
// Error message has already been written out.
1358
ASSERT(mDiagnostics.numErrors() > 0);
1359
return false;
1360
}
1361
1362
UNREACHABLE();
1363
return true;
1364
}
1365
1366
bool TCompiler::checkCallDepth()
1367
{
1368
std::vector<int> depths(mCallDag.size());
1369
1370
for (size_t i = 0; i < mCallDag.size(); i++)
1371
{
1372
int depth = 0;
1373
const CallDAG::Record &record = mCallDag.getRecordFromIndex(i);
1374
1375
for (int calleeIndex : record.callees)
1376
{
1377
depth = std::max(depth, depths[calleeIndex] + 1);
1378
}
1379
1380
depths[i] = depth;
1381
1382
if (depth >= mResources.MaxCallStackDepth)
1383
{
1384
// Trace back the function chain to have a meaningful info log.
1385
std::stringstream errorStream = sh::InitializeStream<std::stringstream>();
1386
errorStream << "Call stack too deep (larger than " << mResources.MaxCallStackDepth
1387
<< ") with the following call chain: "
1388
<< record.node->getFunction()->name();
1389
1390
int currentFunction = static_cast<int>(i);
1391
int currentDepth = depth;
1392
1393
while (currentFunction != -1)
1394
{
1395
errorStream
1396
<< " -> "
1397
<< mCallDag.getRecordFromIndex(currentFunction).node->getFunction()->name();
1398
1399
int nextFunction = -1;
1400
for (const int &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
1401
{
1402
if (depths[calleeIndex] == currentDepth - 1)
1403
{
1404
currentDepth--;
1405
nextFunction = calleeIndex;
1406
}
1407
}
1408
1409
currentFunction = nextFunction;
1410
}
1411
1412
std::string errorStr = errorStream.str();
1413
mDiagnostics.globalError(errorStr.c_str());
1414
1415
return false;
1416
}
1417
}
1418
1419
return true;
1420
}
1421
1422
bool TCompiler::tagUsedFunctions()
1423
{
1424
// Search from main, starting from the end of the DAG as it usually is the root.
1425
for (size_t i = mCallDag.size(); i-- > 0;)
1426
{
1427
if (mCallDag.getRecordFromIndex(i).node->getFunction()->isMain())
1428
{
1429
internalTagUsedFunction(i);
1430
return true;
1431
}
1432
}
1433
1434
mDiagnostics.globalError("Missing main()");
1435
return false;
1436
}
1437
1438
void TCompiler::internalTagUsedFunction(size_t index)
1439
{
1440
if (mFunctionMetadata[index].used)
1441
{
1442
return;
1443
}
1444
1445
mFunctionMetadata[index].used = true;
1446
1447
for (int calleeIndex : mCallDag.getRecordFromIndex(index).callees)
1448
{
1449
internalTagUsedFunction(calleeIndex);
1450
}
1451
}
1452
1453
// A predicate for the stl that returns if a top-level node is unused
1454
class TCompiler::UnusedPredicate
1455
{
1456
public:
1457
UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
1458
: mCallDag(callDag), mMetadatas(metadatas)
1459
{}
1460
1461
bool operator()(TIntermNode *node)
1462
{
1463
const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode();
1464
const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
1465
1466
const TFunction *func = nullptr;
1467
1468
if (asFunctionDefinition)
1469
{
1470
func = asFunctionDefinition->getFunction();
1471
}
1472
else if (asFunctionPrototype)
1473
{
1474
func = asFunctionPrototype->getFunction();
1475
}
1476
if (func == nullptr)
1477
{
1478
return false;
1479
}
1480
1481
size_t callDagIndex = mCallDag->findIndex(func->uniqueId());
1482
if (callDagIndex == CallDAG::InvalidIndex)
1483
{
1484
// This happens only for unimplemented prototypes which are thus unused
1485
ASSERT(asFunctionPrototype);
1486
return true;
1487
}
1488
1489
ASSERT(callDagIndex < mMetadatas->size());
1490
return !(*mMetadatas)[callDagIndex].used;
1491
}
1492
1493
private:
1494
const CallDAG *mCallDag;
1495
const std::vector<FunctionMetadata> *mMetadatas;
1496
};
1497
1498
void TCompiler::pruneUnusedFunctions(TIntermBlock *root)
1499
{
1500
UnusedPredicate isUnused(&mCallDag, &mFunctionMetadata);
1501
TIntermSequence *sequence = root->getSequence();
1502
1503
if (!sequence->empty())
1504
{
1505
sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
1506
sequence->end());
1507
}
1508
}
1509
1510
bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
1511
{
1512
if (!IsASTDepthBelowLimit(root, mResources.MaxExpressionComplexity))
1513
{
1514
mDiagnostics.globalError("Expression too complex.");
1515
return false;
1516
}
1517
1518
if (!ValidateMaxParameters(root, mResources.MaxFunctionParameters))
1519
{
1520
mDiagnostics.globalError("Function has too many parameters.");
1521
return false;
1522
}
1523
1524
return true;
1525
}
1526
1527
bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
1528
{
1529
return (compileOptions & SH_VARIABLES) != 0;
1530
}
1531
1532
bool TCompiler::wereVariablesCollected() const
1533
{
1534
return mVariablesCollected;
1535
}
1536
1537
bool TCompiler::initializeGLPosition(TIntermBlock *root)
1538
{
1539
sh::ShaderVariable var(GL_FLOAT_VEC4);
1540
var.name = "gl_Position";
1541
return InitializeVariables(this, root, {var}, &mSymbolTable, mShaderVersion, mExtensionBehavior,
1542
false, false);
1543
}
1544
1545
bool TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
1546
{
1547
sh::InterfaceBlockList list;
1548
1549
for (const sh::InterfaceBlock &block : mUniformBlocks)
1550
{
1551
if (!block.staticUse &&
1552
(block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
1553
{
1554
list.push_back(block);
1555
}
1556
}
1557
1558
return sh::UseInterfaceBlockFields(this, root, list, mSymbolTable);
1559
}
1560
1561
bool TCompiler::initializeOutputVariables(TIntermBlock *root)
1562
{
1563
InitVariableList list;
1564
list.reserve(mOutputVaryings.size());
1565
if (mShaderType == GL_VERTEX_SHADER || mShaderType == GL_GEOMETRY_SHADER_EXT)
1566
{
1567
for (const sh::ShaderVariable &var : mOutputVaryings)
1568
{
1569
list.push_back(var);
1570
if (var.name == "gl_Position")
1571
{
1572
ASSERT(!mGLPositionInitialized);
1573
mGLPositionInitialized = true;
1574
}
1575
}
1576
}
1577
else
1578
{
1579
ASSERT(mShaderType == GL_FRAGMENT_SHADER);
1580
for (const sh::ShaderVariable &var : mOutputVariables)
1581
{
1582
list.push_back(var);
1583
}
1584
}
1585
return InitializeVariables(this, root, list, &mSymbolTable, mShaderVersion, mExtensionBehavior,
1586
false, false);
1587
}
1588
1589
const TExtensionBehavior &TCompiler::getExtensionBehavior() const
1590
{
1591
return mExtensionBehavior;
1592
}
1593
1594
const char *TCompiler::getSourcePath() const
1595
{
1596
return mSourcePath;
1597
}
1598
1599
const ShBuiltInResources &TCompiler::getResources() const
1600
{
1601
return mResources;
1602
}
1603
1604
const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
1605
{
1606
return mBuiltInFunctionEmulator;
1607
}
1608
1609
bool TCompiler::isVaryingDefined(const char *varyingName)
1610
{
1611
ASSERT(mVariablesCollected);
1612
for (size_t ii = 0; ii < mInputVaryings.size(); ++ii)
1613
{
1614
if (mInputVaryings[ii].name == varyingName)
1615
{
1616
return true;
1617
}
1618
}
1619
for (size_t ii = 0; ii < mOutputVaryings.size(); ++ii)
1620
{
1621
if (mOutputVaryings[ii].name == varyingName)
1622
{
1623
return true;
1624
}
1625
}
1626
1627
return false;
1628
}
1629
1630
} // namespace sh
1631
1632