blob: 00438be30875f932e66930a486f34af83471b527 [file] [log] [blame]
//
// Copyright 2018 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.
//
// NameEmbeddedUniformStructs: Gives nameless uniform struct internal names.
//
#include "compiler/translator/tree_ops/NameEmbeddedUniformStructs.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
namespace
{
// This traverser translates embedded uniform structs into a specifier and declaration.
// This makes the declarations easier to move into uniform blocks.
class Traverser : public TIntermTraverser
{
public:
explicit Traverser(TSymbolTable *symbolTable)
: TIntermTraverser(true, false, false, symbolTable)
{}
bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override
{
ASSERT(visit == PreVisit);
if (!mInGlobalScope)
{
return false;
}
const TIntermSequence &sequence = *(decl->getSequence());
ASSERT(sequence.size() == 1);
TIntermTyped *declarator = sequence.front()->getAsTyped();
const TType &type = declarator->getType();
if (type.isStructSpecifier() && type.getQualifier() == EvqUniform)
{
const TStructure *structure = type.getStruct();
if (structure->symbolType() == SymbolType::Empty)
{
doReplacement(decl, declarator, structure);
}
}
return false;
}
private:
void doReplacement(TIntermDeclaration *decl,
TIntermTyped *declarator,
const TStructure *oldStructure)
{
// struct <structName> { ... };
TStructure *structure = new TStructure(mSymbolTable, kEmptyImmutableString,
&oldStructure->fields(), SymbolType::AngleInternal);
TType *namedType = new TType(structure, true);
namedType->setQualifier(EvqGlobal);
TVariable *structVariable =
new TVariable(mSymbolTable, kEmptyImmutableString, namedType, SymbolType::Empty);
TIntermSymbol *structDeclarator = new TIntermSymbol(structVariable);
TIntermDeclaration *structDeclaration = new TIntermDeclaration;
structDeclaration->appendDeclarator(structDeclarator);
TIntermSequence *newSequence = new TIntermSequence;
newSequence->push_back(structDeclaration);
// uniform <structName> <structUniformName>;
TIntermSymbol *asSymbol = declarator->getAsSymbolNode();
if (asSymbol && asSymbol->variable().symbolType() != SymbolType::Empty)
{
TIntermDeclaration *namedDecl = new TIntermDeclaration;
TType *uniformType = new TType(structure, false);
uniformType->setQualifier(EvqUniform);
TVariable *newVar = new TVariable(mSymbolTable, asSymbol->getName(), uniformType,
asSymbol->variable().symbolType());
TIntermSymbol *newSymbol = new TIntermSymbol(newVar);
namedDecl->appendDeclarator(newSymbol);
newSequence->push_back(namedDecl);
}
mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), decl, *newSequence);
}
};
} // anonymous namespace
bool NameEmbeddedStructUniforms(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable)
{
Traverser nameStructs(symbolTable);
root->traverse(&nameStructs);
return nameStructs.updateTree(compiler, root);
}
} // namespace sh