blob: 2a1a812e2d140d71fec183ed4942dd25c45cef83 [file] [log] [blame]
Qin Jiajia7835b522016-10-08 11:20:17 +08001//
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/util.h"
15
16namespace sh
17{
18
19namespace
20{
21
22class UseUniformBlockMembers : public TIntermTraverser
23{
24 public:
25 UseUniformBlockMembers(const InterfaceBlockList &blocks)
26 : TIntermTraverser(true, false, false), mBlocks(blocks), mCodeInserted(false)
27 {
28 }
29
30 protected:
Olli Etuaho336b1472016-10-05 16:37:55 +010031 bool visitAggregate(Visit visit, TIntermAggregate *node) override { return !mCodeInserted; }
32 bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
Qin Jiajia7835b522016-10-08 11:20:17 +080033
34 private:
35 void insertUseCode(TIntermSequence *sequence);
36 void AddFieldUseStatements(const ShaderVariable &var, TIntermSequence *sequence);
37
38 const InterfaceBlockList &mBlocks;
39 bool mCodeInserted;
40};
41
Olli Etuaho336b1472016-10-05 16:37:55 +010042bool UseUniformBlockMembers::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
Qin Jiajia7835b522016-10-08 11:20:17 +080043{
Olli Etuaho336b1472016-10-05 16:37:55 +010044 ASSERT(visit == PreVisit);
45 if (node->getFunctionSymbolInfo()->isMain())
Qin Jiajia7835b522016-10-08 11:20:17 +080046 {
Olli Etuaho336b1472016-10-05 16:37:55 +010047 TIntermBlock *body = node->getBody();
48 ASSERT(body);
49 insertUseCode(body->getSequence());
50 mCodeInserted = true;
51 return false;
Qin Jiajia7835b522016-10-08 11:20:17 +080052 }
Olli Etuaho336b1472016-10-05 16:37:55 +010053 return !mCodeInserted;
Qin Jiajia7835b522016-10-08 11:20:17 +080054}
55
56void UseUniformBlockMembers::AddFieldUseStatements(const ShaderVariable &var,
57 TIntermSequence *sequence)
58{
59 TString name = TString(var.name.c_str());
60 TType type = GetShaderVariableType(var);
61
62 if (var.isArray())
63 {
64 size_t pos = name.find_last_of('[');
65 if (pos != TString::npos)
66 {
67 name = name.substr(0, pos);
68 }
69 TType elementType = type;
70 elementType.clearArrayness();
71
72 TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, type);
73 for (unsigned int i = 0; i < var.arraySize; ++i)
74 {
75 TIntermBinary *element =
76 new TIntermBinary(EOpIndexDirect, arraySymbol, TIntermTyped::CreateIndexNode(i));
77
78 sequence->insert(sequence->begin(), element);
79 }
80 }
81 else if (var.isStruct())
82 {
83 TIntermSymbol *structSymbol = new TIntermSymbol(0, name, type);
84 for (unsigned int i = 0; i < var.fields.size(); ++i)
85 {
86 TIntermBinary *element = new TIntermBinary(EOpIndexDirectStruct, structSymbol,
87 TIntermTyped::CreateIndexNode(i));
88
89 sequence->insert(sequence->begin(), element);
90 }
91 }
92 else
93 {
94 TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
95
96 sequence->insert(sequence->begin(), symbol);
97 }
98}
99
100void UseUniformBlockMembers::insertUseCode(TIntermSequence *sequence)
101{
102 for (const auto &block : mBlocks)
103 {
104 if (block.instanceName.empty())
105 {
106 for (const auto &var : block.fields)
107 {
108 AddFieldUseStatements(var, sequence);
109 }
110 }
111 else if (block.arraySize > 0)
112 {
113 TType type = GetInterfaceBlockType(block);
114 TString name = TString(block.instanceName.c_str());
115 TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, type);
116 for (unsigned int i = 0; i < block.arraySize; ++i)
117 {
118 TIntermBinary *instanceSymbol = new TIntermBinary(EOpIndexDirect, arraySymbol,
119 TIntermTyped::CreateIndexNode(i));
120 for (unsigned int j = 0; j < block.fields.size(); ++j)
121 {
122 TIntermBinary *element =
123 new TIntermBinary(EOpIndexDirectInterfaceBlock, instanceSymbol,
124 TIntermTyped::CreateIndexNode(j));
125 sequence->insert(sequence->begin(), element);
126 }
127 }
128 }
129 else
130 {
131 TType type = GetInterfaceBlockType(block);
132 TString name = TString(block.instanceName.c_str());
133 TIntermSymbol *blockSymbol = new TIntermSymbol(0, name, type);
134 for (unsigned int i = 0; i < block.fields.size(); ++i)
135 {
136 TIntermBinary *element = new TIntermBinary(
137 EOpIndexDirectInterfaceBlock, blockSymbol, TIntermTyped::CreateIndexNode(i));
138
139 sequence->insert(sequence->begin(), element);
140 }
141 }
142 }
143}
144
145} // namespace anonymous
146
147void UseInterfaceBlockFields(TIntermNode *root, const InterfaceBlockList &blocks)
148{
149 UseUniformBlockMembers useUniformBlock(blocks);
150 root->traverse(&useUniformBlock);
151}
152
153} // namespace sh