blob: 0819cabc4ce753fdacb7d6a08240fd8f41596de3 [file] [log] [blame]
//
// 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/FindMain.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/util.h"
namespace sh
{
namespace
{
void AddFieldUseStatements(const ShaderVariable &var,
TIntermSequence *sequence,
const TSymbolTable &symbolTable)
{
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 *>(symbolTable.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 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 > 0)
{
TString name = TString(block.instanceName.c_str());
TVariable *ubInfo = reinterpret_cast<TVariable *>(symbolTable.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 *>(symbolTable.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(TIntermBlock *root,
const InterfaceBlockList &blocks,
const TSymbolTable &symbolTable)
{
TIntermFunctionDefinition *main = FindMain(root);
TIntermBlock *mainBody = main->getBody();
ASSERT(mainBody);
InsertUseCode(mainBody->getSequence(), blocks, symbolTable);
}
} // namespace sh