Commit e740addb by Zhenyao Mo

Add compiler option SH_REGENERATE_STRUCT_NAMES.

BUG=angle:701 TEST=webgl conformance tests Change-Id: I13b35900956e7d840d5891a5bab90a400347cd6f Reviewed-on: https://chromium-review.googlesource.com/209229Tested-by: 's avatarZhenyao Mo <zmo@chromium.org> Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org>
parent a2ad4e8a
...@@ -188,6 +188,11 @@ typedef enum { ...@@ -188,6 +188,11 @@ typedef enum {
// This flag scalarizes vec/ivec/bvec/mat constructor args. // This flag scalarizes vec/ivec/bvec/mat constructor args.
// It is intended as a workaround for Linux/Mac driver bugs. // It is intended as a workaround for Linux/Mac driver bugs.
SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000, SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000,
// This flag overwrites a struct name with a unique prefix.
// It is intended as a workaround for drivers that do not handle
// struct scopes correctly, including all Mac drivers and Linux AMD.
SH_REGENERATE_STRUCT_NAMES = 0x80000,
} ShCompileOptions; } ShCompileOptions;
// Defines alternate strategies for implementing array index clamping. // Defines alternate strategies for implementing array index clamping.
......
...@@ -92,6 +92,8 @@ ...@@ -92,6 +92,8 @@
'compiler/translator/Pragma.h', 'compiler/translator/Pragma.h',
'compiler/translator/QualifierAlive.cpp', 'compiler/translator/QualifierAlive.cpp',
'compiler/translator/QualifierAlive.h', 'compiler/translator/QualifierAlive.h',
'compiler/translator/RegenerateStructNames.cpp',
'compiler/translator/RegenerateStructNames.h',
'compiler/translator/RemoveTree.cpp', 'compiler/translator/RemoveTree.cpp',
'compiler/translator/RemoveTree.h', 'compiler/translator/RemoveTree.h',
'compiler/translator/RenameFunction.h', 'compiler/translator/RenameFunction.h',
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/InitializeVariables.h" #include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/ParseContext.h" #include "compiler/translator/ParseContext.h"
#include "compiler/translator/RegenerateStructNames.h"
#include "compiler/translator/RenameFunction.h" #include "compiler/translator/RenameFunction.h"
#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
#include "compiler/translator/UnfoldShortCircuitAST.h" #include "compiler/translator/UnfoldShortCircuitAST.h"
...@@ -261,6 +262,12 @@ bool TCompiler::compile(const char* const shaderStrings[], ...@@ -261,6 +262,12 @@ bool TCompiler::compile(const char* const shaderStrings[],
root->traverse(&scalarizer); root->traverse(&scalarizer);
} }
if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES))
{
RegenerateStructNames gen(symbolTable, shaderVersion);
root->traverse(&gen);
}
if (success && (compileOptions & SH_INTERMEDIATE_TREE)) if (success && (compileOptions & SH_INTERMEDIATE_TREE))
intermediate.outputTree(root); intermediate.outputTree(root);
......
//
// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/translator/RegenerateStructNames.h"
#include "compiler/translator/compilerdebug.h"
void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
{
ASSERT(symbol);
TType *type = symbol->getTypePointer();
ASSERT(type);
TStructure *userType = type->getStruct();
if (!userType)
return;
if (mSymbolTable.findBuiltIn(userType->name(), mShaderVersion))
{
// Built-in struct, do not touch it.
return;
}
int uniqueId = userType->uniqueId();
ASSERT(mScopeDepth > 0);
if (mScopeDepth == 1)
{
// If a struct is defined at global scope, we don't map its name.
// This is because at global level, the struct might be used to
// declare a uniform, so the same name needs to stay the same for
// vertex/fragment shaders. However, our mapping uses internal ID,
// which will be different for the same struct in vertex/fragment
// shaders.
// This is OK because names for any structs defined in other scopes
// will begin with "_webgl", which is reserved. So there will be
// no conflicts among unmapped struct names from global scope and
// mapped struct names from other scopes.
// However, we need to keep track of these global structs, so if a
// variable is used in a local scope, we don't try to modify the
// struct name through that variable.
mDeclaredGlobalStructs.insert(uniqueId);
return;
}
if (mDeclaredGlobalStructs.count(uniqueId) > 0)
return;
// Map {name} to _webgl_struct_{uniqueId}_{name}.
const char kPrefix[] = "_webgl_struct_";
if (userType->name().find(kPrefix) == 0)
{
// The name has already been regenerated.
return;
}
std::string id = Str(uniqueId);
TString tmp = kPrefix + TString(id.c_str());
tmp += "_" + userType->name();
userType->setName(tmp);
}
bool RegenerateStructNames::visitAggregate(Visit, TIntermAggregate *aggregate)
{
ASSERT(aggregate);
switch (aggregate->getOp())
{
case EOpSequence:
++mScopeDepth;
{
TIntermSequence &sequence = *(aggregate->getSequence());
for (size_t ii = 0; ii < sequence.size(); ++ii)
{
TIntermNode *node = sequence[ii];
ASSERT(node != NULL);
node->traverse(this);
}
}
--mScopeDepth;
return false;
default:
return true;
}
}
//
// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_
#define COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_
#include "compiler/translator/intermediate.h"
#include "compiler/translator/SymbolTable.h"
#include <set>
class RegenerateStructNames : public TIntermTraverser
{
public:
RegenerateStructNames(const TSymbolTable &symbolTable,
int shaderVersion)
: mSymbolTable(symbolTable),
mShaderVersion(shaderVersion),
mScopeDepth(0) {}
protected:
virtual void visitSymbol(TIntermSymbol *);
virtual bool visitAggregate(Visit, TIntermAggregate *);
private:
const TSymbolTable &mSymbolTable;
int mShaderVersion;
// Indicating the depth of the current scope.
// The global scope is 1.
int mScopeDepth;
// If a struct's declared globally, push its ID in this set.
std::set<int> mDeclaredGlobalStructs;
};
#endif // COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_
...@@ -98,7 +98,8 @@ TSymbol::TSymbol(const TSymbol &copyOf) ...@@ -98,7 +98,8 @@ TSymbol::TSymbol(const TSymbol &copyOf)
uniqueId = copyOf.uniqueId; uniqueId = copyOf.uniqueId;
} }
TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) TSymbol *TSymbolTable::find(const TString &name, int shaderVersion,
bool *builtIn, bool *sameScope) const
{ {
int level = currentLevel(); int level = currentLevel();
TSymbol *symbol; TSymbol *symbol;
...@@ -122,7 +123,8 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtI ...@@ -122,7 +123,8 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtI
return symbol; return symbol;
} }
TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) TSymbol *TSymbolTable::findBuiltIn(
const TString &name, int shaderVersion) const
{ {
for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--) for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
{ {
...@@ -210,7 +212,7 @@ void TSymbolTable::insertBuiltIn( ...@@ -210,7 +212,7 @@ void TSymbolTable::insertBuiltIn(
insert(level, function); insert(level, function);
} }
TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
{ {
if (!SupportsPrecision(type)) if (!SupportsPrecision(type))
return EbpUndefined; return EbpUndefined;
......
...@@ -323,15 +323,15 @@ class TSymbolTable ...@@ -323,15 +323,15 @@ class TSymbolTable
// When the symbol table is initialized with the built-ins, there should // When the symbol table is initialized with the built-ins, there should
// 'push' calls, so that built-ins are at level 0 and the shader // 'push' calls, so that built-ins are at level 0 and the shader
// globals are at level 1. // globals are at level 1.
bool isEmpty() bool isEmpty() const
{ {
return table.empty(); return table.empty();
} }
bool atBuiltInLevel() bool atBuiltInLevel() const
{ {
return currentLevel() <= LAST_BUILTIN_LEVEL; return currentLevel() <= LAST_BUILTIN_LEVEL;
} }
bool atGlobalLevel() bool atGlobalLevel() const
{ {
return currentLevel() <= GLOBAL_LEVEL; return currentLevel() <= GLOBAL_LEVEL;
} }
...@@ -373,8 +373,8 @@ class TSymbolTable ...@@ -373,8 +373,8 @@ class TSymbolTable
TType *ptype4 = 0, TType *ptype5 = 0); TType *ptype4 = 0, TType *ptype5 = 0);
TSymbol *find(const TString &name, int shaderVersion, TSymbol *find(const TString &name, int shaderVersion,
bool *builtIn = NULL, bool *sameScope = NULL); bool *builtIn = NULL, bool *sameScope = NULL) const;
TSymbol *findBuiltIn(const TString &name, int shaderVersion); TSymbol *findBuiltIn(const TString &name, int shaderVersion) const;
TSymbolTableLevel *getOuterLevel() TSymbolTableLevel *getOuterLevel()
{ {
...@@ -406,7 +406,7 @@ class TSymbolTable ...@@ -406,7 +406,7 @@ class TSymbolTable
// Searches down the precisionStack for a precision qualifier // Searches down the precisionStack for a precision qualifier
// for the specified TBasicType // for the specified TBasicType
TPrecision getDefaultPrecision(TBasicType type); TPrecision getDefaultPrecision(TBasicType type) const;
static int nextUniqueId() static int nextUniqueId()
{ {
......
...@@ -140,6 +140,17 @@ class TStructure : public TFieldListCollection ...@@ -140,6 +140,17 @@ class TStructure : public TFieldListCollection
private: private:
DISALLOW_COPY_AND_ASSIGN(TStructure); DISALLOW_COPY_AND_ASSIGN(TStructure);
// TODO(zmo): Find a way to get rid of the const_cast in function
// setName(). At the moment keep this function private so only
// friend class RegenerateStructNames may call it.
friend class RegenerateStructNames;
void setName(const TString &name)
{
TString *mutableName = const_cast<TString *>(mName);
*mutableName = name;
}
virtual TString mangledNamePrefix() const virtual TString mangledNamePrefix() const
{ {
return "struct-"; return "struct-";
......
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