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