diff options
Diffstat (limited to 'gfx/angle/src/compiler/translator/UseInterfaceBlockFields.cpp')
-rw-r--r-- | gfx/angle/src/compiler/translator/UseInterfaceBlockFields.cpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/gfx/angle/src/compiler/translator/UseInterfaceBlockFields.cpp b/gfx/angle/src/compiler/translator/UseInterfaceBlockFields.cpp new file mode 100644 index 000000000..390e2b092 --- /dev/null +++ b/gfx/angle/src/compiler/translator/UseInterfaceBlockFields.cpp @@ -0,0 +1,163 @@ +// +// 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/SymbolTable.h" +#include "compiler/translator/util.h" + +namespace sh +{ + +namespace +{ + +class UseUniformBlockMembers : public TIntermTraverser +{ + public: + UseUniformBlockMembers(const InterfaceBlockList &blocks, const TSymbolTable &symbolTable) + : TIntermTraverser(true, false, false), + mBlocks(blocks), + mSymbolTable(symbolTable), + mCodeInserted(false) + { + ASSERT(mSymbolTable.atGlobalLevel()); + } + + 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; + const TSymbolTable &mSymbolTable; + 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()); + if (var.isArray()) + { + size_t pos = name.find_last_of('['); + if (pos != TString::npos) + { + name = name.substr(0, pos); + } + } + const TType *type; + TType basicType; + if (var.isStruct()) + { + TVariable *structInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name)); + ASSERT(structInfo); + const TType &structType = structInfo->getType(); + type = &structType; + } + else + { + basicType = sh::GetShaderVariableBasicType(var); + type = &basicType; + } + ASSERT(type); + + TIntermSymbol *symbol = new TIntermSymbol(0, name, *type); + if (var.isArray()) + { + for (unsigned int i = 0; i < var.arraySize; ++i) + { + TIntermBinary *element = + new TIntermBinary(EOpIndexDirect, symbol, TIntermTyped::CreateIndexNode(i)); + sequence->insert(sequence->begin(), element); + } + } + else + { + 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) + { + TString name = TString(block.instanceName.c_str()); + TVariable *ubInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name)); + ASSERT(ubInfo); + TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, ubInfo->getType()); + 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 + { + TString name = TString(block.instanceName.c_str()); + TVariable *ubInfo = reinterpret_cast<TVariable *>(mSymbolTable.findGlobal(name)); + ASSERT(ubInfo); + TIntermSymbol *blockSymbol = new TIntermSymbol(0, name, ubInfo->getType()); + 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, + const TSymbolTable &symbolTable) +{ + UseUniformBlockMembers useUniformBlock(blocks, symbolTable); + root->traverse(&useUniformBlock); +} + +} // namespace sh |