| // |
| // 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/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 |