summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp')
-rw-r--r--gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp175
1 files changed, 175 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp
new file mode 100644
index 0000000000..ddbb22685d
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp
@@ -0,0 +1,175 @@
+//
+// Copyright 2020 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.
+//
+// ReplaceArrayOfMatrixVarying: Find any references to array of matrices varying
+// and replace it with array of vectors.
+//
+
+#include "compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.h"
+
+#include <vector>
+
+#include "common/bitset_utils.h"
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "compiler/translator/Compiler.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/tree_util/BuiltIn.h"
+#include "compiler/translator/tree_util/FindMain.h"
+#include "compiler/translator/tree_util/IntermNode_util.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
+#include "compiler/translator/tree_util/ReplaceVariable.h"
+#include "compiler/translator/tree_util/RunAtTheEndOfShader.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+// We create two variables to replace the given varying:
+// - The new varying which is an array of vectors to be used at input/ouput only.
+// - The new global variable which is a same type as given variable, to temporarily be used
+// as replacements for assignments, arithmetic ops and so on. During input/ouput phrase, this temp
+// variable will be copied from/to the array of vectors variable above.
+// NOTE(hqle): Consider eliminating the need for using temp variable.
+
+namespace
+{
+class CollectVaryingTraverser : public TIntermTraverser
+{
+ public:
+ CollectVaryingTraverser(std::vector<const TVariable *> *varyingsOut)
+ : TIntermTraverser(true, false, false), mVaryingsOut(varyingsOut)
+ {}
+
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
+ {
+ const TIntermSequence &sequence = *(node->getSequence());
+
+ if (sequence.size() != 1)
+ {
+ return false;
+ }
+
+ TIntermTyped *variableType = sequence.front()->getAsTyped();
+ if (!variableType || !IsVarying(variableType->getQualifier()) ||
+ !variableType->isMatrix() || !variableType->isArray())
+ {
+ return false;
+ }
+
+ TIntermSymbol *variableSymbol = variableType->getAsSymbolNode();
+ if (!variableSymbol)
+ {
+ return false;
+ }
+
+ mVaryingsOut->push_back(&variableSymbol->variable());
+
+ return false;
+ }
+
+ private:
+ std::vector<const TVariable *> *mVaryingsOut;
+};
+} // namespace
+
+[[nodiscard]] bool ReplaceArrayOfMatrixVarying(TCompiler *compiler,
+ TIntermBlock *root,
+ TSymbolTable *symbolTable,
+ const TVariable *varying)
+{
+ const TType &type = varying->getType();
+
+ // Create global variable to temporarily acts as the given variable in places such as
+ // arithmetic, assignments an so on.
+ TType *tmpReplacementType = new TType(type);
+ tmpReplacementType->setQualifier(EvqGlobal);
+
+ TVariable *tempReplaceVar = new TVariable(
+ symbolTable, ImmutableString(std::string("ANGLE_AOM_Temp_") + varying->name().data()),
+ tmpReplacementType, SymbolType::AngleInternal);
+
+ if (!ReplaceVariable(compiler, root, varying, tempReplaceVar))
+ {
+ return false;
+ }
+
+ // Create array of vectors type
+ TType *varyingReplaceType = new TType(type);
+ varyingReplaceType->toMatrixColumnType();
+ varyingReplaceType->toArrayElementType();
+ varyingReplaceType->makeArray(type.getCols() * type.getOutermostArraySize());
+
+ TVariable *varyingReplaceVar =
+ new TVariable(symbolTable, varying->name(), varyingReplaceType, SymbolType::UserDefined);
+
+ TIntermSymbol *varyingReplaceDeclarator = new TIntermSymbol(varyingReplaceVar);
+ TIntermDeclaration *varyingReplaceDecl = new TIntermDeclaration;
+ varyingReplaceDecl->appendDeclarator(varyingReplaceDeclarator);
+ root->insertStatement(0, varyingReplaceDecl);
+
+ // Copy from/to the temp variable
+ TIntermBlock *reassignBlock = new TIntermBlock;
+ TIntermSymbol *tempReplaceSymbol = new TIntermSymbol(tempReplaceVar);
+ TIntermSymbol *varyingReplaceSymbol = new TIntermSymbol(varyingReplaceVar);
+ bool isInput = IsVaryingIn(type.getQualifier());
+
+ for (unsigned int i = 0; i < type.getOutermostArraySize(); ++i)
+ {
+ TIntermBinary *tempMatrixIndexed =
+ new TIntermBinary(EOpIndexDirect, tempReplaceSymbol->deepCopy(), CreateIndexNode(i));
+ for (uint8_t col = 0; col < type.getCols(); ++col)
+ {
+
+ TIntermBinary *tempMatrixColIndexed = new TIntermBinary(
+ EOpIndexDirect, tempMatrixIndexed->deepCopy(), CreateIndexNode(col));
+ TIntermBinary *vectorIndexed =
+ new TIntermBinary(EOpIndexDirect, varyingReplaceSymbol->deepCopy(),
+ CreateIndexNode(i * type.getCols() + col));
+ TIntermBinary *assignment;
+ if (isInput)
+ {
+ assignment = new TIntermBinary(EOpAssign, tempMatrixColIndexed, vectorIndexed);
+ }
+ else
+ {
+ assignment = new TIntermBinary(EOpAssign, vectorIndexed, tempMatrixColIndexed);
+ }
+ reassignBlock->appendStatement(assignment);
+ }
+ }
+
+ if (isInput)
+ {
+ TIntermFunctionDefinition *main = FindMain(root);
+ main->getBody()->insertStatement(0, reassignBlock);
+ return compiler->validateAST(root);
+ }
+ else
+ {
+ return RunAtTheEndOfShader(compiler, root, reassignBlock, symbolTable);
+ }
+}
+
+[[nodiscard]] bool ReplaceArrayOfMatrixVaryings(TCompiler *compiler,
+ TIntermBlock *root,
+ TSymbolTable *symbolTable)
+{
+ std::vector<const TVariable *> arrayOfMatrixVars;
+ CollectVaryingTraverser varCollector(&arrayOfMatrixVars);
+ root->traverse(&varCollector);
+
+ for (const TVariable *var : arrayOfMatrixVars)
+ {
+ if (!ReplaceArrayOfMatrixVarying(compiler, root, symbolTable, var))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace sh