• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // SeparateStructFromUniformDeclarations: Separate struct declarations from uniform declarations.
7 //
8 
9 #include "compiler/translator/tree_ops/vulkan/SeparateStructFromUniformDeclarations.h"
10 
11 #include "compiler/translator/SymbolTable.h"
12 #include "compiler/translator/tree_util/IntermTraverse.h"
13 #include "compiler/translator/tree_util/ReplaceVariable.h"
14 
15 namespace sh
16 {
17 namespace
18 {
19 // This traverser translates embedded uniform structs into a specifier and declaration.
20 // This makes the declarations easier to move into uniform blocks.
21 class Traverser : public TIntermTraverser
22 {
23   public:
Traverser(TSymbolTable * symbolTable)24     explicit Traverser(TSymbolTable *symbolTable)
25         : TIntermTraverser(true, false, false, symbolTable)
26     {}
27 
visitDeclaration(Visit visit,TIntermDeclaration * decl)28     bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override
29     {
30         ASSERT(visit == PreVisit);
31 
32         if (!mInGlobalScope)
33         {
34             return true;
35         }
36 
37         const TIntermSequence &sequence = *(decl->getSequence());
38         ASSERT(sequence.size() == 1);
39         TIntermTyped *declarator = sequence.front()->getAsTyped();
40         const TType &type        = declarator->getType();
41 
42         if (type.isStructSpecifier() && type.getQualifier() == EvqUniform)
43         {
44             doReplacement(decl, declarator, type);
45             return false;
46         }
47 
48         return true;
49     }
50 
visitSymbol(TIntermSymbol * symbol)51     void visitSymbol(TIntermSymbol *symbol) override
52     {
53         const TVariable *variable = &symbol->variable();
54         if (mVariableMap.count(variable) > 0)
55         {
56             queueReplacement(mVariableMap[variable]->deepCopy(), OriginalNode::IS_DROPPED);
57         }
58     }
59 
60   private:
doReplacement(TIntermDeclaration * decl,TIntermTyped * declarator,const TType & oldType)61     void doReplacement(TIntermDeclaration *decl, TIntermTyped *declarator, const TType &oldType)
62     {
63         const TStructure *structure = oldType.getStruct();
64         if (structure->symbolType() == SymbolType::Empty)
65         {
66             // Handle nameless structs: uniform struct { ... } variable;
67             structure = new TStructure(mSymbolTable, kEmptyImmutableString, &structure->fields(),
68                                        SymbolType::AngleInternal);
69         }
70         TType *namedType = new TType(structure, true);
71         namedType->setQualifier(EvqGlobal);
72 
73         TVariable *structVariable =
74             new TVariable(mSymbolTable, kEmptyImmutableString, namedType, SymbolType::Empty);
75         TIntermSymbol *structDeclarator       = new TIntermSymbol(structVariable);
76         TIntermDeclaration *structDeclaration = new TIntermDeclaration;
77         structDeclaration->appendDeclarator(structDeclarator);
78 
79         TIntermSequence newSequence;
80         newSequence.push_back(structDeclaration);
81 
82         // Redeclare the uniform with the (potentially) new struct type
83         TIntermSymbol *asSymbol = declarator->getAsSymbolNode();
84         ASSERT(asSymbol && asSymbol->variable().symbolType() != SymbolType::Empty);
85 
86         TIntermDeclaration *namedDecl = new TIntermDeclaration;
87         TType *uniformType            = new TType(structure, false);
88         uniformType->setQualifier(EvqUniform);
89         uniformType->makeArrays(oldType.getArraySizes());
90 
91         TVariable *newVar        = new TVariable(mSymbolTable, asSymbol->getName(), uniformType,
92                                           asSymbol->variable().symbolType());
93         TIntermSymbol *newSymbol = new TIntermSymbol(newVar);
94         namedDecl->appendDeclarator(newSymbol);
95 
96         newSequence.push_back(namedDecl);
97 
98         mVariableMap[&asSymbol->variable()] = newSymbol;
99 
100         mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), decl,
101                                         std::move(newSequence));
102     }
103 
104     VariableReplacementMap mVariableMap;
105 };
106 }  // anonymous namespace
107 
SeparateStructFromUniformDeclarations(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable)108 bool SeparateStructFromUniformDeclarations(TCompiler *compiler,
109                                            TIntermBlock *root,
110                                            TSymbolTable *symbolTable)
111 {
112     Traverser separateStructDecls(symbolTable);
113     root->traverse(&separateStructDecls);
114     return separateStructDecls.updateTree(compiler, root);
115 }
116 }  // namespace sh
117