UseInterfaceBlockFields.cpp (3568B)
1 // 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/tree_ops/gl/UseInterfaceBlockFields.h" 12 13 #include "compiler/translator/Compiler.h" 14 #include "compiler/translator/IntermNode.h" 15 #include "compiler/translator/SymbolTable.h" 16 #include "compiler/translator/tree_util/FindMain.h" 17 #include "compiler/translator/tree_util/IntermNode_util.h" 18 #include "compiler/translator/util.h" 19 20 namespace sh 21 { 22 23 namespace 24 { 25 26 void AddNodeUseStatements(TIntermTyped *node, TIntermSequence *sequence) 27 { 28 if (node->isArray()) 29 { 30 for (unsigned int i = 0u; i < node->getOutermostArraySize(); ++i) 31 { 32 TIntermBinary *element = 33 new TIntermBinary(EOpIndexDirect, node->deepCopy(), CreateIndexNode(i)); 34 AddNodeUseStatements(element, sequence); 35 } 36 } 37 else 38 { 39 sequence->insert(sequence->begin(), node); 40 } 41 } 42 43 void AddFieldUseStatements(const ShaderVariable &var, 44 TIntermSequence *sequence, 45 const TSymbolTable &symbolTable) 46 { 47 ASSERT(var.name.find_last_of('[') == std::string::npos); 48 TIntermSymbol *symbol = ReferenceGlobalVariable(ImmutableString(var.name), symbolTable); 49 AddNodeUseStatements(symbol, sequence); 50 } 51 52 void InsertUseCode(const InterfaceBlock &block, TIntermTyped *blockNode, TIntermSequence *sequence) 53 { 54 for (unsigned int i = 0; i < block.fields.size(); ++i) 55 { 56 TIntermBinary *element = new TIntermBinary(EOpIndexDirectInterfaceBlock, 57 blockNode->deepCopy(), CreateIndexNode(i)); 58 sequence->insert(sequence->begin(), element); 59 } 60 } 61 62 void InsertUseCode(TIntermSequence *sequence, 63 const InterfaceBlockList &blocks, 64 const TSymbolTable &symbolTable) 65 { 66 for (const auto &block : blocks) 67 { 68 if (block.instanceName.empty()) 69 { 70 for (const auto &var : block.fields) 71 { 72 AddFieldUseStatements(var, sequence, symbolTable); 73 } 74 } 75 else if (block.arraySize > 0u) 76 { 77 TIntermSymbol *arraySymbol = 78 ReferenceGlobalVariable(ImmutableString(block.instanceName), symbolTable); 79 for (unsigned int i = 0u; i < block.arraySize; ++i) 80 { 81 TIntermBinary *elementSymbol = 82 new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(), CreateIndexNode(i)); 83 InsertUseCode(block, elementSymbol, sequence); 84 } 85 } 86 else 87 { 88 TIntermSymbol *blockSymbol = 89 ReferenceGlobalVariable(ImmutableString(block.instanceName), symbolTable); 90 InsertUseCode(block, blockSymbol, sequence); 91 } 92 } 93 } 94 95 } // namespace 96 97 bool UseInterfaceBlockFields(TCompiler *compiler, 98 TIntermBlock *root, 99 const InterfaceBlockList &blocks, 100 const TSymbolTable &symbolTable) 101 { 102 TIntermBlock *mainBody = FindMainBody(root); 103 InsertUseCode(mainBody->getSequence(), blocks, symbolTable); 104 105 return compiler->validateAST(root); 106 } 107 108 } // namespace sh