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/UseInterfaceBlockFields.h"
12
13 #include "compiler/translator/FindMain.h"
14 #include "compiler/translator/IntermNode.h"
15 #include "compiler/translator/IntermNode_util.h"
16 #include "compiler/translator/SymbolTable.h"
17 #include "compiler/translator/util.h"
18
19 namespace sh
20 {
21
22 namespace
23 {
24
AddNodeUseStatements(TIntermTyped * node,TIntermSequence * sequence)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
AddFieldUseStatements(const ShaderVariable & var,TIntermSequence * sequence,const TSymbolTable & symbolTable)42 void AddFieldUseStatements(const ShaderVariable &var,
43 TIntermSequence *sequence,
44 const TSymbolTable &symbolTable)
45 {
46 TString name = TString(var.name.c_str());
47 ASSERT(name.find_last_of('[') == TString::npos);
48 TIntermSymbol *symbol = ReferenceGlobalVariable(name, symbolTable);
49 AddNodeUseStatements(symbol, sequence);
50 }
51
InsertUseCode(const InterfaceBlock & block,TIntermTyped * blockNode,TIntermSequence * sequence)52 void InsertUseCode(const InterfaceBlock &block, TIntermTyped *blockNode, TIntermSequence *sequence)
53 {
54 for (unsigned int i = 0; i < block.fields.size(); ++i)
55 {
56 TIntermBinary *element = new TIntermBinary(EOpIndexDirectInterfaceBlock,
57 blockNode->deepCopy(), CreateIndexNode(i));
58 sequence->insert(sequence->begin(), element);
59 }
60 }
61
InsertUseCode(TIntermSequence * sequence,const InterfaceBlockList & blocks,const TSymbolTable & symbolTable)62 void InsertUseCode(TIntermSequence *sequence,
63 const InterfaceBlockList &blocks,
64 const TSymbolTable &symbolTable)
65 {
66 for (const auto &block : blocks)
67 {
68 if (block.instanceName.empty())
69 {
70 for (const auto &var : block.fields)
71 {
72 AddFieldUseStatements(var, sequence, symbolTable);
73 }
74 }
75 else if (block.arraySize > 0u)
76 {
77 TString name(block.instanceName.c_str());
78 TIntermSymbol *arraySymbol = ReferenceGlobalVariable(name, symbolTable);
79 for (unsigned int i = 0u; i < block.arraySize; ++i)
80 {
81 TIntermBinary *elementSymbol =
82 new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(), CreateIndexNode(i));
83 InsertUseCode(block, elementSymbol, sequence);
84 }
85 }
86 else
87 {
88 TString name(block.instanceName.c_str());
89 TIntermSymbol *blockSymbol = ReferenceGlobalVariable(name, symbolTable);
90 InsertUseCode(block, blockSymbol, sequence);
91 }
92 }
93 }
94
95 } // namespace anonymous
96
UseInterfaceBlockFields(TIntermBlock * root,const InterfaceBlockList & blocks,const TSymbolTable & symbolTable)97 void UseInterfaceBlockFields(TIntermBlock *root,
98 const InterfaceBlockList &blocks,
99 const TSymbolTable &symbolTable)
100 {
101 TIntermBlock *mainBody = FindMainBody(root);
102 InsertUseCode(mainBody->getSequence(), blocks, symbolTable);
103 }
104
105 } // namespace sh
106