Hash :
336b1470
Author :
Date :
2016-10-05T16:37:55
Split TIntermFunctionDefinition from TIntermAggregate This makes the code easier to understand. Function definition nodes always have just two children, the parameters node and the function body node, so there was no proper reason why they should be aggregate nodes. As a part of this change, intermediate output is modified to print symbol table ids of functions so that debugging function id related functionality will be easier in the future. After this patch, TIntermAggregate is still used for function prototypes, function parameter lists, function calls, variable and invariant declarations and the comma (sequence) operator. BUG=angleproject:1490 TEST=angle_unittests, angle_end2end_tests Change-Id: Ib88b4ca5d21abd5f126836ca5900d0baecabd19e Reviewed-on: https://chromium-review.googlesource.com/394707 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: Geoff Lang <geofflang@chromium.org>
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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
//
// 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/UseInterfaceBlockFields.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/util.h"
namespace sh
{
namespace
{
class UseUniformBlockMembers : public TIntermTraverser
{
public:
UseUniformBlockMembers(const InterfaceBlockList &blocks)
: TIntermTraverser(true, false, false), mBlocks(blocks), mCodeInserted(false)
{
}
protected:
bool visitAggregate(Visit visit, TIntermAggregate *node) override { return !mCodeInserted; }
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
private:
void insertUseCode(TIntermSequence *sequence);
void AddFieldUseStatements(const ShaderVariable &var, TIntermSequence *sequence);
const InterfaceBlockList &mBlocks;
bool mCodeInserted;
};
bool UseUniformBlockMembers::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
{
ASSERT(visit == PreVisit);
if (node->getFunctionSymbolInfo()->isMain())
{
TIntermBlock *body = node->getBody();
ASSERT(body);
insertUseCode(body->getSequence());
mCodeInserted = true;
return false;
}
return !mCodeInserted;
}
void UseUniformBlockMembers::AddFieldUseStatements(const ShaderVariable &var,
TIntermSequence *sequence)
{
TString name = TString(var.name.c_str());
TType type = GetShaderVariableType(var);
if (var.isArray())
{
size_t pos = name.find_last_of('[');
if (pos != TString::npos)
{
name = name.substr(0, pos);
}
TType elementType = type;
elementType.clearArrayness();
TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, type);
for (unsigned int i = 0; i < var.arraySize; ++i)
{
TIntermBinary *element =
new TIntermBinary(EOpIndexDirect, arraySymbol, TIntermTyped::CreateIndexNode(i));
sequence->insert(sequence->begin(), element);
}
}
else if (var.isStruct())
{
TIntermSymbol *structSymbol = new TIntermSymbol(0, name, type);
for (unsigned int i = 0; i < var.fields.size(); ++i)
{
TIntermBinary *element = new TIntermBinary(EOpIndexDirectStruct, structSymbol,
TIntermTyped::CreateIndexNode(i));
sequence->insert(sequence->begin(), element);
}
}
else
{
TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
sequence->insert(sequence->begin(), symbol);
}
}
void UseUniformBlockMembers::insertUseCode(TIntermSequence *sequence)
{
for (const auto &block : mBlocks)
{
if (block.instanceName.empty())
{
for (const auto &var : block.fields)
{
AddFieldUseStatements(var, sequence);
}
}
else if (block.arraySize > 0)
{
TType type = GetInterfaceBlockType(block);
TString name = TString(block.instanceName.c_str());
TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, type);
for (unsigned int i = 0; i < block.arraySize; ++i)
{
TIntermBinary *instanceSymbol = new TIntermBinary(EOpIndexDirect, arraySymbol,
TIntermTyped::CreateIndexNode(i));
for (unsigned int j = 0; j < block.fields.size(); ++j)
{
TIntermBinary *element =
new TIntermBinary(EOpIndexDirectInterfaceBlock, instanceSymbol,
TIntermTyped::CreateIndexNode(j));
sequence->insert(sequence->begin(), element);
}
}
}
else
{
TType type = GetInterfaceBlockType(block);
TString name = TString(block.instanceName.c_str());
TIntermSymbol *blockSymbol = new TIntermSymbol(0, name, type);
for (unsigned int i = 0; i < block.fields.size(); ++i)
{
TIntermBinary *element = new TIntermBinary(
EOpIndexDirectInterfaceBlock, blockSymbol, TIntermTyped::CreateIndexNode(i));
sequence->insert(sequence->begin(), element);
}
}
}
}
} // namespace anonymous
void UseInterfaceBlockFields(TIntermNode *root, const InterfaceBlockList &blocks)
{
UseUniformBlockMembers useUniformBlock(blocks);
root->traverse(&useUniformBlock);
}
} // namespace sh