Hash :
cc56e1aa
Author :
Date :
2021-04-09T23:35:07
Vulkan: Remove special output of structs and keep them in AST The code that separated out declaration of nameless structs from uniform variable declarations is generalized to separate out declaration of all structs from uniform variable declarations. As a result, a pass that outputs the struct types at the top of the shader is no longer necessary. The struct declarations are kept in the AST to be output to GLSL as they normally would when not used in conjunction with uniform variables. After this change, the Vulkan and Metal translators no longer intermix transformations and code generation; transformations are done first entirely in AST, and code generation is done at the end. Bug: angleproject:2461 Bug: angleproject:4889 Change-Id: Ieb4d3f7091845e50c3dc399603ab01182692521d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2818153 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
//
// 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.
//
// SeparateStructFromUniformDeclarations: Separate struct declarations from uniform declarations.
//
#include "compiler/translator/tree_ops/vulkan/SeparateStructFromUniformDeclarations.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
#include "compiler/translator/tree_util/ReplaceVariable.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)
{
doReplacement(decl, declarator, type.getStruct());
}
return false;
}
void visitSymbol(TIntermSymbol *symbol) override
{
const TVariable *variable = &symbol->variable();
if (mVariableMap.count(variable) > 0)
{
queueReplacement(mVariableMap[variable]->deepCopy(), OriginalNode::IS_DROPPED);
}
}
private:
void doReplacement(TIntermDeclaration *decl,
TIntermTyped *declarator,
const TStructure *oldStructure)
{
// struct <structName> { ... };
const TStructure *structure = oldStructure;
if (oldStructure->symbolType() == SymbolType::Empty)
{
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;
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);
mVariableMap[&asSymbol->variable()] = new TIntermSymbol(newVar);
}
mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), decl,
std::move(newSequence));
}
VariableReplacementMap mVariableMap;
};
} // anonymous namespace
bool SeparateStructFromUniformDeclarations(TCompiler *compiler,
TIntermBlock *root,
TSymbolTable *symbolTable)
{
Traverser separateStructDecls(symbolTable);
root->traverse(&separateStructDecls);
return separateStructDecls.updateTree(compiler, root);
}
} // namespace sh