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 | // NameEmbeddedUniformStructs: Gives nameless uniform struct internal names. |
7 | // |
8 | |
9 | #include "compiler/translator/tree_ops/NameEmbeddedUniformStructs.h" |
10 | |
11 | #include "compiler/translator/SymbolTable.h" |
12 | #include "compiler/translator/tree_util/IntermTraverse.h" |
13 | |
14 | namespace sh |
15 | { |
16 | namespace |
17 | { |
18 | // This traverser translates embedded uniform structs into a specifier and declaration. |
19 | // This makes the declarations easier to move into uniform blocks. |
20 | class Traverser : public TIntermTraverser |
21 | { |
22 | public: |
23 | explicit Traverser(TSymbolTable *symbolTable) |
24 | : TIntermTraverser(true, false, false, symbolTable) |
25 | {} |
26 | |
27 | bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override |
28 | { |
29 | ASSERT(visit == PreVisit); |
30 | |
31 | if (!mInGlobalScope) |
32 | { |
33 | return false; |
34 | } |
35 | |
36 | const TIntermSequence &sequence = *(decl->getSequence()); |
37 | ASSERT(sequence.size() == 1); |
38 | TIntermTyped *declarator = sequence.front()->getAsTyped(); |
39 | const TType &type = declarator->getType(); |
40 | |
41 | if (type.isStructSpecifier() && type.getQualifier() == EvqUniform) |
42 | { |
43 | const TStructure *structure = type.getStruct(); |
44 | |
45 | if (structure->symbolType() == SymbolType::Empty) |
46 | { |
47 | doReplacement(decl, declarator, structure); |
48 | } |
49 | } |
50 | |
51 | return false; |
52 | } |
53 | |
54 | private: |
55 | void doReplacement(TIntermDeclaration *decl, |
56 | TIntermTyped *declarator, |
57 | const TStructure *oldStructure) |
58 | { |
59 | // struct <structName> { ... }; |
60 | TStructure *structure = new TStructure(mSymbolTable, kEmptyImmutableString, |
61 | &oldStructure->fields(), SymbolType::AngleInternal); |
62 | TType *namedType = new TType(structure, true); |
63 | namedType->setQualifier(EvqGlobal); |
64 | |
65 | TVariable *structVariable = |
66 | new TVariable(mSymbolTable, kEmptyImmutableString, namedType, SymbolType::Empty); |
67 | TIntermSymbol *structDeclarator = new TIntermSymbol(structVariable); |
68 | TIntermDeclaration *structDeclaration = new TIntermDeclaration; |
69 | structDeclaration->appendDeclarator(structDeclarator); |
70 | |
71 | TIntermSequence *newSequence = new TIntermSequence; |
72 | newSequence->push_back(structDeclaration); |
73 | |
74 | // uniform <structName> <structUniformName>; |
75 | TIntermSymbol *asSymbol = declarator->getAsSymbolNode(); |
76 | if (asSymbol && asSymbol->variable().symbolType() != SymbolType::Empty) |
77 | { |
78 | TIntermDeclaration *namedDecl = new TIntermDeclaration; |
79 | TType *uniformType = new TType(structure, false); |
80 | uniformType->setQualifier(EvqUniform); |
81 | |
82 | TVariable *newVar = new TVariable(mSymbolTable, asSymbol->getName(), uniformType, |
83 | asSymbol->variable().symbolType()); |
84 | TIntermSymbol *newSymbol = new TIntermSymbol(newVar); |
85 | namedDecl->appendDeclarator(newSymbol); |
86 | |
87 | newSequence->push_back(namedDecl); |
88 | } |
89 | |
90 | mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), decl, *newSequence); |
91 | } |
92 | }; |
93 | } // anonymous namespace |
94 | |
95 | void NameEmbeddedStructUniforms(TIntermBlock *root, TSymbolTable *symbolTable) |
96 | { |
97 | Traverser nameStructs(symbolTable); |
98 | root->traverse(&nameStructs); |
99 | nameStructs.updateTree(); |
100 | } |
101 | } // namespace sh |
102 | |