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 {
// This flag scalarizes vec/ivec/bvec/mat constructor args.
// It is intended as a workaround for Linux/Mac driver bugs.
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;
// Defines alternate strategies for implementing array index clamping.
......
......@@ -92,6 +92,8 @@
'compiler/translator/Pragma.h',
'compiler/translator/QualifierAlive.cpp',
'compiler/translator/QualifierAlive.h',
'compiler/translator/RegenerateStructNames.cpp',
'compiler/translator/RegenerateStructNames.h',
'compiler/translator/RemoveTree.cpp',
'compiler/translator/RemoveTree.h',
'compiler/translator/RenameFunction.h',
......
......@@ -12,6 +12,7 @@
#include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/ParseContext.h"
#include "compiler/translator/RegenerateStructNames.h"
#include "compiler/translator/RenameFunction.h"
#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
#include "compiler/translator/UnfoldShortCircuitAST.h"
......@@ -261,6 +262,12 @@ bool TCompiler::compile(const char* const shaderStrings[],
root->traverse(&scalarizer);
}
if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES))
{
RegenerateStructNames gen(symbolTable, shaderVersion);
root->traverse(&gen);
}
if (success && (compileOptions & SH_INTERMEDIATE_TREE))
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)
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();
TSymbol *symbol;
......@@ -122,7 +123,8 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtI
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--)
{
......@@ -210,7 +212,7 @@ void TSymbolTable::insertBuiltIn(
insert(level, function);
}
TPrecision TSymbolTable::getDefaultPrecision(TBasicType type)
TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
{
if (!SupportsPrecision(type))
return EbpUndefined;
......
......@@ -323,15 +323,15 @@ class TSymbolTable
// 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
// globals are at level 1.
bool isEmpty()
bool isEmpty() const
{
return table.empty();
}
bool atBuiltInLevel()
bool atBuiltInLevel() const
{
return currentLevel() <= LAST_BUILTIN_LEVEL;
}
bool atGlobalLevel()
bool atGlobalLevel() const
{
return currentLevel() <= GLOBAL_LEVEL;
}
......@@ -373,8 +373,8 @@ class TSymbolTable
TType *ptype4 = 0, TType *ptype5 = 0);
TSymbol *find(const TString &name, int shaderVersion,
bool *builtIn = NULL, bool *sameScope = NULL);
TSymbol *findBuiltIn(const TString &name, int shaderVersion);
bool *builtIn = NULL, bool *sameScope = NULL) const;
TSymbol *findBuiltIn(const TString &name, int shaderVersion) const;
TSymbolTableLevel *getOuterLevel()
{
......@@ -406,7 +406,7 @@ class TSymbolTable
// Searches down the precisionStack for a precision qualifier
// for the specified TBasicType
TPrecision getDefaultPrecision(TBasicType type);
TPrecision getDefaultPrecision(TBasicType type) const;
static int nextUniqueId()
{
......
......@@ -140,6 +140,17 @@ class TStructure : public TFieldListCollection
private:
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
{
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