Commit 2c7f34c8 by Olli Etuaho Committed by Commit Bot

Initialize uninitialized GLSL arrays in a for loop

Previously, creating nodes for initializing each single array element could result in memory bloat during translation when dealing with large arrays. The resulting shader could also end up very long. Initialize most arrays using a simple for loop instead. The loop is compatible with ESSL 1.00 Appendix A limitations. An exception is made for fragment outputs, so that they are not indexed by non-constant values. On some platforms using the a loop to initialize variables can cause problems, so we also have a compiler flag for turning this behavior off. The flag was already added earlier for a staggered rollout of this functionality. BUG=chromium:735497 TEST=angle_unittests, angle_end2end_tests, WebGL conformance tests Change-Id: Iec727821d8137db56b440ddbe007879b1b55f61f Reviewed-on: https://chromium-review.googlesource.com/707195 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent bb27c3a1
...@@ -595,7 +595,9 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, ...@@ -595,7 +595,9 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
// on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00. // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
bool initializeLocalsAndGlobals = bool initializeLocalsAndGlobals =
(compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType()); (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
DeferGlobalInitializers(root, initializeLocalsAndGlobals, &symbolTable); bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize, &symbolTable);
if (initializeLocalsAndGlobals) if (initializeLocalsAndGlobals)
{ {
...@@ -615,7 +617,8 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, ...@@ -615,7 +617,8 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
&getSymbolTable(), getShaderVersion()); &getSymbolTable(), getShaderVersion());
} }
InitializeUninitializedLocals(root, getShaderVersion()); InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize,
&getSymbolTable());
} }
if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE)) if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE))
...@@ -1055,7 +1058,7 @@ void TCompiler::initializeGLPosition(TIntermBlock *root) ...@@ -1055,7 +1058,7 @@ void TCompiler::initializeGLPosition(TIntermBlock *root)
sh::ShaderVariable var(GL_FLOAT_VEC4); sh::ShaderVariable var(GL_FLOAT_VEC4);
var.name = "gl_Position"; var.name = "gl_Position";
list.push_back(var); list.push_back(var);
InitializeVariables(root, list, symbolTable, shaderVersion, extensionBehavior); InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
} }
void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root) void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
...@@ -1097,7 +1100,7 @@ void TCompiler::initializeOutputVariables(TIntermBlock *root) ...@@ -1097,7 +1100,7 @@ void TCompiler::initializeOutputVariables(TIntermBlock *root)
list.push_back(var); list.push_back(var);
} }
} }
InitializeVariables(root, list, symbolTable, shaderVersion, extensionBehavior); InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
} }
const TExtensionBehavior &TCompiler::getExtensionBehavior() const const TExtensionBehavior &TCompiler::getExtensionBehavior() const
......
...@@ -29,7 +29,9 @@ namespace ...@@ -29,7 +29,9 @@ namespace
void GetDeferredInitializers(TIntermDeclaration *declaration, void GetDeferredInitializers(TIntermDeclaration *declaration,
bool initializeUninitializedGlobals, bool initializeUninitializedGlobals,
TIntermSequence *deferredInitializersOut) bool canUseLoopsToInitialize,
TIntermSequence *deferredInitializersOut,
TSymbolTable *symbolTable)
{ {
// SeparateDeclarations should have already been run. // SeparateDeclarations should have already been run.
ASSERT(declaration->getSequence()->size() == 1); ASSERT(declaration->getSequence()->size() == 1);
...@@ -81,7 +83,8 @@ void GetDeferredInitializers(TIntermDeclaration *declaration, ...@@ -81,7 +83,8 @@ void GetDeferredInitializers(TIntermDeclaration *declaration,
if (symbolNode->getQualifier() == EvqGlobal && symbolNode->getSymbol() != "") if (symbolNode->getQualifier() == EvqGlobal && symbolNode->getSymbol() != "")
{ {
TIntermSequence *initCode = CreateInitCode(symbolNode); TIntermSequence *initCode =
CreateInitCode(symbolNode, canUseLoopsToInitialize, symbolTable);
deferredInitializersOut->insert(deferredInitializersOut->end(), initCode->begin(), deferredInitializersOut->insert(deferredInitializersOut->end(), initCode->begin(),
initCode->end()); initCode->end());
} }
...@@ -117,6 +120,7 @@ void InsertInitCallToMain(TIntermBlock *root, ...@@ -117,6 +120,7 @@ void InsertInitCallToMain(TIntermBlock *root,
void DeferGlobalInitializers(TIntermBlock *root, void DeferGlobalInitializers(TIntermBlock *root,
bool initializeUninitializedGlobals, bool initializeUninitializedGlobals,
bool canUseLoopsToInitialize,
TSymbolTable *symbolTable) TSymbolTable *symbolTable)
{ {
TIntermSequence *deferredInitializers = new TIntermSequence(); TIntermSequence *deferredInitializers = new TIntermSequence();
...@@ -129,7 +133,7 @@ void DeferGlobalInitializers(TIntermBlock *root, ...@@ -129,7 +133,7 @@ void DeferGlobalInitializers(TIntermBlock *root,
if (declaration) if (declaration)
{ {
GetDeferredInitializers(declaration, initializeUninitializedGlobals, GetDeferredInitializers(declaration, initializeUninitializedGlobals,
deferredInitializers); canUseLoopsToInitialize, deferredInitializers, symbolTable);
} }
} }
......
...@@ -24,6 +24,7 @@ class TSymbolTable; ...@@ -24,6 +24,7 @@ class TSymbolTable;
void DeferGlobalInitializers(TIntermBlock *root, void DeferGlobalInitializers(TIntermBlock *root,
bool initializeUninitializedGlobals, bool initializeUninitializedGlobals,
bool canUseLoopsToInitialize,
TSymbolTable *symbolTable); TSymbolTable *symbolTable);
} // namespace sh } // namespace sh
......
...@@ -18,12 +18,20 @@ class TSymbolTable; ...@@ -18,12 +18,20 @@ class TSymbolTable;
typedef std::vector<sh::ShaderVariable> InitVariableList; typedef std::vector<sh::ShaderVariable> InitVariableList;
// For all of the functions below: If canUseLoopsToInitialize is set, for loops are used instead of
// a large number of initializers where it can make sense, such as for initializing large arrays.
// Return a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol // Return a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol
// may be an array, struct or any combination of these, as long as it contains only basic types. // may be an array, struct or any combination of these, as long as it contains only basic types.
TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol); TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol,
bool canUseLoopsToInitialize,
TSymbolTable *symbolTable);
// Initialize all uninitialized local variables, so that undefined behavior is avoided. // Initialize all uninitialized local variables, so that undefined behavior is avoided.
void InitializeUninitializedLocals(TIntermBlock *root, int shaderVersion); void InitializeUninitializedLocals(TIntermBlock *root,
int shaderVersion,
bool canUseLoopsToInitialize,
TSymbolTable *symbolTable);
// This function can initialize all the types that CreateInitCode is able to initialize. All // This function can initialize all the types that CreateInitCode is able to initialize. All
// variables must be globals which can be found in the symbol table. For now it is used for the // variables must be globals which can be found in the symbol table. For now it is used for the
...@@ -35,9 +43,10 @@ void InitializeUninitializedLocals(TIntermBlock *root, int shaderVersion); ...@@ -35,9 +43,10 @@ void InitializeUninitializedLocals(TIntermBlock *root, int shaderVersion);
// enabled extensions. // enabled extensions.
void InitializeVariables(TIntermBlock *root, void InitializeVariables(TIntermBlock *root,
const InitVariableList &vars, const InitVariableList &vars,
const TSymbolTable &symbolTable, TSymbolTable *symbolTable,
int shaderVersion, int shaderVersion,
const TExtensionBehavior &extensionBehavior); const TExtensionBehavior &extensionBehavior,
bool canUseLoopsToInitialize);
} // namespace sh } // namespace sh
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment