1 | // |
2 | // Copyright 2016 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 | |
7 | // UseInterfaceBlockFields.cpp: insert statements to reference all members in InterfaceBlock list at |
8 | // the beginning of main. This is to work around a Mac driver that treats unused standard/shared |
9 | // uniform blocks as inactive. |
10 | |
11 | #include "compiler/translator/tree_ops/UseInterfaceBlockFields.h" |
12 | |
13 | #include "compiler/translator/IntermNode.h" |
14 | #include "compiler/translator/SymbolTable.h" |
15 | #include "compiler/translator/tree_util/FindMain.h" |
16 | #include "compiler/translator/tree_util/IntermNode_util.h" |
17 | #include "compiler/translator/util.h" |
18 | |
19 | namespace sh |
20 | { |
21 | |
22 | namespace |
23 | { |
24 | |
25 | void AddNodeUseStatements(TIntermTyped *node, TIntermSequence *sequence) |
26 | { |
27 | if (node->isArray()) |
28 | { |
29 | for (unsigned int i = 0u; i < node->getOutermostArraySize(); ++i) |
30 | { |
31 | TIntermBinary *element = |
32 | new TIntermBinary(EOpIndexDirect, node->deepCopy(), CreateIndexNode(i)); |
33 | AddNodeUseStatements(element, sequence); |
34 | } |
35 | } |
36 | else |
37 | { |
38 | sequence->insert(sequence->begin(), node); |
39 | } |
40 | } |
41 | |
42 | void AddFieldUseStatements(const ShaderVariable &var, |
43 | TIntermSequence *sequence, |
44 | const TSymbolTable &symbolTable) |
45 | { |
46 | ASSERT(var.name.find_last_of('[') == std::string::npos); |
47 | TIntermSymbol *symbol = ReferenceGlobalVariable(ImmutableString(var.name), symbolTable); |
48 | AddNodeUseStatements(symbol, sequence); |
49 | } |
50 | |
51 | void InsertUseCode(const InterfaceBlock &block, TIntermTyped *blockNode, TIntermSequence *sequence) |
52 | { |
53 | for (unsigned int i = 0; i < block.fields.size(); ++i) |
54 | { |
55 | TIntermBinary *element = new TIntermBinary(EOpIndexDirectInterfaceBlock, |
56 | blockNode->deepCopy(), CreateIndexNode(i)); |
57 | sequence->insert(sequence->begin(), element); |
58 | } |
59 | } |
60 | |
61 | void InsertUseCode(TIntermSequence *sequence, |
62 | const InterfaceBlockList &blocks, |
63 | const TSymbolTable &symbolTable) |
64 | { |
65 | for (const auto &block : blocks) |
66 | { |
67 | if (block.instanceName.empty()) |
68 | { |
69 | for (const auto &var : block.fields) |
70 | { |
71 | AddFieldUseStatements(var, sequence, symbolTable); |
72 | } |
73 | } |
74 | else if (block.arraySize > 0u) |
75 | { |
76 | TIntermSymbol *arraySymbol = |
77 | ReferenceGlobalVariable(ImmutableString(block.instanceName), symbolTable); |
78 | for (unsigned int i = 0u; i < block.arraySize; ++i) |
79 | { |
80 | TIntermBinary *elementSymbol = |
81 | new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(), CreateIndexNode(i)); |
82 | InsertUseCode(block, elementSymbol, sequence); |
83 | } |
84 | } |
85 | else |
86 | { |
87 | TIntermSymbol *blockSymbol = |
88 | ReferenceGlobalVariable(ImmutableString(block.instanceName), symbolTable); |
89 | InsertUseCode(block, blockSymbol, sequence); |
90 | } |
91 | } |
92 | } |
93 | |
94 | } // namespace |
95 | |
96 | void UseInterfaceBlockFields(TIntermBlock *root, |
97 | const InterfaceBlockList &blocks, |
98 | const TSymbolTable &symbolTable) |
99 | { |
100 | TIntermBlock *mainBody = FindMainBody(root); |
101 | InsertUseCode(mainBody->getSequence(), blocks, symbolTable); |
102 | } |
103 | |
104 | } // namespace sh |
105 | |