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:
Traverser(TSymbolTable * symbolTable)23 explicit Traverser(TSymbolTable *symbolTable)
24 : TIntermTraverser(true, false, false, symbolTable)
25 {}
26
visitDeclaration(Visit visit,TIntermDeclaration * decl)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:
doReplacement(TIntermDeclaration * decl,TIntermTyped * declarator,const TStructure * oldStructure)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
NameEmbeddedStructUniforms(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable)95 bool NameEmbeddedStructUniforms(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable)
96 {
97 Traverser nameStructs(symbolTable);
98 root->traverse(&nameStructs);
99 return nameStructs.updateTree(compiler, root);
100 }
101 } // namespace sh
102