Line data Source code
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/IntermNode.h"
14 : #include "compiler/translator/SymbolTable.h"
15 : #include "compiler/translator/util.h"
16 :
17 : namespace sh
18 : {
19 :
20 : namespace
21 : {
22 :
23 0 : class UseUniformBlockMembers : public TIntermTraverser
24 : {
25 : public:
26 0 : UseUniformBlockMembers(const InterfaceBlockList &blocks, const TSymbolTable &symbolTable)
27 0 : : TIntermTraverser(true, false, false),
28 : mBlocks(blocks),
29 : mSymbolTable(symbolTable),
30 0 : mCodeInserted(false)
31 : {
32 0 : ASSERT(mSymbolTable.atGlobalLevel());
33 0 : }
34 :
35 : protected:
36 0 : bool visitAggregate(Visit visit, TIntermAggregate *node) override { return !mCodeInserted; }
37 : bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
38 :
39 : private:
40 : void insertUseCode(TIntermSequence *sequence);
41 : void AddFieldUseStatements(const ShaderVariable &var, TIntermSequence *sequence);
42 :
43 : const InterfaceBlockList &mBlocks;
44 : const TSymbolTable &mSymbolTable;
45 : bool mCodeInserted;
46 : };
47 :
48 0 : bool UseUniformBlockMembers::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
49 : {
50 0 : ASSERT(visit == PreVisit);
51 0 : if (node->getFunctionSymbolInfo()->isMain())
52 : {
53 0 : TIntermBlock *body = node->getBody();
54 0 : ASSERT(body);
55 0 : insertUseCode(body->getSequence());
56 0 : mCodeInserted = true;
57 0 : return false;
58 : }
59 0 : return !mCodeInserted;
60 : }
61 :
62 0 : void UseUniformBlockMembers::AddFieldUseStatements(const ShaderVariable &var,
63 : TIntermSequence *sequence)
64 : {
65 0 : TString name = TString(var.name.c_str());
66 0 : if (var.isArray())
67 : {
68 0 : size_t pos = name.find_last_of('[');
69 0 : if (pos != TString::npos)
70 : {
71 0 : name = name.substr(0, pos);
72 : }
73 : }
74 : const TType *type;
75 0 : TType basicType;
76 0 : if (var.isStruct())
77 : {
78 0 : TVariable *structInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name));
79 0 : ASSERT(structInfo);
80 0 : const TType &structType = structInfo->getType();
81 0 : type = &structType;
82 : }
83 : else
84 : {
85 0 : basicType = sh::GetShaderVariableBasicType(var);
86 0 : type = &basicType;
87 : }
88 0 : ASSERT(type);
89 :
90 0 : TIntermSymbol *symbol = new TIntermSymbol(0, name, *type);
91 0 : if (var.isArray())
92 : {
93 0 : for (unsigned int i = 0; i < var.arraySize; ++i)
94 : {
95 : TIntermBinary *element =
96 0 : new TIntermBinary(EOpIndexDirect, symbol, TIntermTyped::CreateIndexNode(i));
97 0 : sequence->insert(sequence->begin(), element);
98 : }
99 : }
100 : else
101 : {
102 0 : sequence->insert(sequence->begin(), symbol);
103 : }
104 0 : }
105 :
106 0 : void UseUniformBlockMembers::insertUseCode(TIntermSequence *sequence)
107 : {
108 0 : for (const auto &block : mBlocks)
109 : {
110 0 : if (block.instanceName.empty())
111 : {
112 0 : for (const auto &var : block.fields)
113 : {
114 0 : AddFieldUseStatements(var, sequence);
115 : }
116 : }
117 0 : else if (block.arraySize > 0)
118 : {
119 0 : TString name = TString(block.instanceName.c_str());
120 0 : TVariable *ubInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name));
121 0 : ASSERT(ubInfo);
122 0 : TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, ubInfo->getType());
123 0 : for (unsigned int i = 0; i < block.arraySize; ++i)
124 : {
125 : TIntermBinary *instanceSymbol = new TIntermBinary(EOpIndexDirect, arraySymbol,
126 0 : TIntermTyped::CreateIndexNode(i));
127 0 : for (unsigned int j = 0; j < block.fields.size(); ++j)
128 : {
129 : TIntermBinary *element =
130 : new TIntermBinary(EOpIndexDirectInterfaceBlock, instanceSymbol,
131 0 : TIntermTyped::CreateIndexNode(j));
132 0 : sequence->insert(sequence->begin(), element);
133 : }
134 : }
135 : }
136 : else
137 : {
138 0 : TString name = TString(block.instanceName.c_str());
139 0 : TVariable *ubInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name));
140 0 : ASSERT(ubInfo);
141 0 : TIntermSymbol *blockSymbol = new TIntermSymbol(0, name, ubInfo->getType());
142 0 : for (unsigned int i = 0; i < block.fields.size(); ++i)
143 : {
144 : TIntermBinary *element = new TIntermBinary(
145 0 : EOpIndexDirectInterfaceBlock, blockSymbol, TIntermTyped::CreateIndexNode(i));
146 :
147 0 : sequence->insert(sequence->begin(), element);
148 : }
149 : }
150 : }
151 0 : }
152 :
153 : } // namespace anonymous
154 :
155 0 : void UseInterfaceBlockFields(TIntermNode *root,
156 : const InterfaceBlockList &blocks,
157 : const TSymbolTable &symbolTable)
158 : {
159 0 : UseUniformBlockMembers useUniformBlock(blocks, symbolTable);
160 0 : root->traverse(&useUniformBlock);
161 0 : }
162 :
163 : } // namespace sh
|