Commit fb2a871c by Geoff Lang Committed by Commit Bot

Work around VC++ 2017 compiler bug

A code-gen bug was found in 15.3.2 (VC++ 2017 Update 3.2) that causes test failures due to one loop being skipped. Attempts to disable optimizations for just the affected function failed so optimizations must be disabled at the end of the source file, which seems to cause all template functions and compiler generated functions to have optimizations disabled. A VS bug has been filed and cross-linked. BUG=759402 Change-Id: Ida765a47234a63bad48e6a4e910f3b82919d6be9 Reviewed-on: https://chromium-review.googlesource.com/647313Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent f00f7ffe
......@@ -229,7 +229,6 @@
'<(deqp_path)/modules/gles2/functional/es2fShaderInvarianceTests.hpp',
'<(deqp_path)/modules/gles2/functional/es2fShaderLoopTests.cpp',
'<(deqp_path)/modules/gles2/functional/es2fShaderLoopTests.hpp',
'<(deqp_path)/modules/gles2/functional/es2fShaderMatrixTests.cpp',
'<(deqp_path)/modules/gles2/functional/es2fShaderMatrixTests.hpp',
'<(deqp_path)/modules/gles2/functional/es2fShaderOperatorTests.cpp',
'<(deqp_path)/modules/gles2/functional/es2fShaderOperatorTests.hpp',
......@@ -324,6 +323,10 @@
'<(deqp_path)/modules/gles2/tes2TestPackage.cpp',
'<(deqp_path)/modules/gles2/tes2TestPackage.hpp',
'<(deqp_path)/modules/gles2/tes2TestPackageEntry.cpp',
# TODO(geofflang): Remove this once the test is updated in dEQP or the VC++2017
# compiler is fixed (crbug.com/759402)
#'<(deqp_path)/modules/gles2/functional/es2fShaderMatrixTests.cpp',
'<(angle_path)/src/tests/deqp_support/es2fShaderMatrixTests.cpp',
],
'deqp_gles3_sources':
[
......@@ -1629,6 +1632,12 @@
'deqp_support/tcuANGLEPlatform.cpp',
'deqp_support/tcuANGLEPlatform.h',
],
# TODO(geofflang): Remove once es2fShaderMatrixTests.cpp no longer requires
# a local copy (crbug.com/759402)
'include_dirs':
[
'<(deqp_path)/modules/gles2/functional',
],
},
{
......
/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 2.0 Module
* -------------------------------------------------
*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Shader matrix arithmetic tests.
*
* Variables:
* + operation
* - mat OP mat
* - mat OP vec
* - vec OP mat
* - mat OP scalar
* - OP mat
* + matrix source
* - constant (ctor)
* - uniform
* - vertex input
* - fragment input
* + other operand: always dynamic data?
* + how to reduce to vec3?
*//*--------------------------------------------------------------------*/
#include "es2fShaderMatrixTests.hpp"
#include "glsShaderRenderCase.hpp"
#include "gluShaderUtil.hpp"
#include "tcuVector.hpp"
#include "tcuMatrix.hpp"
#include "tcuMatrixUtil.hpp"
#include "deStringUtil.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
namespace deqp
{
namespace gles2
{
namespace Functional
{
using std::string;
using std::vector;
using namespace glu;
using namespace deqp::gls;
using tcu::Vec2;
using tcu::Vec3;
using tcu::Vec4;
using tcu::Mat2;
using tcu::Mat3;
using tcu::Mat4;
// Uniform / constant values for tests.
// \note Input1 should not contain 0 components as it is used as divisor in div cases.
// \todo [2012-02-14 pyry] Make these dynamic.
static const float s_constInFloat[2] = { 0.5f, -0.2f };
static const Vec2 s_constInVec2[2] = { Vec2(1.2f, 0.5f), Vec2(0.5f, 1.0f) };
static const Vec3 s_constInVec3[2] = { Vec3(1.1f, 0.1f, 0.5f), Vec3(-0.2f, 0.5f, 0.8f) };
static const Vec4 s_constInVec4[2] = { Vec4(1.4f, 0.2f, -0.5f, 0.7f), Vec4(0.2f, -1.0f, 0.5f, 0.8f) };
static const float s_constInMat20[] = { 0.6f, -1.0f, 0.7f, 0.4f };
static const float s_constInMat21[] = { -0.5f, -0.4f, 0.7f, -0.8f };
static const float s_constInMat31[] =
{
1.2f, 0.1f, -0.1f,
0.1f, 0.9f, 0.2f,
0.2f, -0.1f, 0.7f
};
static const float s_constInMat41[] =
{
1.2f, -0.2f, 0.4f, 0.1f,
0.1f, 0.8f, -0.1f, -0.2f,
-0.2f, 0.1f, -1.1f, 0.3f,
0.1f, 0.2f, 0.3f, 0.9f
};
static const Mat2 s_constInMat2[2] = { tcu::Mat2(s_constInMat20), tcu::Mat2(s_constInMat21) };
static const Mat3 s_constInMat3[2] = { tcu::translationMatrix(tcu::Vec2(0.2f, -0.3f)), tcu::Mat3(s_constInMat31) };
static const Mat4 s_constInMat4[2] = { tcu::translationMatrix(tcu::Vec3(0.2f, -0.3f, 0.15f)), tcu::Mat4(s_constInMat41) };
namespace MatrixCaseUtils
{
enum InputType
{
INPUTTYPE_CONST = 0,
INPUTTYPE_UNIFORM,
INPUTTYPE_DYNAMIC,
INPUTTYPE_LAST
};
struct ShaderInput
{
ShaderInput (InputType inputType_, DataType dataType_, Precision precision_)
: inputType (inputType_)
, dataType (dataType_)
, precision (precision_)
{
}
InputType inputType;
DataType dataType;
Precision precision;
};
enum MatrixOp
{
OP_ADD = 0,
OP_SUB,
OP_MUL,
OP_DIV,
OP_COMP_MUL,
OP_UNARY_PLUS,
OP_NEGATION,
OP_PRE_INCREMENT,
OP_PRE_DECREMENT,
OP_POST_INCREMENT,
OP_POST_DECREMENT,
OP_ADD_INTO,
OP_SUBTRACT_FROM,
OP_MULTIPLY_INTO,
OP_DIVIDE_INTO,
OP_LAST
};
// Type traits.
template <int DataT>
struct TypeTraits;
#define DECLARE_TYPE_TRAIT(DATATYPE, TYPE) \
template<> \
struct TypeTraits<DATATYPE> { \
typedef TYPE Type; \
}
DECLARE_TYPE_TRAIT(TYPE_FLOAT, float);
DECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC2, tcu::Vec2);
DECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC3, tcu::Vec3);
DECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC4, tcu::Vec4);
DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT2, tcu::Mat2);
DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT3, tcu::Mat3);
DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT4, tcu::Mat4);
// Operation info
enum OperationType
{
OPERATIONTYPE_BINARY_OPERATOR = 0,
OPERATIONTYPE_BINARY_FUNCTION,
OPERATIONTYPE_UNARY_PREFIX_OPERATOR,
OPERATIONTYPE_UNARY_POSTFIX_OPERATOR,
OPERATIONTYPE_ASSIGNMENT,
OPERATIONTYPE_LAST
};
static const char* getOperationName (MatrixOp op)
{
switch (op)
{
case OP_ADD: return "+";
case OP_SUB: return "-";
case OP_MUL: return "*";
case OP_DIV: return "/";
case OP_COMP_MUL: return "matrixCompMult";
case OP_UNARY_PLUS: return "+";
case OP_NEGATION: return "-";
case OP_PRE_INCREMENT: return "++";
case OP_PRE_DECREMENT: return "--";
case OP_POST_INCREMENT: return "++";
case OP_POST_DECREMENT: return "--";
case OP_ADD_INTO: return "+=";
case OP_SUBTRACT_FROM: return "-=";
case OP_MULTIPLY_INTO: return "*=";
case OP_DIVIDE_INTO: return "/=";
default:
DE_ASSERT(DE_FALSE);
return "";
}
}
static OperationType getOperationType (MatrixOp op)
{
switch (op)
{
case OP_ADD: return OPERATIONTYPE_BINARY_OPERATOR;
case OP_SUB: return OPERATIONTYPE_BINARY_OPERATOR;
case OP_MUL: return OPERATIONTYPE_BINARY_OPERATOR;
case OP_DIV: return OPERATIONTYPE_BINARY_OPERATOR;
case OP_COMP_MUL: return OPERATIONTYPE_BINARY_FUNCTION;
case OP_UNARY_PLUS: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
case OP_NEGATION: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
case OP_PRE_INCREMENT: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
case OP_PRE_DECREMENT: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
case OP_POST_INCREMENT: return OPERATIONTYPE_UNARY_POSTFIX_OPERATOR;
case OP_POST_DECREMENT: return OPERATIONTYPE_UNARY_POSTFIX_OPERATOR;
case OP_ADD_INTO: return OPERATIONTYPE_ASSIGNMENT;
case OP_SUBTRACT_FROM: return OPERATIONTYPE_ASSIGNMENT;
case OP_MULTIPLY_INTO: return OPERATIONTYPE_ASSIGNMENT;
case OP_DIVIDE_INTO: return OPERATIONTYPE_ASSIGNMENT;
default:
DE_ASSERT(DE_FALSE);
return OPERATIONTYPE_LAST;
}
}
enum TestMatrixType
{
TESTMATRIXTYPE_DEFAULT = 0,
TESTMATRIXTYPE_NEGATED,
TESTMATRIXTYPE_INCREMENTED,
TESTMATRIXTYPE_DECREMENTED,
TESTMATRIXTYPE_LAST
};
static TestMatrixType getOperationTestMatrixType (MatrixOp op)
{
switch(op)
{
case OP_ADD: return TESTMATRIXTYPE_DEFAULT;
case OP_SUB: return TESTMATRIXTYPE_DEFAULT;
case OP_MUL: return TESTMATRIXTYPE_DEFAULT;
case OP_DIV: return TESTMATRIXTYPE_DEFAULT;
case OP_COMP_MUL: return TESTMATRIXTYPE_DEFAULT;
case OP_UNARY_PLUS: return TESTMATRIXTYPE_DEFAULT;
case OP_NEGATION: return TESTMATRIXTYPE_NEGATED;
case OP_PRE_INCREMENT: return TESTMATRIXTYPE_NEGATED;
case OP_PRE_DECREMENT: return TESTMATRIXTYPE_INCREMENTED;
case OP_POST_INCREMENT: return TESTMATRIXTYPE_NEGATED;
case OP_POST_DECREMENT: return TESTMATRIXTYPE_DEFAULT;
case OP_ADD_INTO: return TESTMATRIXTYPE_DECREMENTED;
case OP_SUBTRACT_FROM: return TESTMATRIXTYPE_DEFAULT;
case OP_MULTIPLY_INTO: return TESTMATRIXTYPE_DEFAULT;
case OP_DIVIDE_INTO: return TESTMATRIXTYPE_DEFAULT;
default:
DE_ASSERT(DE_FALSE);
return TESTMATRIXTYPE_LAST;
}
}
static bool isOperationBinary (MatrixOp op)
{
return getOperationType(op) == OPERATIONTYPE_BINARY_OPERATOR ||
getOperationType(op) == OPERATIONTYPE_BINARY_FUNCTION ||
getOperationType(op) == OPERATIONTYPE_ASSIGNMENT;
}
static bool isOperationMatrixScalar (MatrixOp op)
{
return op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV;
}
static bool isOperationMatrixVector (MatrixOp op)
{
return op == OP_MUL;
}
static bool isOperationMatrixMatrix (MatrixOp op)
{
return op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV || op == OP_COMP_MUL;
}
static bool isOperationUnary (MatrixOp op)
{
return op == OP_UNARY_PLUS ||
op == OP_NEGATION ||
op == OP_PRE_INCREMENT ||
op == OP_PRE_DECREMENT ||
op == OP_POST_INCREMENT ||
op == OP_POST_DECREMENT;
}
static bool isOperationValueModifying (MatrixOp op)
{
return op == OP_PRE_INCREMENT ||
op == OP_PRE_DECREMENT ||
op == OP_POST_INCREMENT ||
op == OP_POST_DECREMENT;
}
static bool isOperationAssignment (MatrixOp op)
{
return op == OP_ADD_INTO ||
op == OP_SUBTRACT_FROM ||
op == OP_MULTIPLY_INTO ||
op == OP_DIVIDE_INTO;
}
// Operation nature
enum OperationNature
{
OPERATIONNATURE_PURE = 0,
OPERATIONNATURE_MUTATING,
OPERATIONNATURE_ASSIGNMENT,
OPERATIONNATURE_LAST
};
static OperationNature getOperationNature (MatrixOp op)
{
if (isOperationAssignment(op))
return OPERATIONNATURE_ASSIGNMENT;
if (isOperationValueModifying(op))
return OPERATIONNATURE_MUTATING;
return OPERATIONNATURE_PURE;
}
// Input value loader.
template <int InputT, int DataT>
typename TypeTraits<DataT>::Type getInputValue (const ShaderEvalContext& evalCtx, int inputNdx);
template <> inline float getInputValue<INPUTTYPE_CONST, TYPE_FLOAT> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInFloat[inputNdx]; }
template <> inline tcu::Vec2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_VEC2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec2[inputNdx]; }
template <> inline tcu::Vec3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_VEC3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec3[inputNdx]; }
template <> inline tcu::Vec4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_VEC4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec4[inputNdx]; }
template <> inline tcu::Mat2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInMat2[inputNdx]; }
template <> inline tcu::Mat3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInMat3[inputNdx]; }
template <> inline tcu::Mat4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInMat4[inputNdx]; }
template <> inline float getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.x(); }
template <> inline tcu::Vec2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_VEC2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.swizzle(0, 1); }
template <> inline tcu::Vec3 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_VEC3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.swizzle(0, 1, 2); }
template <> inline tcu::Vec4 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_VEC4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.swizzle(0, 1, 2, 3); }
template <> inline tcu::Mat2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT2> (const ShaderEvalContext& evalCtx, int inputNdx)
{
DE_UNREF(inputNdx); // Not used.
tcu::Mat2 m;
m.setColumn(0, evalCtx.in[0].swizzle(0,1));
m.setColumn(1, evalCtx.in[1].swizzle(0,1));
return m;
}
template <> inline tcu::Mat3 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT3> (const ShaderEvalContext& evalCtx, int inputNdx)
{
DE_UNREF(inputNdx); // Not used.
tcu::Mat3 m;
m.setColumn(0, evalCtx.in[0].swizzle(0,1,2));
m.setColumn(1, evalCtx.in[1].swizzle(0,1,2));
m.setColumn(2, evalCtx.in[2].swizzle(0,1,2));
return m;
}
template <> inline tcu::Mat4 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT4> (const ShaderEvalContext& evalCtx, int inputNdx)
{
DE_UNREF(inputNdx); // Not used.
tcu::Mat4 m;
m.setColumn(0, evalCtx.in[0]);
m.setColumn(1, evalCtx.in[1]);
m.setColumn(2, evalCtx.in[2]);
m.setColumn(3, evalCtx.in[3]);
return m;
}
// Reduction from expression result to vec3.
inline tcu::Vec3 reduceToVec3 (const tcu::Vec2& value) { return value.swizzle(0,1,0); }
inline tcu::Vec3 reduceToVec3 (const tcu::Vec3& value) { return value; }
inline tcu::Vec3 reduceToVec3 (const tcu::Vec4& value) { return tcu::Vec3(value.x(), value.y(), value.z()+value.w()); }
inline tcu::Vec3 reduceToVec3 (const tcu::Mat2& value) { return tcu::Vec3(value(0, 0), value(0, 1), value(1, 0)+value(1, 1)); }
inline tcu::Vec3 reduceToVec3 (const tcu::Mat3& value) { return value.getColumn(0) + value.getColumn(1) + value.getColumn(2); }
inline tcu::Vec3 reduceToVec3 (const tcu::Mat4& value) { return value.getColumn(0).swizzle(0,1,2) + value.getColumn(1).swizzle(1,2,3) + value.getColumn(2).swizzle(2,3,0) + value.getColumn(3).swizzle(3,0,1); }
// matrixCompMult
template <typename T, int Rows, int Cols>
tcu::Matrix<T, Rows, Cols> matrixCompMult (const tcu::Matrix<T, Rows, Cols>& a, const tcu::Matrix<T, Rows, Cols>& b)
{
tcu::Matrix<T, Rows, Cols> retVal;
for (int r = 0; r < Rows; ++r)
for (int c = 0; c < Cols; ++c)
retVal(r,c) = a(r,c) * b(r, c);
return retVal;
}
// negate
template <typename T, int Rows, int Cols>
tcu::Matrix<T, Rows, Cols> negate (const tcu::Matrix<T, Rows, Cols>& mat)
{
tcu::Matrix<T, Rows, Cols> retVal;
for (int r = 0; r < Rows; ++r)
for (int c = 0; c < Cols; ++c)
retVal(r,c) = -mat(r, c);
return retVal;
}
// increment/decrement
template <typename T, int Rows, int Cols>
tcu::Matrix<T, Rows, Cols> increment (const tcu::Matrix<T, Rows, Cols>& mat)
{
tcu::Matrix<T, Rows, Cols> retVal;
for (int r = 0; r < Rows; ++r)
for (int c = 0; c < Cols; ++c)
retVal(r,c) = mat(r, c) + 1.0f;
return retVal;
}
template <typename T, int Rows, int Cols>
tcu::Matrix<T, Rows, Cols> decrement (const tcu::Matrix<T, Rows, Cols>& mat)
{
tcu::Matrix<T, Rows, Cols> retVal;
for (int r = 0; r < Rows; ++r)
for (int c = 0; c < Cols; ++c)
retVal(r,c) = mat(r, c) - 1.0f;
return retVal;
}
// Evaluator template.
template <int Op, int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator;
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_ADD, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) + getInputValue<In1Type, In1DataType>(evalCtx, 1));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_SUB, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) - getInputValue<In1Type, In1DataType>(evalCtx, 1));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_MUL, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) * getInputValue<In1Type, In1DataType>(evalCtx, 1));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_DIV, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) / getInputValue<In1Type, In1DataType>(evalCtx, 1));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_COMP_MUL, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(matrixCompMult(getInputValue<In0Type, In0DataType>(evalCtx, 0), getInputValue<In1Type, In1DataType>(evalCtx, 1)));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_UNARY_PLUS, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_NEGATION, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(negate(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_PRE_INCREMENT, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
// modifying reduction: sum modified value too
evalCtx.color.xyz() = reduceToVec3(increment(getInputValue<In0Type, In0DataType>(evalCtx, 0))) + reduceToVec3(increment(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_PRE_DECREMENT, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
// modifying reduction: sum modified value too
evalCtx.color.xyz() = reduceToVec3(decrement(getInputValue<In0Type, In0DataType>(evalCtx, 0))) + reduceToVec3(decrement(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_POST_INCREMENT, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
// modifying reduction: sum modified value too
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0)) + reduceToVec3(increment(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_POST_DECREMENT, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
// modifying reduction: sum modified value too
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0)) + reduceToVec3(decrement(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_ADD_INTO, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) + getInputValue<In1Type, In1DataType>(evalCtx, 1));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_SUBTRACT_FROM, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) - getInputValue<In1Type, In1DataType>(evalCtx, 1));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_MULTIPLY_INTO, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) * getInputValue<In1Type, In1DataType>(evalCtx, 1));
}
};
template <int In0Type, int In0DataType, int In1Type, int In1DataType>
struct Evaluator<OP_DIVIDE_INTO, In0Type, In0DataType, In1Type, In1DataType>
{
static void evaluate (ShaderEvalContext& evalCtx)
{
evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) / getInputValue<In1Type, In1DataType>(evalCtx, 1));
}
};
ShaderEvalFunc getEvalFunc (const ShaderInput& in0, const ShaderInput& in1, MatrixOp op)
{
DE_STATIC_ASSERT(TYPE_LAST <= (1<<7));
DE_STATIC_ASSERT(OP_LAST <= (1<<4));
DE_STATIC_ASSERT(INPUTTYPE_LAST <= (1<<2));
#define PACK_EVAL_CASE(OP, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE) (((OP) << 18) | ((IN0TYPE) << 16) | ((IN0DATATYPE) << 9) | ((IN1TYPE) << 7) | (IN1DATATYPE))
#define MAKE_EVAL_CASE(OP, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE) \
case PACK_EVAL_CASE(OP, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE): \
return Evaluator<OP, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE>::evaluate
#define SCALAR_OPS(IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE) \
MAKE_EVAL_CASE(OP_ADD, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_SUB, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_MUL, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_DIV, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)
#define ALL_OPS(IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE) \
MAKE_EVAL_CASE(OP_ADD, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_SUB, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_MUL, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_DIV, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_COMP_MUL, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);
#define MUL_OP(IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE) \
MAKE_EVAL_CASE(OP_MUL, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)
#define MAKE_MAT_SCALAR_VEC_CASES(OP, TYPE0, TYPE1) \
OP(INPUTTYPE_CONST, TYPE0, INPUTTYPE_CONST, TYPE1); \
OP(INPUTTYPE_DYNAMIC, TYPE0, INPUTTYPE_CONST, TYPE1); \
OP(INPUTTYPE_CONST, TYPE0, INPUTTYPE_DYNAMIC, TYPE1); \
OP(INPUTTYPE_DYNAMIC, TYPE0, INPUTTYPE_DYNAMIC, TYPE1)
#define MAKE_MAT_MAT_CASES(OP, MATTYPE) \
OP(INPUTTYPE_CONST, MATTYPE, INPUTTYPE_CONST, MATTYPE); \
OP(INPUTTYPE_DYNAMIC, MATTYPE, INPUTTYPE_CONST, MATTYPE)
#define UNARY_OP(IN0TYPE, IN0DATATYPE) \
MAKE_EVAL_CASE(OP_UNARY_PLUS, IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST); \
MAKE_EVAL_CASE(OP_NEGATION, IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST); \
MAKE_EVAL_CASE(OP_PRE_INCREMENT, IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST); \
MAKE_EVAL_CASE(OP_PRE_DECREMENT, IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST); \
MAKE_EVAL_CASE(OP_POST_INCREMENT, IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST); \
MAKE_EVAL_CASE(OP_POST_DECREMENT, IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST)
#define MAKE_UNARY_CASES(OP, MATTYPE) \
OP(INPUTTYPE_CONST, MATTYPE); \
OP(INPUTTYPE_DYNAMIC, MATTYPE)
#define ASSIGN_OP(IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE) \
MAKE_EVAL_CASE(OP_ADD_INTO, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_SUBTRACT_FROM, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_MULTIPLY_INTO, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE); \
MAKE_EVAL_CASE(OP_DIVIDE_INTO, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)
#define MAKE_ASSIGNMENT_CASES(OP, MATTYPE) \
OP(INPUTTYPE_CONST, MATTYPE, INPUTTYPE_CONST, MATTYPE); \
OP(INPUTTYPE_DYNAMIC, MATTYPE, INPUTTYPE_CONST, MATTYPE); \
OP(INPUTTYPE_CONST, MATTYPE, INPUTTYPE_DYNAMIC, MATTYPE); \
OP(INPUTTYPE_DYNAMIC, MATTYPE, INPUTTYPE_DYNAMIC, MATTYPE)
// \note At the moment there is no difference between uniform and const inputs. This saves binary size.
InputType in0Type = in0.inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_DYNAMIC : INPUTTYPE_CONST;
InputType in1Type = in1.inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_DYNAMIC : INPUTTYPE_CONST;
switch (PACK_EVAL_CASE(op, in0Type, in0.dataType, in1Type, in1.dataType))
{
// Matrix-scalar.
MAKE_MAT_SCALAR_VEC_CASES(SCALAR_OPS, TYPE_FLOAT_MAT2, TYPE_FLOAT);
MAKE_MAT_SCALAR_VEC_CASES(SCALAR_OPS, TYPE_FLOAT_MAT3, TYPE_FLOAT);
MAKE_MAT_SCALAR_VEC_CASES(SCALAR_OPS, TYPE_FLOAT_MAT4, TYPE_FLOAT);
// Matrix-vector.
MAKE_MAT_SCALAR_VEC_CASES(MUL_OP, TYPE_FLOAT_MAT2, TYPE_FLOAT_VEC2);
MAKE_MAT_SCALAR_VEC_CASES(MUL_OP, TYPE_FLOAT_MAT3, TYPE_FLOAT_VEC3);
MAKE_MAT_SCALAR_VEC_CASES(MUL_OP, TYPE_FLOAT_MAT4, TYPE_FLOAT_VEC4);
// Vector-matrix.
MAKE_MAT_SCALAR_VEC_CASES(MUL_OP, TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT2);
MAKE_MAT_SCALAR_VEC_CASES(MUL_OP, TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT3);
MAKE_MAT_SCALAR_VEC_CASES(MUL_OP, TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT4);
// Matrix-matrix.
MAKE_MAT_MAT_CASES(ALL_OPS, TYPE_FLOAT_MAT2);
MAKE_MAT_MAT_CASES(ALL_OPS, TYPE_FLOAT_MAT3);
MAKE_MAT_MAT_CASES(ALL_OPS, TYPE_FLOAT_MAT4);
// Unary matrix
MAKE_UNARY_CASES(UNARY_OP, TYPE_FLOAT_MAT2);
MAKE_UNARY_CASES(UNARY_OP, TYPE_FLOAT_MAT3);
MAKE_UNARY_CASES(UNARY_OP, TYPE_FLOAT_MAT4);
// Assignment matrix
MAKE_ASSIGNMENT_CASES(ASSIGN_OP, TYPE_FLOAT_MAT2);
MAKE_ASSIGNMENT_CASES(ASSIGN_OP, TYPE_FLOAT_MAT3);
MAKE_ASSIGNMENT_CASES(ASSIGN_OP, TYPE_FLOAT_MAT4);
default:
DE_ASSERT(DE_FALSE);
return DE_NULL;
}
#undef PACK_EVAL_CASE
#undef MAKE_EVAL_CASE
#undef MUL_OP
#undef ALL_OPS
#undef MAKE_MAT_SCALAR_VEC_CASES
#undef MAKE_MAT_MAT_CASES
}
// Shader source format utilities.
template <int Size>
void writeVectorConstructor (std::ostream& str, const tcu::Vector<float, Size>& v)
{
str << "vec" << Size << "(";
for (int ndx = 0; ndx < Size; ndx++)
{
if (ndx != 0)
str << ", ";
str << de::floatToString(v[ndx], 1);
}
str << ")";
}
template <int Cols, int Rows>
void writeMatrixConstructor (std::ostream& str, const tcu::Matrix<float, Rows, Cols>& m)
{
if (Rows == Cols)
str << "mat" << Cols;
else
str << "mat" << Cols << "x" << Rows;
str << "(";
for (int colNdx = 0; colNdx < Cols; colNdx++)
{
for (int rowNdx = 0; rowNdx < Rows; rowNdx++)
{
if (rowNdx > 0 || colNdx > 0)
str << ", ";
str << de::floatToString(m(rowNdx, colNdx), 1);
}
}
str << ")";
}
} // MatrixCaseUtils
using namespace MatrixCaseUtils;
class ShaderMatrixCase : public ShaderRenderCase
{
public:
ShaderMatrixCase (Context& context, const char* name, const char* desc, const ShaderInput& in0, const ShaderInput& in1, MatrixOp op, bool isVertexCase);
~ShaderMatrixCase (void);
void init (void);
protected:
std::string genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName);
void setupUniforms (int programID, const tcu::Vec4& constCoords);
private:
ShaderInput m_in0;
ShaderInput m_in1;
MatrixOp m_op;
};
ShaderMatrixCase::ShaderMatrixCase (Context& context, const char* name, const char* desc, const ShaderInput& in0, const ShaderInput& in1, MatrixOp op, bool isVertexCase)
: ShaderRenderCase (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, getEvalFunc(in0, in1, op))
, m_in0 (in0)
, m_in1 (in1)
, m_op (op)
{
}
ShaderMatrixCase::~ShaderMatrixCase (void)
{
}
void ShaderMatrixCase::init (void)
{
std::ostringstream vtx;
std::ostringstream frag;
std::ostringstream& op = m_isVertexCase ? vtx : frag;
bool isInDynMat0 = isDataTypeMatrix(m_in0.dataType) && m_in0.inputType == INPUTTYPE_DYNAMIC;
bool isInDynMat1 = isDataTypeMatrix(m_in1.dataType) && m_in1.inputType == INPUTTYPE_DYNAMIC;
string inValue0;
string inValue1;
DataType resultType = TYPE_LAST;
Precision resultPrec = m_in0.precision;
vector<string> passVars;
int numInputs = (isOperationBinary(m_op)) ? (2) : (1);
std::string operationValue0;
std::string operationValue1;
DE_ASSERT(!isInDynMat0 || !isInDynMat1); // Only single dynamic matrix input is allowed.
DE_UNREF(isInDynMat0 && isInDynMat1);
// Compute result type.
if (isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
{
DE_ASSERT(m_in0.dataType == m_in1.dataType);
resultType = m_in0.dataType;
}
else if (getOperationType(m_op) == OPERATIONTYPE_UNARY_PREFIX_OPERATOR ||
getOperationType(m_op) == OPERATIONTYPE_UNARY_POSTFIX_OPERATOR)
{
resultType = m_in0.dataType;
}
else
{
int matNdx = isDataTypeMatrix(m_in0.dataType) ? 0 : 1;
DataType matrixType = matNdx == 0 ? m_in0.dataType : m_in1.dataType;
DataType otherType = matNdx == 0 ? m_in1.dataType : m_in0.dataType;
if (otherType == TYPE_FLOAT)
resultType = matrixType;
else
{
DE_ASSERT(isDataTypeVector(otherType));
resultType = otherType;
}
}
vtx << "attribute highp vec4 a_position;\n";
if (m_isVertexCase)
{
vtx << "varying mediump vec4 v_color;\n";
frag << "varying mediump vec4 v_color;\n";
}
// Input declarations.
for (int inNdx = 0; inNdx < numInputs; inNdx++)
{
const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
const char* precName = getPrecisionName(in.precision);
const char* typeName = getDataTypeName(in.dataType);
string& inValue = inNdx > 0 ? inValue1 : inValue0;
if (in.inputType == INPUTTYPE_DYNAMIC)
{
vtx << "attribute " << precName << " " << typeName << " a_";
if (isDataTypeMatrix(in.dataType))
{
// a_matN, v_matN
vtx << typeName << ";\n";
if (!m_isVertexCase)
{
vtx << "varying " << precName << " " << typeName << " v_" << typeName << ";\n";
frag << "varying " << precName << " " << typeName << " v_" << typeName << ";\n";
passVars.push_back(typeName);
}
inValue = string(m_isVertexCase ? "a_" : "v_") + getDataTypeName(in.dataType);
}
else
{
// a_coords, v_coords
vtx << "coords;\n";
if (!m_isVertexCase)
{
vtx << "varying " << precName << " " << typeName << " v_coords;\n";
frag << "varying " << precName << " " << typeName << " v_coords;\n";
passVars.push_back("coords");
}
inValue = m_isVertexCase ? "a_coords" : "v_coords";
}
}
else if (in.inputType == INPUTTYPE_UNIFORM)
{
op << "uniform " << precName << " " << typeName << " u_in" << inNdx << ";\n";
inValue = string("u_in") + de::toString(inNdx);
}
else if (in.inputType == INPUTTYPE_CONST)
{
op << "const " << precName << " " << typeName << " in" << inNdx << " = ";
// Generate declaration.
switch (in.dataType)
{
case TYPE_FLOAT: op << de::floatToString(s_constInFloat[inNdx], 1); break;
case TYPE_FLOAT_VEC2: writeVectorConstructor<2>(op, s_constInVec2[inNdx]); break;
case TYPE_FLOAT_VEC3: writeVectorConstructor<3>(op, s_constInVec3[inNdx]); break;
case TYPE_FLOAT_VEC4: writeVectorConstructor<4>(op, s_constInVec4[inNdx]); break;
case TYPE_FLOAT_MAT2: writeMatrixConstructor<2, 2>(op, Mat2(s_constInMat2[inNdx])); break;
case TYPE_FLOAT_MAT3: writeMatrixConstructor<3, 3>(op, Mat3(s_constInMat3[inNdx])); break;
case TYPE_FLOAT_MAT4: writeMatrixConstructor<4, 4>(op, Mat4(s_constInMat4[inNdx])); break;
default:
DE_ASSERT(DE_FALSE);
}
op << ";\n";
inValue = string("in") + de::toString(inNdx);
}
}
vtx << "\n"
<< "void main (void)\n"
<< "{\n"
<< " gl_Position = a_position;\n";
frag << "\n"
<< "void main (void)\n"
<< "{\n";
if (m_isVertexCase)
{
frag << " gl_FragColor = v_color;\n";
}
else
{
for (vector<string>::const_iterator copyIter = passVars.begin(); copyIter != passVars.end(); copyIter++)
vtx << " v_" << *copyIter << " = " << "a_" << *copyIter << ";\n";
}
// Operation.
switch (getOperationNature(m_op))
{
case OPERATIONNATURE_PURE:
DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
operationValue0 = inValue0;
operationValue1 = inValue1;
break;
case OPERATIONNATURE_MUTATING:
DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " tmpValue = " << inValue0 << ";\n";
operationValue0 = "tmpValue";
operationValue1 = inValue1;
break;
case OPERATIONNATURE_ASSIGNMENT:
DE_ASSERT(getOperationType(m_op) == OPERATIONTYPE_ASSIGNMENT);
operationValue0 = inValue0;
operationValue1 = inValue1;
break;
default:
DE_ASSERT(DE_FALSE);
}
switch (getOperationType(m_op))
{
case OPERATIONTYPE_BINARY_OPERATOR:
op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << " " << getOperationName(m_op) << " " << operationValue1 << ";\n";
break;
case OPERATIONTYPE_UNARY_PREFIX_OPERATOR:
op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << operationValue0 << ";\n";
break;
case OPERATIONTYPE_UNARY_POSTFIX_OPERATOR:
op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << getOperationName(m_op) << ";\n";
break;
case OPERATIONTYPE_BINARY_FUNCTION:
op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ", " << operationValue1 << ");\n";
break;
case OPERATIONTYPE_ASSIGNMENT:
op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << ";\n";
op << " res " << getOperationName(m_op) << " " << operationValue1 << ";\n";
break;
default:
DE_ASSERT(DE_FALSE);
}
// Reduction to vec3 (rgb). Check the used value too if it was modified.
op << " " << (m_isVertexCase ? "v_color" : "gl_FragColor") << " = ";
if (isOperationValueModifying(m_op))
op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0) + vec4(" << genGLSLMatToVec3Reduction(resultType, "tmpValue") << ", 0.0);\n";
else
op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0);\n";
vtx << "}\n";
frag << "}\n";
m_vertShaderSource = vtx.str();
m_fragShaderSource = frag.str();
// \todo [2012-02-14 pyry] Compute better values for matrix tests.
m_userAttribTransforms.resize(4);
for (int attribNdx = 0; attribNdx < 4; attribNdx++)
{
m_userAttribTransforms[attribNdx] = Mat4(0.0f);
m_userAttribTransforms[attribNdx]((0 + attribNdx) % 4, 0) = 1.0f;
m_userAttribTransforms[attribNdx]((1 + attribNdx) % 4, 1) = 1.0f;
m_userAttribTransforms[attribNdx]((2 + attribNdx) % 4, 2) = 1.0f;
m_userAttribTransforms[attribNdx]((3 + attribNdx) % 4, 3) = 1.0f;
}
// prevent bad reference cases such as black result images by fine-tuning used matrices
if (getOperationTestMatrixType(m_op) != TESTMATRIXTYPE_DEFAULT)
{
for (int attribNdx = 0; attribNdx < 4; attribNdx++)
{
for (int row = 0; row < 4; row++)
for (int col = 0; col < 4; col++)
{
switch (getOperationTestMatrixType(m_op))
{
case TESTMATRIXTYPE_NEGATED:
m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col);
break;
case TESTMATRIXTYPE_INCREMENTED:
m_userAttribTransforms[attribNdx](row, col) += 0.3f;
break;
case TESTMATRIXTYPE_DECREMENTED:
m_userAttribTransforms[attribNdx](row, col) -= 0.1f;
break;
default:
DE_ASSERT(DE_FALSE);
break;
}
}
}
}
ShaderRenderCase::init();
}
std::string ShaderMatrixCase::genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName)
{
std::ostringstream op;
switch (matType)
{
case TYPE_FLOAT: op << varName << ", " << varName << ", " << varName << ""; break;
case TYPE_FLOAT_VEC2: op << varName << ".x, " << varName << ".y, " << varName << ".x"; break;
case TYPE_FLOAT_VEC3: op << varName << ""; break;
case TYPE_FLOAT_VEC4: op << varName << ".x, " << varName << ".y, " << varName << ".z+" << varName << ".w"; break;
case TYPE_FLOAT_MAT2: op << varName << "[0][0], " << varName << "[1][0], " << varName << "[0][1]+" << varName << "[1][1]"; break;
case TYPE_FLOAT_MAT3: op << varName << "[0]+" << varName << "[1]+" << varName << "[2]"; break;
case TYPE_FLOAT_MAT4: op << varName << "[0].xyz+" << varName << "[1].yzw+" << varName << "[2].zwx+" << varName << "[3].wxy"; break;
default:
DE_ASSERT(DE_FALSE);
}
return op.str();
}
void ShaderMatrixCase::setupUniforms (int programID, const tcu::Vec4& constCoords)
{
const glw::Functions& gl = m_renderCtx.getFunctions();
DE_UNREF(constCoords);
for (int inNdx = 0; inNdx < 2; inNdx++)
{
const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
if (in.inputType == INPUTTYPE_UNIFORM)
{
int loc = gl.getUniformLocation(programID, (string("u_in") + de::toString(inNdx)).c_str());
if (loc < 0)
continue;
switch (in.dataType)
{
case TYPE_FLOAT: gl.uniform1f(loc, s_constInFloat[inNdx]); break;
case TYPE_FLOAT_VEC2: gl.uniform2fv(loc, 1, s_constInVec2[inNdx].getPtr()); break;
case TYPE_FLOAT_VEC3: gl.uniform3fv(loc, 1, s_constInVec3[inNdx].getPtr()); break;
case TYPE_FLOAT_VEC4: gl.uniform4fv(loc, 1, s_constInVec4[inNdx].getPtr()); break;
case TYPE_FLOAT_MAT2: gl.uniformMatrix2fv(loc, 1, GL_FALSE, s_constInMat2[inNdx].getColumnMajorData().getPtr()); break;
case TYPE_FLOAT_MAT3: gl.uniformMatrix3fv(loc, 1, GL_FALSE, s_constInMat3[inNdx].getColumnMajorData().getPtr()); break;
case TYPE_FLOAT_MAT4: gl.uniformMatrix4fv(loc, 1, GL_FALSE, s_constInMat4[inNdx].getColumnMajorData().getPtr()); break;
default:
DE_ASSERT(false);
}
}
}
}
ShaderMatrixTests::ShaderMatrixTests (Context& context)
: TestCaseGroup(context, "matrix", "Matrix Tests")
{
}
ShaderMatrixTests::~ShaderMatrixTests (void)
{
}
void ShaderMatrixTests::init (void)
{
static const struct
{
const char* name;
const char* desc;
MatrixOp op;
bool extendedInputTypeCases; // !< test with const and uniform types too
} ops[] =
{
{ "add", "Matrix addition tests", OP_ADD, true },
{ "sub", "Matrix subtraction tests", OP_SUB, true },
{ "mul", "Matrix multiplication tests", OP_MUL, true },
{ "div", "Matrix division tests", OP_DIV, true },
{ "matrixcompmult", "Matrix component-wise multiplication tests", OP_COMP_MUL, false },
{ "unary_addition", "Matrix unary addition tests", OP_UNARY_PLUS, false },
{ "negation", "Matrix negation tests", OP_NEGATION, false },
{ "pre_increment", "Matrix prefix increment tests", OP_PRE_INCREMENT, false },
{ "pre_decrement", "Matrix prefix decrement tests", OP_PRE_DECREMENT, false },
{ "post_increment", "Matrix postfix increment tests", OP_POST_INCREMENT, false },
{ "post_decrement", "Matrix postfix decrement tests", OP_POST_DECREMENT, false },
{ "add_assign", "Matrix add into tests", OP_ADD_INTO, false },
{ "sub_assign", "Matrix subtract from tests", OP_SUBTRACT_FROM, false },
{ "mul_assign", "Matrix multiply into tests", OP_MULTIPLY_INTO, false },
{ "div_assign", "Matrix divide into tests", OP_DIVIDE_INTO, false },
};
struct InputTypeSpec
{
const char* name;
const char* desc;
InputType type;
};
static const InputTypeSpec extendedInputTypes[] =
{
{ "const", "Constant matrix input", INPUTTYPE_CONST },
{ "uniform", "Uniform matrix input", INPUTTYPE_UNIFORM },
{ "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC }
};
static const InputTypeSpec reducedInputTypes[] =
{
{ "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC }
};
static const DataType matrixTypes[] =
{
TYPE_FLOAT_MAT2,
TYPE_FLOAT_MAT3,
TYPE_FLOAT_MAT4
};
static const Precision precisions[] =
{
PRECISION_LOWP,
PRECISION_MEDIUMP,
PRECISION_HIGHP
};
for (int opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
{
const InputTypeSpec* inTypeList = (ops[opNdx].extendedInputTypeCases) ? (extendedInputTypes) : (reducedInputTypes);
const int inTypeListSize = (ops[opNdx].extendedInputTypeCases) ? (DE_LENGTH_OF_ARRAY(extendedInputTypes)) : (DE_LENGTH_OF_ARRAY(reducedInputTypes));
const MatrixOp op = ops[opNdx].op;
tcu::TestCaseGroup* opGroup = new tcu::TestCaseGroup(m_testCtx, ops[opNdx].name, ops[opNdx].desc);
addChild(opGroup);
for (int inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++)
{
const InputType inputType = inTypeList[inTypeNdx].type;
for (int matTypeNdx = 0; matTypeNdx < DE_LENGTH_OF_ARRAY(matrixTypes); matTypeNdx++)
{
DataType matType = matrixTypes[matTypeNdx];
const char* matTypeName = getDataTypeName(matType);
for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
{
Precision precision = precisions[precNdx];
const char* precName = getPrecisionName(precision);
string baseName = string(inTypeList[inTypeNdx].name) + "_" + precName + "_" + matTypeName + "_";
ShaderInput matIn (inputType, matType, precision);
if (isOperationMatrixScalar(op))
{
// Matrix-scalar \note For div cases we use uniform input.
ShaderInput scalarIn(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, TYPE_FLOAT, precision);
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(), "Matrix-scalar case", matIn, scalarIn, op, true));
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(), "Matrix-scalar case", matIn, scalarIn, op, false));
}
if (isOperationMatrixVector(op))
{
// Matrix-vector.
DataType vecType = getDataTypeFloatVec(getDataTypeMatrixNumColumns(matType));
ShaderInput vecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, vecType, precision);
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(vecType) + "_vertex").c_str(), "Matrix-vector case", matIn, vecIn, op, true));
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(vecType) + "_fragment").c_str(), "Matrix-vector case", matIn, vecIn, op, false));
// Vector-matrix.
string vecMatName = string(inTypeList[inTypeNdx].name) + "_" + precName + "_" + getDataTypeName(vecType) + "_" + matTypeName;
opGroup->addChild(new ShaderMatrixCase(m_context, (vecMatName + "_vertex").c_str(), "Vector-matrix case", vecIn, matIn, op, true));
opGroup->addChild(new ShaderMatrixCase(m_context, (vecMatName + "_fragment").c_str(), "Vector-matrix case", vecIn, matIn, op, false));
}
if (isOperationMatrixMatrix(op))
{
// Matrix-matrix.
ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + matTypeName + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true));
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + matTypeName + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false));
}
if (isOperationUnary(op))
{
// op matrix
ShaderInput voidInput(INPUTTYPE_LAST, TYPE_LAST, PRECISION_LAST);
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "vertex").c_str(), "Matrix case", matIn, voidInput, op, true));
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "fragment").c_str(), "Matrix case", matIn, voidInput, op, false));
}
if (isOperationAssignment(op))
{
ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "vertex").c_str(), "Matrix assignment case", matIn, otherMatIn, op, true));
opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "fragment").c_str(), "Matrix assignment case", matIn, otherMatIn, op, false));
}
}
}
}
}
}
} // Functional
} // gles2
} // deqp
#if defined(_MSC_VER) && _MSC_FULL_VER == 191125507
// Work around crbug.com/759402 which is a code-gen bug in VC++ 2015, version
// 15.3.2.
#pragma optimize("", off)
#endif
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