Commit 9ff58ddd by Le Hoang Quyen Committed by Commit Bot

Metal: Support array of matrices varying.

MSL doesn't support array of matrices as varying variable. This CL converts array of matrices varying to array of vectors. This fixes WebGL test: conformance/glsl/misc/shader-varying-packing-restrictions.html Bug: angleproject:4846 Bug: angleproject:2634 Change-Id: I3cfc638dc01092ddf1add7df02c131d1a5c8ba1d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2392172 Commit-Queue: Le Hoang Quyen <le.hoang.q@gmail.com> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 49f01a53
...@@ -217,6 +217,8 @@ angle_translator_sources = [ ...@@ -217,6 +217,8 @@ angle_translator_sources = [
"src/compiler/translator/tree_util/IntermTraverse.cpp", "src/compiler/translator/tree_util/IntermTraverse.cpp",
"src/compiler/translator/tree_util/IntermTraverse.h", "src/compiler/translator/tree_util/IntermTraverse.h",
"src/compiler/translator/tree_util/NodeSearch.h", "src/compiler/translator/tree_util/NodeSearch.h",
"src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.cpp",
"src/compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.h",
"src/compiler/translator/tree_util/ReplaceClipDistanceVariable.cpp", "src/compiler/translator/tree_util/ReplaceClipDistanceVariable.cpp",
"src/compiler/translator/tree_util/ReplaceClipDistanceVariable.h", "src/compiler/translator/tree_util/ReplaceClipDistanceVariable.h",
"src/compiler/translator/tree_util/ReplaceShadowingVariables.cpp", "src/compiler/translator/tree_util/ReplaceShadowingVariables.cpp",
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "compiler/translator/tree_util/FindMain.h" #include "compiler/translator/tree_util/FindMain.h"
#include "compiler/translator/tree_util/FindSymbolNode.h" #include "compiler/translator/tree_util/FindSymbolNode.h"
#include "compiler/translator/tree_util/IntermNode_util.h" #include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/ReplaceArrayOfMatrixVarying.h"
#include "compiler/translator/tree_util/ReplaceVariable.h" #include "compiler/translator/tree_util/ReplaceVariable.h"
#include "compiler/translator/tree_util/RunAtTheEndOfShader.h" #include "compiler/translator/tree_util/RunAtTheEndOfShader.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
...@@ -141,6 +142,12 @@ bool TranslatorMetal::translate(TIntermBlock *root, ...@@ -141,6 +142,12 @@ bool TranslatorMetal::translate(TIntermBlock *root,
return false; return false;
} }
// Replace array of matrix varyings
if (!ReplaceArrayOfMatrixVaryings(this, root, &getSymbolTable()))
{
return false;
}
if (getShaderType() == GL_VERTEX_SHADER) if (getShaderType() == GL_VERTEX_SHADER)
{ {
auto negFlipY = getDriverUniformNegFlipYRef(driverUniforms); auto negFlipY = getDriverUniformNegFlipYRef(driverUniforms);
......
//
// 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
ANGLE_NO_DISCARD 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);
tmpReplacementType->realize();
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.getBasicType(), type.getPrecision(), type.getQualifier(),
static_cast<unsigned char>(type.getRows()), 1);
varyingReplaceType->setInvariant(type.isInvariant());
varyingReplaceType->setMemoryQualifier(type.getMemoryQualifier());
varyingReplaceType->setLayoutQualifier(type.getLayoutQualifier());
varyingReplaceType->makeArray(type.getCols() * type.getOutermostArraySize());
varyingReplaceType->realize();
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 (int 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);
}
}
ANGLE_NO_DISCARD 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
//
// 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.
//
#ifndef COMPILER_TRANSLATOR_TREEUTIL_REPLACEARRAYOFMATRIXVARYING_H_
#define COMPILER_TRANSLATOR_TREEUTIL_REPLACEARRAYOFMATRIXVARYING_H_
#include "common/angleutils.h"
namespace sh
{
class TCompiler;
class TIntermBlock;
class TSymbolTable;
class TVariable;
ANGLE_NO_DISCARD bool ReplaceArrayOfMatrixVarying(TCompiler *compiler,
TIntermBlock *root,
TSymbolTable *symbolTable,
const TVariable *varying);
ANGLE_NO_DISCARD bool ReplaceArrayOfMatrixVaryings(TCompiler *compiler,
TIntermBlock *root,
TSymbolTable *symbolTable);
} // namespace sh
#endif
...@@ -2801,6 +2801,120 @@ void main(void) ...@@ -2801,6 +2801,120 @@ void main(void)
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS); ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
} }
// Test that using a varying matrix array is supported.
TEST_P(GLSLTest, VaryingMatrixArray)
{
constexpr char kVS[] =
"uniform vec2 u_a1;\n"
"uniform vec2 u_a2;\n"
"attribute vec4 a_position;\n"
"varying mat2 v_mat[2];\n"
"void main() {\n"
" v_mat[0] = mat2(u_a1, u_a2);\n"
" v_mat[1] = mat2(1.0 - u_a2, 1.0 - u_a1);\n"
" gl_Position = a_position;\n"
"}";
constexpr char kFS[] =
"precision mediump float;\n"
"varying mat2 v_mat[2];\n"
"void main(void)\n"
"{\n"
" gl_FragColor = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
"}";
ANGLE_GL_PROGRAM(program, kVS, kFS);
GLint oneIndex = glGetUniformLocation(program, "u_a1");
ASSERT_NE(-1, oneIndex);
GLint twoIndex = glGetUniformLocation(program, "u_a2");
ASSERT_NE(-1, twoIndex);
glUseProgram(program);
glUniform2f(oneIndex, 1, 0.5f);
glUniform2f(twoIndex, 0.25f, 0.125f);
drawQuad(program, "a_position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
}
// Test that using a centroid varying matrix array is supported.
TEST_P(GLSLTest_ES3, CentroidVaryingMatrixArray)
{
constexpr char kVS[] =
"#version 300 es\n"
"uniform vec2 u_a1;\n"
"uniform vec2 u_a2;\n"
"in vec4 a_position;\n"
"centroid out mat3x2 v_mat[2];\n"
"void main() {\n"
" v_mat[0] = mat3x2(u_a1, u_a2, vec2(0.0));\n"
" v_mat[1] = mat3x2(vec2(0.0), 1.0 - u_a2, 1.0 - u_a1);\n"
" gl_Position = a_position;\n"
"}";
constexpr char kFS[] =
"#version 300 es\n"
"precision mediump float;\n"
"centroid in mat3x2 v_mat[2];\n"
"layout(location = 0) out vec4 out_color;\n"
"void main(void)\n"
"{\n"
" out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][1].x, 1.0);\n"
"}";
ANGLE_GL_PROGRAM(program, kVS, kFS);
GLint oneIndex = glGetUniformLocation(program, "u_a1");
ASSERT_NE(-1, oneIndex);
GLint twoIndex = glGetUniformLocation(program, "u_a2");
ASSERT_NE(-1, twoIndex);
glUseProgram(program);
glUniform2f(oneIndex, 1, 0.5f);
glUniform2f(twoIndex, 0.25f, 0.125f);
drawQuad(program, "a_position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 255 - 63, 255), 1.0);
}
// Test that using a flat varying matrix array is supported.
TEST_P(GLSLTest_ES3, FlatVaryingMatrixArray)
{
constexpr char kVS[] =
"#version 300 es\n"
"uniform vec2 u_a1;\n"
"uniform vec2 u_a2;\n"
"in vec4 a_position;\n"
"flat out mat2 v_mat[2];\n"
"void main() {\n"
" v_mat[0] = mat2(u_a1, u_a2);\n"
" v_mat[1] = mat2(u_a2, u_a1);\n"
" gl_Position = a_position;\n"
"}";
constexpr char kFS[] =
"#version 300 es\n"
"precision mediump float;\n"
"flat in mat2 v_mat[2];\n"
"layout(location = 0) out vec4 out_color;\n"
"void main(void)\n"
"{\n"
" out_color = vec4(v_mat[0][0].x, v_mat[0][0].y, v_mat[1][0].x, 1.0);\n"
"}";
ANGLE_GL_PROGRAM(program, kVS, kFS);
GLint oneIndex = glGetUniformLocation(program, "u_a1");
ASSERT_NE(-1, oneIndex);
GLint twoIndex = glGetUniformLocation(program, "u_a2");
ASSERT_NE(-1, twoIndex);
glUseProgram(program);
glUniform2f(oneIndex, 1, 0.5f);
glUniform2f(twoIndex, 0.25f, 0.125f);
drawQuad(program, "a_position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 127, 63, 255), 1.0);
}
// Test that literal infinity can be written out from the shader translator. // Test that literal infinity can be written out from the shader translator.
// A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose. // A similar test can't be made for NaNs, since ESSL 3.00.6 requirements for NaNs are very loose.
TEST_P(GLSLTest_ES3, LiteralInfinityOutput) TEST_P(GLSLTest_ES3, LiteralInfinityOutput)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment