GLSL: Fix initializing globals declared after main()
Initialize globals in a separate function instead of a block in the
beginning of main(). This way it works also for globals declared after
main().
BUG=chromium:764036
TEST=angle_end2end_tests
Change-Id: I2fcbb97d046589301287757dc3dde5471172a3f6
Reviewed-on: https://chromium-review.googlesource.com/663158
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index c7da64f..44578c1 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -523,7 +523,7 @@
if (success)
{
- DeferGlobalInitializers(root, needToInitializeGlobalsInAST());
+ DeferGlobalInitializers(root, needToInitializeGlobalsInAST(), &symbolTable);
}
if (success && (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && getOutputType())
diff --git a/src/compiler/translator/DeferGlobalInitializers.cpp b/src/compiler/translator/DeferGlobalInitializers.cpp
index 67ccdf6..9a0073e 100644
--- a/src/compiler/translator/DeferGlobalInitializers.cpp
+++ b/src/compiler/translator/DeferGlobalInitializers.cpp
@@ -3,11 +3,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// DeferGlobalInitializers is an AST traverser that moves global initializers into a block in the
-// beginning of main(). This enables initialization of globals with uniforms or non-constant
-// globals, as allowed by the WebGL spec. Some initializers referencing non-constants may need to be
-// unfolded into if statements in HLSL - this kind of steps should be done after
-// DeferGlobalInitializers is run.
+// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate
+// function that is called in the beginning of main(). This enables initialization of globals with
+// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing
+// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be
+// done after DeferGlobalInitializers is run. Note that it's important that the function definition
+// is at the end of the shader, as some globals may be declared after main().
//
// It can also initialize all uninitialized globals.
//
@@ -17,6 +18,7 @@
#include "compiler/translator/FindMain.h"
#include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/SymbolTable.h"
namespace sh
@@ -100,19 +102,36 @@
}
}
-void InsertInitCodeToMain(TIntermBlock *root, TIntermSequence *deferredInitializers)
+void InsertInitCallToMain(TIntermBlock *root,
+ TIntermSequence *deferredInitializers,
+ TSymbolTable *symbolTable)
{
- // Insert init code as a block to the beginning of the main() function.
TIntermBlock *initGlobalsBlock = new TIntermBlock();
initGlobalsBlock->getSequence()->swap(*deferredInitializers);
+ TSymbolUniqueId initGlobalsFunctionId(symbolTable);
+
+ const char *kInitGlobalsFunctionName = "initGlobals";
+
+ TIntermFunctionPrototype *initGlobalsFunctionPrototype =
+ CreateInternalFunctionPrototypeNode(TType(), kInitGlobalsFunctionName, initGlobalsFunctionId);
+ root->getSequence()->insert(root->getSequence()->begin(), initGlobalsFunctionPrototype);
+ TIntermFunctionDefinition *initGlobalsFunctionDefinition = CreateInternalFunctionDefinitionNode(
+ TType(), kInitGlobalsFunctionName, initGlobalsBlock, initGlobalsFunctionId);
+ root->appendStatement(initGlobalsFunctionDefinition);
+
+ TIntermAggregate *initGlobalsCall = CreateInternalFunctionCallNode(
+ TType(), kInitGlobalsFunctionName, initGlobalsFunctionId, new TIntermSequence());
+
TIntermBlock *mainBody = FindMainBody(root);
- mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsBlock);
+ mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsCall);
}
} // namespace
-void DeferGlobalInitializers(TIntermBlock *root, bool initializeUninitializedGlobals)
+void DeferGlobalInitializers(TIntermBlock *root,
+ bool initializeUninitializedGlobals,
+ TSymbolTable *symbolTable)
{
TIntermSequence *deferredInitializers = new TIntermSequence();
@@ -131,7 +150,7 @@
// Add the function with initialization and the call to that.
if (!deferredInitializers->empty())
{
- InsertInitCodeToMain(root, deferredInitializers);
+ InsertInitCallToMain(root, deferredInitializers, symbolTable);
}
}
diff --git a/src/compiler/translator/DeferGlobalInitializers.h b/src/compiler/translator/DeferGlobalInitializers.h
index 73779cc..18ec66e 100644
--- a/src/compiler/translator/DeferGlobalInitializers.h
+++ b/src/compiler/translator/DeferGlobalInitializers.h
@@ -3,11 +3,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// DeferGlobalInitializers is an AST traverser that moves global initializers into a block in the
-// beginning of main(). This enables initialization of globals with uniforms or non-constant
-// globals, as allowed by the WebGL spec. Some initializers referencing non-constants may need to be
-// unfolded into if statements in HLSL - this kind of steps should be done after
-// DeferGlobalInitializers is run.
+// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate
+// function that is called in the beginning of main(). This enables initialization of globals with
+// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing
+// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be
+// done after DeferGlobalInitializers is run. Note that it's important that the function definition
+// is at the end of the shader, as some globals may be declared after main().
//
// It can also initialize all uninitialized globals.
//
@@ -15,11 +16,16 @@
#ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
-class TIntermBlock;
-
namespace sh
{
-void DeferGlobalInitializers(TIntermBlock *root, bool initializeUninitializedGlobals);
+
+class TIntermBlock;
+class TSymbolTable;
+
+void DeferGlobalInitializers(TIntermBlock *root,
+ bool initializeUninitializedGlobals,
+ TSymbolTable *symbolTable);
+
} // namespace sh
#endif // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_