blob: 390e2b092acaa0c64c5b2882a6c196901c5e1b6f [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"
Zhenyao Mod7490962016-11-09 15:49:51 -080014#include "compiler/translator/SymbolTable.h"
Qin Jiajia7835b522016-10-08 11:20:17 +080015#include "compiler/translator/util.h"
16
17namespace sh
18{
19
20namespace
21{
22
23class UseUniformBlockMembers : public TIntermTraverser
24{
25 public:
Zhenyao Mod7490962016-11-09 15:49:51 -080026 UseUniformBlockMembers(const InterfaceBlockList &blocks, const TSymbolTable &symbolTable)
27 : TIntermTraverser(true, false, false),
28 mBlocks(blocks),
29 mSymbolTable(symbolTable),
30 mCodeInserted(false)
Qin Jiajia7835b522016-10-08 11:20:17 +080031 {
Zhenyao Mod7490962016-11-09 15:49:51 -080032 ASSERT(mSymbolTable.atGlobalLevel());
Qin Jiajia7835b522016-10-08 11:20:17 +080033 }
34
35 protected:
Olli Etuaho336b1472016-10-05 16:37:55 +010036 bool visitAggregate(Visit visit, TIntermAggregate *node) override { return !mCodeInserted; }
37 bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
Qin Jiajia7835b522016-10-08 11:20:17 +080038
39 private:
40 void insertUseCode(TIntermSequence *sequence);
41 void AddFieldUseStatements(const ShaderVariable &var, TIntermSequence *sequence);
42
43 const InterfaceBlockList &mBlocks;
Zhenyao Mod7490962016-11-09 15:49:51 -080044 const TSymbolTable &mSymbolTable;
Qin Jiajia7835b522016-10-08 11:20:17 +080045 bool mCodeInserted;
46};
47
Olli Etuaho336b1472016-10-05 16:37:55 +010048bool UseUniformBlockMembers::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
Qin Jiajia7835b522016-10-08 11:20:17 +080049{
Olli Etuaho336b1472016-10-05 16:37:55 +010050 ASSERT(visit == PreVisit);
51 if (node->getFunctionSymbolInfo()->isMain())
Qin Jiajia7835b522016-10-08 11:20:17 +080052 {
Olli Etuaho336b1472016-10-05 16:37:55 +010053 TIntermBlock *body = node->getBody();
54 ASSERT(body);
55 insertUseCode(body->getSequence());
56 mCodeInserted = true;
57 return false;
Qin Jiajia7835b522016-10-08 11:20:17 +080058 }
Olli Etuaho336b1472016-10-05 16:37:55 +010059 return !mCodeInserted;
Qin Jiajia7835b522016-10-08 11:20:17 +080060}
61
62void UseUniformBlockMembers::AddFieldUseStatements(const ShaderVariable &var,
63 TIntermSequence *sequence)
64{
65 TString name = TString(var.name.c_str());
Qin Jiajia7835b522016-10-08 11:20:17 +080066 if (var.isArray())
67 {
68 size_t pos = name.find_last_of('[');
69 if (pos != TString::npos)
70 {
71 name = name.substr(0, pos);
72 }
Zhenyao Mod7490962016-11-09 15:49:51 -080073 }
74 const TType *type;
75 TType basicType;
76 if (var.isStruct())
77 {
78 TVariable *structInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name));
79 ASSERT(structInfo);
80 const TType &structType = structInfo->getType();
81 type = &structType;
82 }
83 else
84 {
85 basicType = sh::GetShaderVariableBasicType(var);
86 type = &basicType;
87 }
88 ASSERT(type);
Qin Jiajia7835b522016-10-08 11:20:17 +080089
Zhenyao Mod7490962016-11-09 15:49:51 -080090 TIntermSymbol *symbol = new TIntermSymbol(0, name, *type);
91 if (var.isArray())
92 {
Qin Jiajia7835b522016-10-08 11:20:17 +080093 for (unsigned int i = 0; i < var.arraySize; ++i)
94 {
95 TIntermBinary *element =
Zhenyao Mod7490962016-11-09 15:49:51 -080096 new TIntermBinary(EOpIndexDirect, symbol, TIntermTyped::CreateIndexNode(i));
Qin Jiajia7835b522016-10-08 11:20:17 +080097 sequence->insert(sequence->begin(), element);
98 }
99 }
100 else
101 {
Qin Jiajia7835b522016-10-08 11:20:17 +0800102 sequence->insert(sequence->begin(), symbol);
103 }
104}
105
106void UseUniformBlockMembers::insertUseCode(TIntermSequence *sequence)
107{
108 for (const auto &block : mBlocks)
109 {
110 if (block.instanceName.empty())
111 {
112 for (const auto &var : block.fields)
113 {
114 AddFieldUseStatements(var, sequence);
115 }
116 }
117 else if (block.arraySize > 0)
118 {
Zhenyao Mod7490962016-11-09 15:49:51 -0800119 TString name = TString(block.instanceName.c_str());
120 TVariable *ubInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name));
121 ASSERT(ubInfo);
122 TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, ubInfo->getType());
Qin Jiajia7835b522016-10-08 11:20:17 +0800123 for (unsigned int i = 0; i < block.arraySize; ++i)
124 {
125 TIntermBinary *instanceSymbol = new TIntermBinary(EOpIndexDirect, arraySymbol,
126 TIntermTyped::CreateIndexNode(i));
127 for (unsigned int j = 0; j < block.fields.size(); ++j)
128 {
129 TIntermBinary *element =
130 new TIntermBinary(EOpIndexDirectInterfaceBlock, instanceSymbol,
131 TIntermTyped::CreateIndexNode(j));
132 sequence->insert(sequence->begin(), element);
133 }
134 }
135 }
136 else
137 {
Zhenyao Mod7490962016-11-09 15:49:51 -0800138 TString name = TString(block.instanceName.c_str());
139 TVariable *ubInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name));
140 ASSERT(ubInfo);
141 TIntermSymbol *blockSymbol = new TIntermSymbol(0, name, ubInfo->getType());
Qin Jiajia7835b522016-10-08 11:20:17 +0800142 for (unsigned int i = 0; i < block.fields.size(); ++i)
143 {
144 TIntermBinary *element = new TIntermBinary(
145 EOpIndexDirectInterfaceBlock, blockSymbol, TIntermTyped::CreateIndexNode(i));
146
147 sequence->insert(sequence->begin(), element);
148 }
149 }
150 }
151}
152
153} // namespace anonymous
154
Zhenyao Mod7490962016-11-09 15:49:51 -0800155void UseInterfaceBlockFields(TIntermNode *root,
156 const InterfaceBlockList &blocks,
157 const TSymbolTable &symbolTable)
Qin Jiajia7835b522016-10-08 11:20:17 +0800158{
Zhenyao Mod7490962016-11-09 15:49:51 -0800159 UseUniformBlockMembers useUniformBlock(blocks, symbolTable);
Qin Jiajia7835b522016-10-08 11:20:17 +0800160 root->traverse(&useUniformBlock);
161}
162
163} // namespace sh