Commit 904a9164 by Zhenyao Mo

Fix nested struct scope support in GL backend.

Basically we should be able to reuse a struct name once the previous use is out of the scope, or we can reuse it if we are in a inner scope than where it is defined before. BUG=368910 BUG=angle:618 TEST=conformance/glsl/bugs/nested-structs-with-same-name.html Change-Id: Icfac76b844deaca0c8a0501d7426ff3802e657dc Reviewed-on: https://chromium-review.googlesource.com/199137Reviewed-by: 's avatarNicolas Capens <nicolascapens@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarZhenyao Mo <zmo@chromium.org>
parent 26198851
...@@ -54,6 +54,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink, ...@@ -54,6 +54,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink,
mSymbolTable(symbolTable), mSymbolTable(symbolTable),
mShaderVersion(shaderVersion) mShaderVersion(shaderVersion)
{ {
// Set up global scope.
mDeclaredStructs.push_back(ScopedDeclaredStructs());
} }
void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr) void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
...@@ -84,6 +86,7 @@ void TOutputGLSLBase::writeVariableType(const TType& type) ...@@ -84,6 +86,7 @@ void TOutputGLSLBase::writeVariableType(const TType& type)
if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct())) if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
{ {
declareStruct(type.getStruct()); declareStruct(type.getStruct());
mDeclaredStructs[mDeclaredStructs.size() - 1].push_back(type.getStruct());
} }
else else
{ {
...@@ -460,7 +463,11 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -460,7 +463,11 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
{ {
case EOpSequence: { case EOpSequence: {
// Scope the sequences except when at the global scope. // Scope the sequences except when at the global scope.
if (depth > 0) out << "{\n"; if (depth > 0)
{
out << "{\n";
pushDeclaredStructsScope();
}
incrementDepth(node); incrementDepth(node);
const TIntermSequence& sequence = node->getSequence(); const TIntermSequence& sequence = node->getSequence();
...@@ -477,7 +484,11 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -477,7 +484,11 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
decrementDepth(); decrementDepth();
// Scope the sequences except when at the global scope. // Scope the sequences except when at the global scope.
if (depth > 0) out << "}\n"; if (depth > 0)
{
popDeclaredStructsScope();
out << "}\n";
}
visitChildren = false; visitChildren = false;
break; break;
} }
...@@ -809,7 +820,18 @@ TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name) ...@@ -809,7 +820,18 @@ TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
bool TOutputGLSLBase::structDeclared(const TStructure* structure) const bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
{ {
return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end(); ASSERT(structure);
ASSERT(mDeclaredStructs.size() > 0);
for (size_t ii = mDeclaredStructs.size(); ii > 0; --ii)
{
const ScopedDeclaredStructs& scope = mDeclaredStructs[ii - 1];
for (size_t jj = 0; jj < scope.size(); ++jj)
{
if (scope[jj]->equals(*structure))
return true;
}
}
return false;
} }
void TOutputGLSLBase::declareStruct(const TStructure* structure) void TOutputGLSLBase::declareStruct(const TStructure* structure)
...@@ -829,6 +851,16 @@ void TOutputGLSLBase::declareStruct(const TStructure* structure) ...@@ -829,6 +851,16 @@ void TOutputGLSLBase::declareStruct(const TStructure* structure)
out << ";\n"; out << ";\n";
} }
out << "}"; out << "}";
}
mDeclaredStructs.insert(structure->name()); void TOutputGLSLBase::pushDeclaredStructsScope()
{
mDeclaredStructs.push_back(ScopedDeclaredStructs());
}
void TOutputGLSLBase::popDeclaredStructsScope()
{
// We should never pop the global scope.
ASSERT(mDeclaredStructs.size() >= 2);
mDeclaredStructs.pop_back();
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ #ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ #define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
#include <set> #include <vector>
#include "compiler/translator/intermediate.h" #include "compiler/translator/intermediate.h"
#include "compiler/translator/LoopInfo.h" #include "compiler/translator/LoopInfo.h"
...@@ -57,14 +57,19 @@ protected: ...@@ -57,14 +57,19 @@ protected:
private: private:
bool structDeclared(const TStructure* structure) const; bool structDeclared(const TStructure* structure) const;
void declareStruct(const TStructure* structure); void declareStruct(const TStructure* structure);
void pushDeclaredStructsScope();
void popDeclaredStructsScope();
TInfoSinkBase& mObjSink; TInfoSinkBase& mObjSink;
bool mDeclaringVariables; bool mDeclaringVariables;
// Structs are declared as the tree is traversed. This set contains all // Structs are declared as the tree is traversed. This list contains all
// the structs already declared. It is maintained so that a struct is // the structs already declared within a scope. It is maintained so that
// declared only once. // a struct is declared only once within a scope.
typedef std::set<TString> DeclaredStructs; typedef std::vector<TStructure *> ScopedDeclaredStructs;
// This vector contains all the structs from the global scope to the
// current scope. When the traverser exits a scope, the scope is discarded.
typedef std::vector<ScopedDeclaredStructs> DeclaredStructs;
DeclaredStructs mDeclaredStructs; DeclaredStructs mDeclaredStructs;
// Stack of loops that need to be unrolled. // Stack of loops that need to be unrolled.
......
...@@ -17,142 +17,9 @@ ...@@ -17,142 +17,9 @@
#include <stdio.h> #include <stdio.h>
#include <algorithm> #include <algorithm>
#include <climits>
int TSymbolTableLevel::uniqueId = 0; int TSymbolTableLevel::uniqueId = 0;
TType::TType(const TPublicType &p) :
type(p.type), precision(p.precision), qualifier(p.qualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), layoutQualifier(p.layoutQualifier), arraySize(p.arraySize),
interfaceBlock(0), structure(0)
{
if (p.userDef) {
structure = p.userDef->getStruct();
}
}
//
// Recursively generate mangled names.
//
TString TType::buildMangledName() const
{
TString mangledName;
if (isMatrix())
mangledName += 'm';
else if (isVector())
mangledName += 'v';
switch (type)
{
case EbtFloat: mangledName += 'f'; break;
case EbtInt: mangledName += 'i'; break;
case EbtUInt: mangledName += 'u'; break;
case EbtBool: mangledName += 'b'; break;
case EbtSampler2D: mangledName += "s2"; break;
case EbtSampler3D: mangledName += "s3"; break;
case EbtSamplerCube: mangledName += "sC"; break;
case EbtSampler2DArray: mangledName += "s2a"; break;
case EbtSamplerExternalOES: mangledName += "sext"; break;
case EbtSampler2DRect: mangledName += "s2r"; break;
case EbtISampler2D: mangledName += "is2"; break;
case EbtISampler3D: mangledName += "is3"; break;
case EbtISamplerCube: mangledName += "isC"; break;
case EbtISampler2DArray: mangledName += "is2a"; break;
case EbtUSampler2D: mangledName += "us2"; break;
case EbtUSampler3D: mangledName += "us3"; break;
case EbtUSamplerCube: mangledName += "usC"; break;
case EbtUSampler2DArray: mangledName += "us2a"; break;
case EbtSampler2DShadow: mangledName += "s2s"; break;
case EbtSamplerCubeShadow: mangledName += "sCs"; break;
case EbtSampler2DArrayShadow: mangledName += "s2as"; break;
case EbtStruct: mangledName += structure->mangledName(); break;
case EbtInterfaceBlock: mangledName += interfaceBlock->mangledName(); break;
default: UNREACHABLE();
}
if (isMatrix())
{
mangledName += static_cast<char>('0' + getCols());
mangledName += static_cast<char>('x');
mangledName += static_cast<char>('0' + getRows());
}
else
{
mangledName += static_cast<char>('0' + getNominalSize());
}
if (isArray()) {
char buf[20];
snprintf(buf, sizeof(buf), "%d", arraySize);
mangledName += '[';
mangledName += buf;
mangledName += ']';
}
return mangledName;
}
size_t TType::getObjectSize() const
{
size_t totalSize;
if (getBasicType() == EbtStruct)
totalSize = structure->objectSize();
else
totalSize = primarySize * secondarySize;
if (isArray()) {
size_t arraySize = getArraySize();
if (arraySize > INT_MAX / totalSize)
totalSize = INT_MAX;
else
totalSize *= arraySize;
}
return totalSize;
}
bool TStructure::containsArrays() const
{
for (size_t i = 0; i < mFields->size(); ++i) {
const TType* fieldType = (*mFields)[i]->type();
if (fieldType->isArray() || fieldType->isStructureContainingArrays())
return true;
}
return false;
}
TString TFieldListCollection::buildMangledName() const
{
TString mangledName(mangledNamePrefix());
mangledName += *mName;
for (size_t i = 0; i < mFields->size(); ++i) {
mangledName += '-';
mangledName += (*mFields)[i]->type()->getMangledName();
}
return mangledName;
}
size_t TFieldListCollection::calculateObjectSize() const
{
size_t size = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
if (fieldSize > INT_MAX - size)
size = INT_MAX;
else
size += fieldSize;
}
return size;
}
int TStructure::calculateDeepestNesting() const
{
int maxNesting = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
}
return 1 + maxNesting;
}
// //
// Functions have buried pointers to delete. // Functions have buried pointers to delete.
// //
......
//
// 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.
//
#if defined(_MSC_VER)
#pragma warning(disable: 4718)
#endif
#include "compiler/translator/Types.h"
#include <climits>
TType::TType(const TPublicType &p)
: type(p.type), precision(p.precision), qualifier(p.qualifier), layoutQualifier(p.layoutQualifier),
primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize),
interfaceBlock(0), structure(0)
{
if (p.userDef)
{
structure = p.userDef->getStruct();
}
}
bool TType::equals(const TType &other) const
{
if (type != other.type || precision != other.precision ||
primarySize != other.primarySize || secondarySize != other.secondarySize ||
array != other.array || (array && arraySize != other.arraySize) ||
interfaceBlock != other.interfaceBlock || structure != other.structure)
{
return false;
}
if (interfaceBlock && !interfaceBlock->equals(*(other.interfaceBlock)))
{
return false;
}
if (structure && !structure->equals(*(other.structure)))
{
return false;
}
return true;
}
bool TField::equals(const TField &other) const
{
ASSERT(mType && mName);
ASSERT(other.mType && other.mName);
return mType->equals(*(other.mType)) && *mName == *(other.mName);
}
bool TFieldListCollection::equals(const TFieldListCollection &other) const
{
ASSERT(mName && mFields);
ASSERT(other.mName && other.mFields);
if (*mName != *(other.mName))
return false;
if (mFields->size() != other.mFields->size())
return false;
for (size_t ii = 0; ii < mFields->size(); ++ii)
{
ASSERT((*mFields)[ii] && (*(other.mFields))[ii]);
if (!(*mFields)[ii]->equals(*((*(other.mFields))[ii])))
return false;
}
return true;
}
bool TInterfaceBlock::equals(const TInterfaceBlock &other) const
{
if (!TFieldListCollection::equals(other))
return false;
// TODO(zmo): do we need to consider mBlockStorage and mMatrixPacking?
return mArraySize == other.mArraySize;
}
//
// Recursively generate mangled names.
//
TString TType::buildMangledName() const
{
TString mangledName;
if (isMatrix())
mangledName += 'm';
else if (isVector())
mangledName += 'v';
switch (type)
{
case EbtFloat: mangledName += 'f'; break;
case EbtInt: mangledName += 'i'; break;
case EbtUInt: mangledName += 'u'; break;
case EbtBool: mangledName += 'b'; break;
case EbtSampler2D: mangledName += "s2"; break;
case EbtSampler3D: mangledName += "s3"; break;
case EbtSamplerCube: mangledName += "sC"; break;
case EbtSampler2DArray: mangledName += "s2a"; break;
case EbtSamplerExternalOES: mangledName += "sext"; break;
case EbtSampler2DRect: mangledName += "s2r"; break;
case EbtISampler2D: mangledName += "is2"; break;
case EbtISampler3D: mangledName += "is3"; break;
case EbtISamplerCube: mangledName += "isC"; break;
case EbtISampler2DArray: mangledName += "is2a"; break;
case EbtUSampler2D: mangledName += "us2"; break;
case EbtUSampler3D: mangledName += "us3"; break;
case EbtUSamplerCube: mangledName += "usC"; break;
case EbtUSampler2DArray: mangledName += "us2a"; break;
case EbtSampler2DShadow: mangledName += "s2s"; break;
case EbtSamplerCubeShadow: mangledName += "sCs"; break;
case EbtSampler2DArrayShadow: mangledName += "s2as"; break;
case EbtStruct: mangledName += structure->mangledName(); break;
case EbtInterfaceBlock: mangledName += interfaceBlock->mangledName(); break;
default: UNREACHABLE();
}
if (isMatrix())
{
mangledName += static_cast<char>('0' + getCols());
mangledName += static_cast<char>('x');
mangledName += static_cast<char>('0' + getRows());
}
else
{
mangledName += static_cast<char>('0' + getNominalSize());
}
if (isArray())
{
char buf[20];
snprintf(buf, sizeof(buf), "%d", arraySize);
mangledName += '[';
mangledName += buf;
mangledName += ']';
}
return mangledName;
}
size_t TType::getObjectSize() const
{
size_t totalSize;
if (getBasicType() == EbtStruct)
totalSize = structure->objectSize();
else
totalSize = primarySize * secondarySize;
if (isArray())
{
size_t arraySize = getArraySize();
if (arraySize > INT_MAX / totalSize)
totalSize = INT_MAX;
else
totalSize *= arraySize;
}
return totalSize;
}
bool TStructure::containsArrays() const
{
for (size_t i = 0; i < mFields->size(); ++i) {
const TType* fieldType = (*mFields)[i]->type();
if (fieldType->isArray() || fieldType->isStructureContainingArrays())
return true;
}
return false;
}
TString TFieldListCollection::buildMangledName() const
{
TString mangledName(mangledNamePrefix());
mangledName += *mName;
for (size_t i = 0; i < mFields->size(); ++i)
{
mangledName += '-';
mangledName += (*mFields)[i]->type()->getMangledName();
}
return mangledName;
}
size_t TFieldListCollection::calculateObjectSize() const
{
size_t size = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
if (fieldSize > INT_MAX - size)
size = INT_MAX;
else
size += fieldSize;
}
return size;
}
int TStructure::calculateDeepestNesting() const
{
int maxNesting = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
}
return 1 + maxNesting;
}
...@@ -30,6 +30,8 @@ public: ...@@ -30,6 +30,8 @@ public:
const TString& name() const { return *mName; } const TString& name() const { return *mName; }
const TSourceLoc& line() const { return mLine; } const TSourceLoc& line() const { return mLine; }
bool equals(const TField &other) const;
private: private:
DISALLOW_COPY_AND_ASSIGN(TField); DISALLOW_COPY_AND_ASSIGN(TField);
TType* mType; TType* mType;
...@@ -61,6 +63,8 @@ public: ...@@ -61,6 +63,8 @@ public:
return mObjectSize; return mObjectSize;
}; };
virtual bool equals(const TFieldListCollection &other) const;
protected: protected:
TFieldListCollection(const TString* name, TFieldList* fields) TFieldListCollection(const TString* name, TFieldList* fields)
: mName(name), : mName(name),
...@@ -122,6 +126,8 @@ public: ...@@ -122,6 +126,8 @@ public:
TLayoutBlockStorage blockStorage() const { return mBlockStorage; } TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; } TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; }
virtual bool equals(const TInterfaceBlock &other) const;
private: private:
DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock); DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock);
virtual TString mangledNamePrefix() const { return "iblock-"; } virtual TString mangledNamePrefix() const { return "iblock-"; }
...@@ -210,6 +216,10 @@ public: ...@@ -210,6 +216,10 @@ public:
return mangled; return mangled;
} }
// This is different from operator== as we also compare
// precision here.
bool equals(const TType &other) const;
bool sameElementType(const TType& right) const { bool sameElementType(const TType& right) const {
return type == right.type && return type == right.type &&
primarySize == right.primarySize && primarySize == right.primarySize &&
......
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