1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2016 The Android Open Source Project
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 * \brief Shader matrix arithmetic tests.
39 *//*--------------------------------------------------------------------*/
41 #include "vktShaderRenderMatrixTests.hpp"
43 #include "vktShaderRender.hpp"
44 #include "tcuVector.hpp"
45 #include "tcuMatrix.hpp"
46 #include "tcuMatrixUtil.hpp"
47 #include "deStringUtil.hpp"
73 // Uniform / constant values for tests.
74 // \note Input1 should not contain 0 components as it is used as divisor in div cases.
75 static const float s_constInFloat[2] = { 0.5f, -0.2f };
76 static const Vec2 s_constInVec2[2] = { Vec2(1.2f, 0.5f), Vec2(0.5f, 1.0f) };
77 static const Vec3 s_constInVec3[2] = { Vec3(1.1f, 0.1f, 0.5f), Vec3(-0.2f, 0.5f, 0.8f) };
78 static const Vec4 s_constInVec4[2] = { Vec4(1.4f, 0.2f, -0.5f, 0.7f), Vec4(0.2f, -1.0f, 0.5f, 0.8f) };
80 static const float s_constInMat2x2[2][4] =
91 static const float s_constInMat3x2[2][6] =
102 static const float s_constInMat4x2[2][8] =
105 -0.2f, 0.5f, 0.0f, -1.0f,
106 1.2f, -0.5f, 0.3f, -0.9f,
109 1.0f, 0.1f, -1.1f, 0.6f,
110 0.8f, -1.2f, -1.1f, 0.7f,
113 static const float s_constInMat2x3[2][6] =
126 static const float s_constInMat3x3[2][9] =
139 static const float s_constInMat4x3[2][12] =
142 -0.9f, 0.0f, 0.6f, 0.2f,
143 0.9f, -0.1f, -0.3f, -0.7f,
144 -0.1f, 0.1f, 1.0f, 0.0f,
147 0.5f, 0.7f, 0.7f, 1.2f,
148 1.1f, 0.1f, 1.0f, -1.0f,
149 -0.2f, -0.2f, -0.3f, -0.5f,
152 static const float s_constInMat2x4[2][8] =
167 static const float s_constInMat3x4[2][12] =
182 static const float s_constInMat4x4[2][16] =
185 0.3f, 0.9f, -0.2f, 1.0f,
186 -0.4f, -0.6f, 0.6f, -1.0f,
187 -0.9f, -0.1f, 0.3f, -0.2f,
188 -0.3f, -0.9f, 1.0f, 0.1f,
191 0.4f, -0.7f, -0.8f, 0.7f,
192 -0.4f, -0.8f, 0.6f, -0.3f,
193 0.7f, -1.0f, 0.1f, -0.3f,
194 0.2f, 0.6f, 0.4f, -1.0f,
198 namespace MatrixCaseUtils
212 ShaderInput (InputType inputType_, DataType dataType_, Precision precision_)
213 : inputType (inputType_)
214 , dataType (dataType_)
215 , precision (precision_)
253 #define DECLARE_TYPE_TRAIT(DATATYPE, TYPE) \
255 struct TypeTraits<DATATYPE> { \
259 DECLARE_TYPE_TRAIT(TYPE_FLOAT, float);
260 DECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC2, tcu::Vec2);
261 DECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC3, tcu::Vec3);
262 DECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC4, tcu::Vec4);
263 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT2, tcu::Mat2);
264 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT2X3, tcu::Mat2x3);
265 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT2X4, tcu::Mat2x4);
266 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT3X2, tcu::Mat3x2);
267 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT3, tcu::Mat3);
268 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT3X4, tcu::Mat3x4);
269 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT4X2, tcu::Mat4x2);
270 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT4X3, tcu::Mat4x3);
271 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT4, tcu::Mat4);
277 OPERATIONTYPE_BINARY_OPERATOR = 0,
278 OPERATIONTYPE_BINARY_FUNCTION,
279 OPERATIONTYPE_UNARY_PREFIX_OPERATOR,
280 OPERATIONTYPE_UNARY_POSTFIX_OPERATOR,
281 OPERATIONTYPE_UNARY_FUNCTION,
282 OPERATIONTYPE_ASSIGNMENT,
287 static const char* getOperationName (MatrixOp op)
291 case OP_ADD: return "+";
292 case OP_SUB: return "-";
293 case OP_MUL: return "*";
294 case OP_DIV: return "/";
295 case OP_COMP_MUL: return "matrixCompMult";
296 case OP_OUTER_PRODUCT: return "outerProduct";
297 case OP_TRANSPOSE: return "transpose";
298 case OP_INVERSE: return "inverse";
299 case OP_DETERMINANT: return "determinant";
300 case OP_UNARY_PLUS: return "+";
301 case OP_NEGATION: return "-";
302 case OP_PRE_INCREMENT: return "++";
303 case OP_PRE_DECREMENT: return "--";
304 case OP_POST_INCREMENT: return "++";
305 case OP_POST_DECREMENT: return "--";
306 case OP_ADD_INTO: return "+=";
307 case OP_SUBTRACT_FROM: return "-=";
308 case OP_MULTIPLY_INTO: return "*=";
309 case OP_DIVIDE_INTO: return "/=";
317 static OperationType getOperationType (MatrixOp op)
321 case OP_ADD: return OPERATIONTYPE_BINARY_OPERATOR;
322 case OP_SUB: return OPERATIONTYPE_BINARY_OPERATOR;
323 case OP_MUL: return OPERATIONTYPE_BINARY_OPERATOR;
324 case OP_DIV: return OPERATIONTYPE_BINARY_OPERATOR;
325 case OP_COMP_MUL: return OPERATIONTYPE_BINARY_FUNCTION;
326 case OP_OUTER_PRODUCT: return OPERATIONTYPE_BINARY_FUNCTION;
327 case OP_TRANSPOSE: return OPERATIONTYPE_UNARY_FUNCTION;
328 case OP_INVERSE: return OPERATIONTYPE_UNARY_FUNCTION;
329 case OP_DETERMINANT: return OPERATIONTYPE_UNARY_FUNCTION;
330 case OP_UNARY_PLUS: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
331 case OP_NEGATION: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
332 case OP_PRE_INCREMENT: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
333 case OP_PRE_DECREMENT: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
334 case OP_POST_INCREMENT: return OPERATIONTYPE_UNARY_POSTFIX_OPERATOR;
335 case OP_POST_DECREMENT: return OPERATIONTYPE_UNARY_POSTFIX_OPERATOR;
336 case OP_ADD_INTO: return OPERATIONTYPE_ASSIGNMENT;
337 case OP_SUBTRACT_FROM: return OPERATIONTYPE_ASSIGNMENT;
338 case OP_MULTIPLY_INTO: return OPERATIONTYPE_ASSIGNMENT;
339 case OP_DIVIDE_INTO: return OPERATIONTYPE_ASSIGNMENT;
342 return OPERATIONTYPE_LAST;
348 TESTMATRIXTYPE_DEFAULT = 0,
349 TESTMATRIXTYPE_NEGATED,
350 TESTMATRIXTYPE_INCREMENTED,
351 TESTMATRIXTYPE_DECREMENTED,
352 TESTMATRIXTYPE_NEGATED_INCREMENTED,
353 TESTMATRIXTYPE_INCREMENTED_LESS,
358 static TestMatrixType getOperationTestMatrixType (MatrixOp op)
362 case OP_ADD: return TESTMATRIXTYPE_DEFAULT;
363 case OP_SUB: return TESTMATRIXTYPE_DEFAULT;
364 case OP_MUL: return TESTMATRIXTYPE_DEFAULT;
365 case OP_DIV: return TESTMATRIXTYPE_DEFAULT;
366 case OP_COMP_MUL: return TESTMATRIXTYPE_DEFAULT;
367 case OP_OUTER_PRODUCT: return TESTMATRIXTYPE_DEFAULT;
368 case OP_TRANSPOSE: return TESTMATRIXTYPE_DEFAULT;
369 case OP_INVERSE: return TESTMATRIXTYPE_DEFAULT;
370 case OP_DETERMINANT: return TESTMATRIXTYPE_DEFAULT;
371 case OP_UNARY_PLUS: return TESTMATRIXTYPE_DECREMENTED;
372 case OP_NEGATION: return TESTMATRIXTYPE_NEGATED_INCREMENTED;
373 case OP_PRE_INCREMENT: return TESTMATRIXTYPE_NEGATED;
374 case OP_PRE_DECREMENT: return TESTMATRIXTYPE_INCREMENTED;
375 case OP_POST_INCREMENT: return TESTMATRIXTYPE_NEGATED;
376 case OP_POST_DECREMENT: return TESTMATRIXTYPE_DEFAULT;
377 case OP_ADD_INTO: return TESTMATRIXTYPE_DEFAULT;
378 case OP_SUBTRACT_FROM: return TESTMATRIXTYPE_INCREMENTED_LESS;
379 case OP_MULTIPLY_INTO: return TESTMATRIXTYPE_NEGATED;
380 case OP_DIVIDE_INTO: return TESTMATRIXTYPE_DECREMENTED;
384 return TESTMATRIXTYPE_LAST;
388 static bool isOperationBinary (MatrixOp op)
390 return getOperationType(op) == OPERATIONTYPE_BINARY_OPERATOR ||
391 getOperationType(op) == OPERATIONTYPE_BINARY_FUNCTION ||
392 getOperationType(op) == OPERATIONTYPE_ASSIGNMENT;
395 static bool isOperationMatrixScalar (MatrixOp op)
397 return op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV;
400 static bool isOperationMatrixVector (MatrixOp op)
405 static bool isOperationArithmeticMatrixMatrix (MatrixOp op)
410 static bool isOperationComponentwiseMatrixMatrix (MatrixOp op)
412 return op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV || op == OP_COMP_MUL;
415 static bool isOperationVectorVector (MatrixOp op)
417 return op == OP_OUTER_PRODUCT;
420 static bool isOperationUnaryAnyMatrix (MatrixOp op)
422 return op == OP_TRANSPOSE ||
423 op == OP_UNARY_PLUS ||
425 op == OP_PRE_INCREMENT ||
426 op == OP_PRE_DECREMENT ||
427 op == OP_POST_INCREMENT ||
428 op == OP_POST_DECREMENT;
431 static bool isOperationUnarySymmetricMatrix (MatrixOp op)
433 return op == OP_INVERSE || op == OP_DETERMINANT;
436 static bool isOperationValueModifying (MatrixOp op)
438 return op == OP_PRE_INCREMENT ||
439 op == OP_PRE_DECREMENT ||
440 op == OP_POST_INCREMENT ||
441 op == OP_POST_DECREMENT;
444 static bool isOperationAssignment (MatrixOp op)
446 return op == OP_ADD_INTO ||
447 op == OP_SUBTRACT_FROM ||
448 op == OP_MULTIPLY_INTO ||
449 op == OP_DIVIDE_INTO;
452 static bool isOperationAssignmentAnyMatrix (MatrixOp op)
454 return op == OP_ADD_INTO ||
455 op == OP_SUBTRACT_FROM ||
456 op == OP_DIVIDE_INTO;
459 static bool isOperationAssignmentSymmetricMatrix (MatrixOp op)
461 return op == OP_MULTIPLY_INTO;
468 OPERATIONNATURE_PURE = 0,
469 OPERATIONNATURE_MUTATING,
470 OPERATIONNATURE_ASSIGNMENT,
475 static OperationNature getOperationNature (MatrixOp op)
477 if (isOperationAssignment(op))
478 return OPERATIONNATURE_ASSIGNMENT;
480 if (isOperationValueModifying(op))
481 return OPERATIONNATURE_MUTATING;
483 return OPERATIONNATURE_PURE;
486 // Input value loader.
488 template <int InputT, int DataT>
489 typename TypeTraits<DataT>::Type getInputValue (const ShaderEvalContext& evalCtx, int inputNdx);
491 template <> inline float getInputValue<INPUTTYPE_CONST, TYPE_FLOAT> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInFloat[inputNdx]; }
492 template <> inline tcu::Vec2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_VEC2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec2[inputNdx]; }
493 template <> inline tcu::Vec3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_VEC3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec3[inputNdx]; }
494 template <> inline tcu::Vec4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_VEC4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec4[inputNdx]; }
496 template <> inline tcu::Mat2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat2(s_constInMat2x2[inputNdx]); }
497 template <> inline tcu::Mat2x3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT2X3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat2x3(s_constInMat2x3[inputNdx]); }
498 template <> inline tcu::Mat2x4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT2X4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat2x4(s_constInMat2x4[inputNdx]); }
499 template <> inline tcu::Mat3x2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT3X2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat3x2(s_constInMat3x2[inputNdx]); }
500 template <> inline tcu::Mat3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat3(s_constInMat3x3[inputNdx]); }
501 template <> inline tcu::Mat3x4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT3X4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat3x4(s_constInMat3x4[inputNdx]); }
502 template <> inline tcu::Mat4x2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT4X2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat4x2(s_constInMat4x2[inputNdx]); }
503 template <> inline tcu::Mat4x3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT4X3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat4x3(s_constInMat4x3[inputNdx]); }
504 template <> inline tcu::Mat4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat4(s_constInMat4x4[inputNdx]); }
506 template <> inline float getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.x(); }
507 template <> inline tcu::Vec2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_VEC2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.swizzle(0, 1); }
508 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); }
509 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); }
511 template <> inline tcu::Mat2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT2> (const ShaderEvalContext& evalCtx, int inputNdx)
513 DE_UNREF(inputNdx); // Not used.
515 m.setColumn(0, evalCtx.in[0].swizzle(0,1));
516 m.setColumn(1, evalCtx.in[1].swizzle(0,1));
520 template <> inline tcu::Mat2x3 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT2X3> (const ShaderEvalContext& evalCtx, int inputNdx)
522 DE_UNREF(inputNdx); // Not used.
524 m.setColumn(0, evalCtx.in[0].swizzle(0,1,2));
525 m.setColumn(1, evalCtx.in[1].swizzle(0,1,2));
529 template <> inline tcu::Mat2x4 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT2X4> (const ShaderEvalContext& evalCtx, int inputNdx)
531 DE_UNREF(inputNdx); // Not used.
533 m.setColumn(0, evalCtx.in[0]);
534 m.setColumn(1, evalCtx.in[1]);
538 template <> inline tcu::Mat3x2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT3X2> (const ShaderEvalContext& evalCtx, int inputNdx)
540 DE_UNREF(inputNdx); // Not used.
542 m.setColumn(0, evalCtx.in[0].swizzle(0,1));
543 m.setColumn(1, evalCtx.in[1].swizzle(0,1));
544 m.setColumn(2, evalCtx.in[2].swizzle(0,1));
548 template <> inline tcu::Mat3 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT3> (const ShaderEvalContext& evalCtx, int inputNdx)
550 DE_UNREF(inputNdx); // Not used.
552 m.setColumn(0, evalCtx.in[0].swizzle(0,1,2));
553 m.setColumn(1, evalCtx.in[1].swizzle(0,1,2));
554 m.setColumn(2, evalCtx.in[2].swizzle(0,1,2));
558 template <> inline tcu::Mat3x4 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT3X4> (const ShaderEvalContext& evalCtx, int inputNdx)
560 DE_UNREF(inputNdx); // Not used.
562 m.setColumn(0, evalCtx.in[0]);
563 m.setColumn(1, evalCtx.in[1]);
564 m.setColumn(2, evalCtx.in[2]);
568 template <> inline tcu::Mat4x2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT4X2> (const ShaderEvalContext& evalCtx, int inputNdx)
570 DE_UNREF(inputNdx); // Not used.
572 m.setColumn(0, evalCtx.in[0].swizzle(0,1));
573 m.setColumn(1, evalCtx.in[1].swizzle(0,1));
574 m.setColumn(2, evalCtx.in[2].swizzle(0,1));
575 m.setColumn(3, evalCtx.in[3].swizzle(0,1));
579 template <> inline tcu::Mat4x3 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT4X3> (const ShaderEvalContext& evalCtx, int inputNdx)
581 DE_UNREF(inputNdx); // Not used.
583 m.setColumn(0, evalCtx.in[0].swizzle(0,1,2));
584 m.setColumn(1, evalCtx.in[1].swizzle(0,1,2));
585 m.setColumn(2, evalCtx.in[2].swizzle(0,1,2));
586 m.setColumn(3, evalCtx.in[3].swizzle(0,1,2));
590 template <> inline tcu::Mat4 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT4> (const ShaderEvalContext& evalCtx, int inputNdx)
592 DE_UNREF(inputNdx); // Not used.
594 m.setColumn(0, evalCtx.in[0]);
595 m.setColumn(1, evalCtx.in[1]);
596 m.setColumn(2, evalCtx.in[2]);
597 m.setColumn(3, evalCtx.in[3]);
601 // Reduction from expression result to vec3.
603 inline tcu::Vec3 reduceToVec3 (const tcu::Vec2& value) { return value.swizzle(0,1,0); }
604 inline tcu::Vec3 reduceToVec3 (const tcu::Vec3& value) { return value; }
605 inline tcu::Vec3 reduceToVec3 (const tcu::Vec4& value) { return tcu::Vec3(value.x(), value.y(), value.z()+value.w()); }
606 inline tcu::Vec3 reduceToVec3 (const tcu::Mat2& value) { return tcu::Vec3(value(0, 0), value(0, 1), value(1, 0)+value(1, 1)); }
607 inline tcu::Vec3 reduceToVec3 (const tcu::Mat2x3& value) { return value.getColumn(0) + value.getColumn(1); }
608 inline tcu::Vec3 reduceToVec3 (const tcu::Mat2x4& value) { return value.getColumn(0).swizzle(0,1,2) + value.getColumn(1).swizzle(1,2,3); }
609 inline tcu::Vec3 reduceToVec3 (const tcu::Mat3x2& value) { return tcu::Vec3(value(0,0)+value(1,0), value(0,1)+value(1,1), value(0,2)+value(1,2)); }
610 inline tcu::Vec3 reduceToVec3 (const tcu::Mat3& value) { return value.getColumn(0) + value.getColumn(1) + value.getColumn(2); }
611 inline tcu::Vec3 reduceToVec3 (const tcu::Mat3x4& value) { return value.getColumn(0).swizzle(0,1,2) + value.getColumn(1).swizzle(1,2,3) + value.getColumn(2).swizzle(2,3,0); }
612 inline tcu::Vec3 reduceToVec3 (const tcu::Mat4x2& value) { return tcu::Vec3(value(0,0)+value(1,0)+value(0,3), value(0,1)+value(1,1)+value(1,3), value(0,2)+value(1,2)); }
613 inline tcu::Vec3 reduceToVec3 (const tcu::Mat4x3& value) { return value.getColumn(0) + value.getColumn(1) + value.getColumn(2) + value.getColumn(3); }
614 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); }
618 template <typename T, int Rows, int Cols>
619 tcu::Matrix<T, Rows, Cols> matrixCompMult (const tcu::Matrix<T, Rows, Cols>& a, const tcu::Matrix<T, Rows, Cols>& b)
621 tcu::Matrix<T, Rows, Cols> retVal;
623 for (int r = 0; r < Rows; ++r)
624 for (int c = 0; c < Cols; ++c)
625 retVal(r,c) = a(r,c) * b(r, c);
632 template <typename T, int Rows, int Cols>
633 tcu::Matrix<T, Cols, Rows> transpose (const tcu::Matrix<T, Rows, Cols>& mat)
635 tcu::Matrix<T, Cols, Rows> retVal;
637 for (int r = 0; r < Rows; ++r)
638 for (int c = 0; c < Cols; ++c)
639 retVal(c, r) = mat(r, c);
646 template <typename T, int Rows, int Cols>
647 tcu::Matrix<T, Cols, Rows> outerProduct (const tcu::Vector<T, Cols>& a, const tcu::Vector<T, Rows>& b)
649 tcu::Matrix<T, Rows, Cols> retVal;
651 for (int r = 0; r < Rows; ++r)
652 for (int c = 0; c < Cols; ++c)
653 retVal(r,c) = a[c] * b[r];
655 return transpose(retVal); // to gl-form (column-major)
661 float determinant (const tcu::Matrix<float, Size, Size>& mat);
664 float determinant<2> (const tcu::Matrix<float, 2, 2>& mat)
666 return mat(0,0) * mat(1,1) - mat(1,0) * mat(0,1);
670 float determinant<3> (const tcu::Matrix<float, 3, 3>& mat)
672 return + mat(0,0) * mat(1,1) * mat(2,2)
673 + mat(0,1) * mat(1,2) * mat(2,0)
674 + mat(0,2) * mat(1,0) * mat(2,1)
675 - mat(0,0) * mat(1,2) * mat(2,1)
676 - mat(0,1) * mat(1,0) * mat(2,2)
677 - mat(0,2) * mat(1,1) * mat(2,0);
681 float determinant<4> (const tcu::Matrix<float, 4, 4>& mat)
683 const float minorMatrices[4][3*3] =
686 mat(1,1), mat(2,1), mat(3,1),
687 mat(1,2), mat(2,2), mat(3,2),
688 mat(1,3), mat(2,3), mat(3,3),
691 mat(1,0), mat(2,0), mat(3,0),
692 mat(1,2), mat(2,2), mat(3,2),
693 mat(1,3), mat(2,3), mat(3,3),
696 mat(1,0), mat(2,0), mat(3,0),
697 mat(1,1), mat(2,1), mat(3,1),
698 mat(1,3), mat(2,3), mat(3,3),
701 mat(1,0), mat(2,0), mat(3,0),
702 mat(1,1), mat(2,1), mat(3,1),
703 mat(1,2), mat(2,2), mat(3,2),
707 return + mat(0,0) * determinant(tcu::Mat3(minorMatrices[0]))
708 - mat(0,1) * determinant(tcu::Mat3(minorMatrices[1]))
709 + mat(0,2) * determinant(tcu::Mat3(minorMatrices[2]))
710 - mat(0,3) * determinant(tcu::Mat3(minorMatrices[3]));
716 tcu::Matrix<float, Size, Size> inverse (const tcu::Matrix<float, Size, Size>& mat);
719 tcu::Matrix<float, 2, 2> inverse<2> (const tcu::Matrix<float, 2, 2>& mat)
721 const float det = determinant(mat);
722 tcu::Matrix<float, 2, 2> retVal;
724 DE_ASSERT(det != 0.0f);
726 retVal(0, 0) = mat(1, 1) / det;
727 retVal(0, 1) = -mat(0, 1) / det;
728 retVal(1, 0) = -mat(1, 0) / det;
729 retVal(1, 1) = mat(0, 0) / det;
735 tcu::Matrix<float, 3, 3> inverse<3> (const tcu::Matrix<float, 3, 3>& mat)
737 // Blockwise inversion
739 DE_ASSERT(determinant(mat) != 0.0f);
741 const float areaA[2*2] =
746 const float areaB[2] =
751 const float areaC[2] =
755 const float areaD[1] =
759 const float nullField[4] = { 0.0f };
761 const tcu::Matrix<float, 2, 2> invA = inverse(tcu::Matrix<float, 2, 2>(areaA));
762 const tcu::Matrix<float, 2, 1> matB = tcu::Matrix<float, 2, 1>(areaB);
763 const tcu::Matrix<float, 1, 2> matC = tcu::Matrix<float, 1, 2>(areaC);
764 const tcu::Matrix<float, 1, 1> matD = tcu::Matrix<float, 1, 1>(areaD);
766 const float schurComplement = 1.0f / (matD - matC*invA*matB)(0,0);
767 const tcu::Matrix<float, 2, 2> zeroMat = Mat2(nullField);
769 const tcu::Matrix<float, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA;
770 const tcu::Matrix<float, 2, 1> blockB = (zeroMat-invA)*matB*schurComplement;
771 const tcu::Matrix<float, 1, 2> blockC = matC*invA*(-schurComplement);
772 const float blockD = schurComplement;
774 const float result[3*3] =
776 blockA(0,0), blockA(0,1), blockB(0,0),
777 blockA(1,0), blockA(1,1), blockB(1,0),
778 blockC(0,0), blockC(0,1), blockD,
785 tcu::Matrix<float, 4, 4> inverse<4> (const tcu::Matrix<float, 4, 4>& mat)
787 // Blockwise inversion
789 DE_ASSERT(determinant(mat) != 0.0f);
791 const float areaA[2*2] =
796 const float areaB[2*2] =
801 const float areaC[2*2] =
806 const float areaD[2*2] =
811 const float nullField[4] = { 0.0f };
813 const tcu::Matrix<float, 2, 2> invA = inverse(Mat2(areaA));
814 const tcu::Matrix<float, 2, 2> matB = Mat2(areaB);
815 const tcu::Matrix<float, 2, 2> matC = Mat2(areaC);
816 const tcu::Matrix<float, 2, 2> matD = Mat2(areaD);
818 const tcu::Matrix<float, 2, 2> schurComplement = inverse(matD - matC*invA*matB);
819 const tcu::Matrix<float, 2, 2> zeroMat = Mat2(nullField);
821 const tcu::Matrix<float, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA;
822 const tcu::Matrix<float, 2, 2> blockB = (zeroMat-invA)*matB*schurComplement;
823 const tcu::Matrix<float, 2, 2> blockC = (zeroMat-schurComplement)*matC*invA;
824 const tcu::Matrix<float, 2, 2> blockD = schurComplement;
826 const float result[4*4] =
828 blockA(0,0), blockA(0,1), blockB(0,0), blockB(0,1),
829 blockA(1,0), blockA(1,1), blockB(1,0), blockB(1,1),
830 blockC(0,0), blockC(0,1), blockD(0,0), blockD(0,1),
831 blockC(1,0), blockC(1,1), blockD(1,0), blockD(1,1),
839 template <typename T, int Rows, int Cols>
840 tcu::Matrix<T, Rows, Cols> negate (const tcu::Matrix<T, Rows, Cols>& mat)
842 tcu::Matrix<T, Rows, Cols> retVal;
844 for (int r = 0; r < Rows; ++r)
845 for (int c = 0; c < Cols; ++c)
846 retVal(r,c) = -mat(r, c);
851 // increment/decrement
853 template <typename T, int Rows, int Cols>
854 tcu::Matrix<T, Rows, Cols> increment (const tcu::Matrix<T, Rows, Cols>& mat)
856 tcu::Matrix<T, Rows, Cols> retVal;
858 for (int r = 0; r < Rows; ++r)
859 for (int c = 0; c < Cols; ++c)
860 retVal(r,c) = mat(r, c) + 1.0f;
865 template <typename T, int Rows, int Cols>
866 tcu::Matrix<T, Rows, Cols> decrement (const tcu::Matrix<T, Rows, Cols>& mat)
868 tcu::Matrix<T, Rows, Cols> retVal;
870 for (int r = 0; r < Rows; ++r)
871 for (int c = 0; c < Cols; ++c)
872 retVal(r,c) = mat(r, c) - 1.0f;
877 // Evaluator template.
879 typedef void (*MatrixShaderEvalFunc) (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type);
881 template <int Op, int In0DataType, int In1DataType>
884 template <int In0DataType, int In1DataType>
885 struct Evaluator<OP_ADD, In0DataType, In1DataType>
887 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
889 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
890 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
891 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
892 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
893 evalCtx.color.xyz() = reduceToVec3(in0 + in1);
897 template <int In0DataType, int In1DataType>
898 struct Evaluator<OP_SUB, In0DataType, In1DataType>
900 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
902 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
903 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
904 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
905 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
906 evalCtx.color.xyz() = reduceToVec3(in0 - in1);
910 template <int In0DataType, int In1DataType>
911 struct Evaluator<OP_MUL, In0DataType, In1DataType>
913 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
915 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
916 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
917 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
918 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
919 evalCtx.color.xyz() = reduceToVec3(in0 * in1);
923 template <int In0DataType, int In1DataType>
924 struct Evaluator<OP_DIV, In0DataType, In1DataType>
926 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
928 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
929 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
930 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
931 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
932 evalCtx.color.xyz() = reduceToVec3(in0 / in1);
936 template <int In0DataType, int In1DataType>
937 struct Evaluator<OP_COMP_MUL, In0DataType, In1DataType>
939 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
941 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
942 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
943 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
944 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
945 evalCtx.color.xyz() = reduceToVec3(matrixCompMult(in0, in1));
949 template <int In0DataType, int In1DataType>
950 struct Evaluator<OP_OUTER_PRODUCT, In0DataType, In1DataType>
952 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
954 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
955 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
956 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
957 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
958 evalCtx.color.xyz() = reduceToVec3(outerProduct(in0, in1));
962 template <int In0DataType, int In1DataType>
963 struct Evaluator<OP_TRANSPOSE, In0DataType, In1DataType>
965 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
968 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
969 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
970 evalCtx.color.xyz() = reduceToVec3(transpose(in0));
974 template <int In0DataType, int In1DataType>
975 struct Evaluator<OP_INVERSE, In0DataType, In1DataType>
977 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
980 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
981 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
982 evalCtx.color.xyz() = reduceToVec3(inverse(in0));
986 template <int In0DataType, int In1DataType>
987 struct Evaluator<OP_DETERMINANT, In0DataType, In1DataType>
989 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
992 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
993 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
994 evalCtx.color.xyz() = Vec3(determinant(in0));
998 template <int In0DataType, int In1DataType>
999 struct Evaluator<OP_UNARY_PLUS, In0DataType, In1DataType>
1001 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1004 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1005 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1006 evalCtx.color.xyz() = reduceToVec3(in0);
1010 template <int In0DataType, int In1DataType>
1011 struct Evaluator<OP_NEGATION, In0DataType, In1DataType>
1013 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1016 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1017 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1018 evalCtx.color.xyz() = reduceToVec3(negate(in0));
1022 template <int In0DataType, int In1DataType>
1023 struct Evaluator<OP_PRE_INCREMENT, In0DataType, In1DataType>
1025 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1028 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1029 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1031 // modifying reduction: sum modified value too
1032 evalCtx.color.xyz() = reduceToVec3(increment(in0)) + reduceToVec3(increment(in0));
1036 template <int In0DataType, int In1DataType>
1037 struct Evaluator<OP_PRE_DECREMENT, In0DataType, In1DataType>
1039 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1042 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1043 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1045 // modifying reduction: sum modified value too
1046 evalCtx.color.xyz() = reduceToVec3(decrement(in0)) + reduceToVec3(decrement(in0));
1050 template <int In0DataType, int In1DataType>
1051 struct Evaluator<OP_POST_INCREMENT, In0DataType, In1DataType>
1053 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1056 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1057 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1059 // modifying reduction: sum modified value too
1060 evalCtx.color.xyz() = reduceToVec3(in0) + reduceToVec3(increment(in0));
1064 template <int In0DataType, int In1DataType>
1065 struct Evaluator<OP_POST_DECREMENT, In0DataType, In1DataType>
1067 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1070 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1071 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1073 // modifying reduction: sum modified value too
1074 evalCtx.color.xyz() = reduceToVec3(in0) + reduceToVec3(decrement(in0));
1078 template <int In0DataType, int In1DataType>
1079 struct Evaluator<OP_ADD_INTO, In0DataType, In1DataType>
1081 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1083 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1084 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1085 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1086 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
1087 evalCtx.color.xyz() = reduceToVec3(in0 + in1);
1091 template <int In0DataType, int In1DataType>
1092 struct Evaluator<OP_SUBTRACT_FROM, In0DataType, In1DataType>
1094 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1096 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1097 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1098 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1099 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
1100 evalCtx.color.xyz() = reduceToVec3(in0 - in1);
1104 template <int In0DataType, int In1DataType>
1105 struct Evaluator<OP_MULTIPLY_INTO, In0DataType, In1DataType>
1107 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1109 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1110 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1111 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1112 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
1113 evalCtx.color.xyz() = reduceToVec3(in0 * in1);
1117 template <int In0DataType, int In1DataType>
1118 struct Evaluator<OP_DIVIDE_INTO, In0DataType, In1DataType>
1120 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1122 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1123 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1124 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1125 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
1126 evalCtx.color.xyz() = reduceToVec3(in0 / in1);
1130 MatrixShaderEvalFunc getEvalFunc (const ShaderInput& in0, const ShaderInput& in1, MatrixOp op)
1132 // Evaluator is selected based on op and input data types.
1133 // For efficient lookup the types and op enums are packed together to form a 19-bit key:
1134 // [18..14 OP] [13..7 TYPE0] [6..0 TYPE1]
1136 DE_STATIC_ASSERT(TYPE_LAST <= (1<<7));
1137 DE_STATIC_ASSERT(OP_LAST <= (1<<5));
1139 #define PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE) (((OP) << 14) | ((IN0DATATYPE) << 7) | (IN1DATATYPE))
1141 #define MAKE_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE) \
1142 case PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE): \
1143 return Evaluator<OP, IN0DATATYPE, IN1DATATYPE>::evaluate
1145 #define MAKE_SCALAR_OPS(IN0DATATYPE, IN1DATATYPE) \
1146 MAKE_EVAL_CASE(OP_ADD, IN0DATATYPE, IN1DATATYPE); \
1147 MAKE_EVAL_CASE(OP_SUB, IN0DATATYPE, IN1DATATYPE); \
1148 MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE); \
1149 MAKE_EVAL_CASE(OP_DIV, IN0DATATYPE, IN1DATATYPE)
1151 #define MAKE_CWISE_OPS(IN0DATATYPE, IN1DATATYPE) \
1152 MAKE_EVAL_CASE(OP_ADD, IN0DATATYPE, IN1DATATYPE); \
1153 MAKE_EVAL_CASE(OP_SUB, IN0DATATYPE, IN1DATATYPE); \
1154 MAKE_EVAL_CASE(OP_DIV, IN0DATATYPE, IN1DATATYPE); \
1155 MAKE_EVAL_CASE(OP_COMP_MUL, IN0DATATYPE, IN1DATATYPE)
1157 #define MAKE_MUL_OP(IN0DATATYPE, IN1DATATYPE) \
1158 MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE)
1160 #define MAKE_VECVEC_OP(IN0DATATYPE, IN1DATATYPE) \
1161 MAKE_EVAL_CASE(OP_OUTER_PRODUCT, IN0DATATYPE, IN1DATATYPE)
1163 #define MAKE_UNARY_OP(IN0DATATYPE) \
1164 MAKE_EVAL_CASE(OP_TRANSPOSE, IN0DATATYPE, TYPE_LAST); \
1165 MAKE_EVAL_CASE(OP_UNARY_PLUS, IN0DATATYPE, TYPE_LAST); \
1166 MAKE_EVAL_CASE(OP_NEGATION, IN0DATATYPE, TYPE_LAST); \
1167 MAKE_EVAL_CASE(OP_PRE_INCREMENT, IN0DATATYPE, TYPE_LAST); \
1168 MAKE_EVAL_CASE(OP_PRE_DECREMENT, IN0DATATYPE, TYPE_LAST); \
1169 MAKE_EVAL_CASE(OP_POST_INCREMENT, IN0DATATYPE, TYPE_LAST); \
1170 MAKE_EVAL_CASE(OP_POST_DECREMENT, IN0DATATYPE, TYPE_LAST)
1172 #define MAKE_UNARY_SYMMETRIC_OP(IN0DATATYPE) \
1173 MAKE_UNARY_OP(IN0DATATYPE); \
1174 MAKE_EVAL_CASE(OP_DETERMINANT, IN0DATATYPE, TYPE_LAST); \
1175 MAKE_EVAL_CASE(OP_INVERSE, IN0DATATYPE, TYPE_LAST)
1177 #define MAKE_ASSIGNMENT_OP(IN0DATATYPE) \
1178 MAKE_EVAL_CASE(OP_ADD_INTO, IN0DATATYPE, IN0DATATYPE); \
1179 MAKE_EVAL_CASE(OP_SUBTRACT_FROM, IN0DATATYPE, IN0DATATYPE); \
1180 MAKE_EVAL_CASE(OP_DIVIDE_INTO, IN0DATATYPE, IN0DATATYPE)
1182 #define MAKE_ASSIGNMENT_SYMMETRIC_OP(IN0DATATYPE) \
1183 MAKE_ASSIGNMENT_OP(IN0DATATYPE); \
1184 MAKE_EVAL_CASE(OP_MULTIPLY_INTO, IN0DATATYPE, IN0DATATYPE)
1186 switch (PACK_EVAL_CASE(op, in0.dataType, in1.dataType))
1189 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2, TYPE_FLOAT);
1190 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X3, TYPE_FLOAT);
1191 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X4, TYPE_FLOAT);
1192 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X2, TYPE_FLOAT);
1193 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3, TYPE_FLOAT);
1194 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X4, TYPE_FLOAT);
1195 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X2, TYPE_FLOAT);
1196 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X3, TYPE_FLOAT);
1197 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4, TYPE_FLOAT);
1200 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_VEC2);
1201 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_VEC2);
1202 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_VEC2);
1203 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_VEC3);
1204 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_VEC3);
1205 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_VEC3);
1206 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_VEC4);
1207 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_VEC4);
1208 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_VEC4);
1211 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT2);
1212 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT2X3);
1213 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT2X4);
1214 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT3X2);
1215 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT3);
1216 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT3X4);
1217 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT4X2);
1218 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT4X3);
1219 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT4);
1222 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT2);
1223 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT2);
1224 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT3X2);
1225 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT4X2);
1227 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2X3);
1228 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2);
1229 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT3X2);
1230 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT4X2);
1232 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT2X4);
1233 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT2);
1234 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT3X2);
1235 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT4X2);
1237 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3X2);
1238 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT2X3);
1239 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3);
1240 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT4X3);
1242 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT3);
1243 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT2X3);
1244 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT3);
1245 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT4X3);
1247 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT3X4);
1248 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT2X3);
1249 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT3);
1250 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT4X3);
1252 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4X2);
1253 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT2X4);
1254 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT3X4);
1255 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4);
1257 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4X3);
1258 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT2X4);
1259 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT3X4);
1260 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4);
1262 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT4);
1263 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT2X4);
1264 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT3X4);
1265 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT4);
1268 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC2);
1269 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3);
1270 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC4);
1271 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC2);
1272 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC3);
1273 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4);
1274 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC2);
1275 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC3);
1276 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4);
1279 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT2);
1280 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X3);
1281 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X4);
1282 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X2);
1283 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT3);
1284 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X4);
1285 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X2);
1286 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X3);
1287 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT4);
1290 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT2);
1291 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X3);
1292 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X4);
1293 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X2);
1294 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT3);
1295 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X4);
1296 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X2);
1297 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X3);
1298 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT4);
1301 DE_ASSERT(DE_FALSE);
1305 #undef PACK_EVAL_CASE
1306 #undef MAKE_EVAL_CASE
1309 #undef MAKE_MAT_SCALAR_VEC_CASES
1310 #undef MAKE_MAT_MAT_CASES
1313 // Shader source format utilities.
1316 void writeVectorConstructor (std::ostream& str, const tcu::Vector<float, Size>& v)
1318 str << "vec" << Size << "(";
1319 for (int ndx = 0; ndx < Size; ndx++)
1323 str << de::floatToString(v[ndx], 1);
1328 template <int Cols, int Rows>
1329 void writeMatrixConstructor (std::ostream& str, const tcu::Matrix<float, Rows, Cols>& m)
1332 str << "mat" << Cols;
1334 str << "mat" << Cols << "x" << Rows;
1337 for (int colNdx = 0; colNdx < Cols; colNdx++)
1339 for (int rowNdx = 0; rowNdx < Rows; rowNdx++)
1341 if (rowNdx > 0 || colNdx > 0)
1343 str << de::floatToString(m(rowNdx, colNdx), 1);
1349 } // MatrixCaseUtils
1351 using namespace MatrixCaseUtils;
1353 class MatrixShaderEvaluator : public ShaderEvaluator
1356 MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1);
1358 virtual void evaluate (ShaderEvalContext& evalCtx) const;
1361 MatrixShaderEvalFunc m_matEvalFunc;
1362 InputType m_inType0;
1363 InputType m_inType1;
1366 MatrixShaderEvaluator::MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1)
1367 : m_matEvalFunc (evalFunc)
1368 , m_inType0 (inType0)
1369 , m_inType1 (inType1)
1373 void MatrixShaderEvaluator::evaluate (ShaderEvalContext& evalCtx) const
1375 m_matEvalFunc(evalCtx, m_inType0, m_inType1);
1379 BaseAttributeType getAttributeType(const glu::DataType dataType)
1383 case TYPE_FLOAT_MAT2: return MAT2;
1384 case TYPE_FLOAT_MAT2X3: return MAT2x3;
1385 case TYPE_FLOAT_MAT2X4: return MAT2x4;
1386 case TYPE_FLOAT_MAT3X2: return MAT3x2;
1387 case TYPE_FLOAT_MAT3: return MAT3;
1388 case TYPE_FLOAT_MAT3X4: return MAT3x4;
1389 case TYPE_FLOAT_MAT4X2: return MAT4x2;
1390 case TYPE_FLOAT_MAT4X3: return MAT4x3;
1391 case TYPE_FLOAT_MAT4: return MAT4;
1393 TCU_THROW(InternalError, "Not supported");
1398 // ShaderMatrixInstance
1400 class ShaderMatrixInstance : public ShaderRenderCaseInstance
1403 ShaderMatrixInstance (Context& context,
1405 const ShaderEvaluator& evaluator,
1406 const ShaderInput in0,
1407 const ShaderInput in1,
1408 const MatrixOp m_op);
1409 virtual ~ShaderMatrixInstance (void);
1412 virtual void setupUniforms (const tcu::Vec4&);
1415 void addMatrixUniform (deUint32 bindingLocation, DataType dataType, const float* dataPtr);
1417 const ShaderInput m_in0;
1418 const ShaderInput m_in1;
1419 const MatrixOp m_op;
1422 ShaderMatrixInstance::ShaderMatrixInstance (Context& context,
1424 const ShaderEvaluator& evaluator,
1425 const ShaderInput in0,
1426 const ShaderInput in1,
1428 : ShaderRenderCaseInstance (context, isVertex, evaluator, DE_NULL, DE_NULL)
1433 m_userAttribTransforms.resize(4);
1434 for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1436 m_userAttribTransforms[attribNdx] = Mat4(0.0f);
1437 m_userAttribTransforms[attribNdx]( 0, 3) = 0.2f; // !< prevent matrix*vec from going into zero (assuming vec.w != 0)
1438 m_userAttribTransforms[attribNdx]( 1, 3) = 0.1f; // !<
1439 m_userAttribTransforms[attribNdx]( 2, 3) = 0.4f + 0.15f * float(attribNdx); // !<
1440 m_userAttribTransforms[attribNdx]( 3, 3) = 0.7f; // !<
1441 m_userAttribTransforms[attribNdx]((0 + attribNdx) % 4, 0) = 1.0f;
1442 m_userAttribTransforms[attribNdx]((1 + attribNdx) % 4, 1) = 1.0f;
1443 m_userAttribTransforms[attribNdx]((2 + attribNdx) % 4, 2) = 1.0f;
1444 m_userAttribTransforms[attribNdx]((3 + attribNdx) % 4, 3) = 1.0f;
1447 // prevent bad reference cases such as black result images by fine-tuning used matrices
1448 if (getOperationTestMatrixType(m_op) != TESTMATRIXTYPE_DEFAULT)
1450 for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1452 for (int row = 0; row < 4; row++)
1453 for (int col = 0; col < 4; col++)
1455 switch (getOperationTestMatrixType(m_op))
1457 case TESTMATRIXTYPE_NEGATED:
1458 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col);
1460 case TESTMATRIXTYPE_INCREMENTED:
1461 m_userAttribTransforms[attribNdx](row, col) += 0.3f;
1463 case TESTMATRIXTYPE_DECREMENTED:
1464 m_userAttribTransforms[attribNdx](row, col) -= 0.3f;
1466 case TESTMATRIXTYPE_NEGATED_INCREMENTED:
1467 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col) + 0.3f;
1469 case TESTMATRIXTYPE_INCREMENTED_LESS:
1470 m_userAttribTransforms[attribNdx](row, col) -= 0.1f;
1474 DE_ASSERT(DE_FALSE);
1481 int numInputs = isOperationBinary(m_op) ? 2 : 1;
1483 for (int inNdx = 0; inNdx < numInputs; inNdx++)
1485 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1487 if (in.inputType == INPUTTYPE_DYNAMIC && isDataTypeMatrix(in.dataType))
1489 useAttribute(4u + inNdx, getAttributeType(in.dataType));
1495 ShaderMatrixInstance::~ShaderMatrixInstance (void)
1499 void ShaderMatrixInstance::addMatrixUniform(deUint32 bindingLocation, DataType dataType, const float *dataPtr)
1502 const size_t matrixSize = sizeof(float) * 4 * 4;
1506 case TYPE_FLOAT_MAT2:
1508 Mat2 matrix = Mat2(dataPtr);
1509 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1510 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1513 case TYPE_FLOAT_MAT2X3:
1515 Mat2x3 matrix = Mat2x3(dataPtr);
1516 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1517 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1520 case TYPE_FLOAT_MAT2X4:
1522 Mat2x4 matrix = Mat2x4(dataPtr);
1523 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1524 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1527 case TYPE_FLOAT_MAT3X2:
1529 Mat3x2 matrix = Mat3x2(dataPtr);
1530 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1531 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1532 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1535 case TYPE_FLOAT_MAT3:
1537 Mat3 matrix = Mat3(dataPtr);
1538 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1539 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1540 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1543 case TYPE_FLOAT_MAT3X4:
1545 Mat3x4 matrix = Mat3x4(dataPtr);
1546 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1547 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1548 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1551 case TYPE_FLOAT_MAT4X2:
1553 Mat4x2 matrix = Mat4x2(dataPtr);
1554 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1555 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1556 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1557 result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1560 case TYPE_FLOAT_MAT4X3:
1562 Mat4x3 matrix = Mat4x3(dataPtr);
1563 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1564 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1565 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1566 result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1569 case TYPE_FLOAT_MAT4:
1571 Mat4 matrix = Mat4(dataPtr);
1572 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1573 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1574 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1575 result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1583 addUniform(bindingLocation, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, matrixSize, result.getColumnMajorData().getPtr());
1586 void ShaderMatrixInstance::setupUniforms (const tcu::Vec4&)
1588 const int numInputs = isOperationBinary(m_op) ? 2 : 1;
1589 deUint32 uniformBinding = 0;
1591 for (int inNdx = 0; inNdx < numInputs; inNdx++)
1593 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1595 if (in.inputType == INPUTTYPE_UNIFORM)
1597 switch (in.dataType)
1599 case TYPE_FLOAT: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(float), &s_constInFloat[inNdx]); break;
1600 case TYPE_FLOAT_VEC2: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec2[inNdx]); break;
1601 case TYPE_FLOAT_VEC3: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec3[inNdx]); break;
1602 case TYPE_FLOAT_VEC4: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec4[inNdx]); break;
1603 // \note GLES3 supports transpose in matrix upload.
1604 case TYPE_FLOAT_MAT2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x2[inNdx]); break;
1605 case TYPE_FLOAT_MAT2X3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x3[inNdx]); break;
1606 case TYPE_FLOAT_MAT2X4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x4[inNdx]); break;
1607 case TYPE_FLOAT_MAT3X2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x2[inNdx]); break;
1608 case TYPE_FLOAT_MAT3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x3[inNdx]); break;
1609 case TYPE_FLOAT_MAT3X4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x4[inNdx]); break;
1610 case TYPE_FLOAT_MAT4X2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x2[inNdx]); break;
1611 case TYPE_FLOAT_MAT4X3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x3[inNdx]); break;
1612 case TYPE_FLOAT_MAT4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x4[inNdx]); break;
1623 class ShaderMatrixCase : public ShaderRenderCase
1626 ShaderMatrixCase (tcu::TestContext& testCtx,
1627 const std::string& name,
1628 const std::string& desc,
1629 const ShaderInput& in0,
1630 const ShaderInput& in1,
1633 ~ShaderMatrixCase (void);
1635 virtual TestInstance* createInstance (Context& context) const;
1638 void setupShader (void);
1639 std::string genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName);
1642 const ShaderInput m_in0;
1643 const ShaderInput m_in1;
1644 const MatrixOp m_op;
1647 ShaderMatrixCase::ShaderMatrixCase (tcu::TestContext& testCtx,
1648 const std::string& name,
1649 const std::string& desc,
1650 const ShaderInput& in0,
1651 const ShaderInput& in1,
1654 : ShaderRenderCase (testCtx,
1658 new MatrixShaderEvaluator(getEvalFunc(in0, in1, op), in0.inputType, in1.inputType),
1659 DE_NULL /* uniform setup */,
1660 DE_NULL /* attribute setup */)
1668 ShaderMatrixCase::~ShaderMatrixCase (void)
1672 TestInstance* ShaderMatrixCase::createInstance (Context& context) const
1674 return new ShaderMatrixInstance(context, m_isVertexCase, *m_evaluator, m_in0, m_in1, m_op);
1677 void ShaderMatrixCase::setupShader (void)
1679 std::ostringstream vtx;
1680 std::ostringstream frag;
1681 std::ostringstream& op = m_isVertexCase ? vtx : frag;
1683 bool isInDynMat0 = isDataTypeMatrix(m_in0.dataType) && m_in0.inputType == INPUTTYPE_DYNAMIC;
1684 bool isInDynMat1 = isDataTypeMatrix(m_in1.dataType) && m_in1.inputType == INPUTTYPE_DYNAMIC;
1687 DataType resultType = TYPE_LAST;
1688 Precision resultPrec = m_in0.precision;
1689 vector<string> passVars;
1690 int numInputs = (isOperationBinary(m_op)) ? (2) : (1);
1692 std::string operationValue0;
1693 std::string operationValue1;
1695 DE_ASSERT(!isInDynMat0 || !isInDynMat1); // Only single dynamic matrix input is allowed.
1696 DE_UNREF(isInDynMat0 && isInDynMat1);
1698 // Compute result type.
1699 if (m_op == OP_MUL && isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1701 resultType = getDataTypeMatrix(getDataTypeMatrixNumColumns(m_in1.dataType), getDataTypeMatrixNumRows(m_in0.dataType));
1703 else if (m_op == OP_OUTER_PRODUCT)
1705 resultType = getDataTypeMatrix(getDataTypeScalarSize(m_in1.dataType), getDataTypeScalarSize(m_in0.dataType));
1707 else if (m_op == OP_TRANSPOSE)
1709 resultType = getDataTypeMatrix(getDataTypeMatrixNumRows(m_in0.dataType), getDataTypeMatrixNumColumns(m_in0.dataType));
1711 else if (m_op == OP_INVERSE)
1713 resultType = m_in0.dataType;
1715 else if (m_op == OP_DETERMINANT)
1717 resultType = TYPE_FLOAT;
1719 else if (getOperationType(m_op) == OPERATIONTYPE_UNARY_PREFIX_OPERATOR ||
1720 getOperationType(m_op) == OPERATIONTYPE_UNARY_POSTFIX_OPERATOR)
1722 resultType = m_in0.dataType;
1724 else if (isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1726 DE_ASSERT(m_in0.dataType == m_in1.dataType);
1727 resultType = m_in0.dataType;
1729 else if (isDataTypeMatrix(m_in0.dataType) || isDataTypeMatrix(m_in1.dataType))
1731 int matNdx = isDataTypeMatrix(m_in0.dataType) ? 0 : 1;
1732 DataType matrixType = matNdx == 0 ? m_in0.dataType : m_in1.dataType;
1733 DataType otherType = matNdx == 0 ? m_in1.dataType : m_in0.dataType;
1735 if (otherType == TYPE_FLOAT)
1736 resultType = matrixType;
1739 DE_ASSERT(isDataTypeVector(otherType));
1740 resultType = getDataTypeFloatVec(matNdx == 0 ? getDataTypeMatrixNumRows(matrixType) : getDataTypeMatrixNumColumns(matrixType));
1745 DE_ASSERT(DE_FALSE);
1748 static const std::string header =
1749 "#version 310 es\n";
1754 vtx << "layout(location = 0) in highp vec4 a_position;\n";
1755 frag << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1758 vtx << "layout(location = 0) out mediump vec4 v_color;\n";
1759 frag << "layout(location = 0) in mediump vec4 v_color;\n";
1762 // Input declarations.
1763 deUint32 uniformBinding = 0;
1764 deUint32 padding = 0;
1765 for (int inNdx = 0; inNdx < numInputs; inNdx++)
1767 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1768 const char* precName = getPrecisionName(in.precision);
1769 const char* typeName = getDataTypeName(in.dataType);
1770 string& inValue = inNdx > 0 ? inValue1 : inValue0;
1772 if (in.inputType == INPUTTYPE_DYNAMIC)
1774 if (isDataTypeMatrix(in.dataType))
1776 vtx << "layout(location = " << 4 + inNdx + padding << ") in " << precName << " " << typeName << " a_";
1778 vtx << typeName << ";\n";
1779 if (!m_isVertexCase)
1781 vtx << "layout(location = " << 1 + inNdx + padding << ") out " << precName << " " << typeName << " v_" << typeName << ";\n";
1782 frag << "layout(location = " << 1 + inNdx + padding << ") in " << precName << " " << typeName << " v_" << typeName << ";\n";
1783 passVars.push_back(typeName);
1786 inValue = string(m_isVertexCase ? "a_" : "v_") + getDataTypeName(in.dataType);
1787 padding += getDataTypeMatrixNumColumns(in.dataType);
1791 // a_coords, v_coords
1792 vtx << "layout(location = 1) in " << precName << " " << typeName << " a_coords;\n";
1793 if (!m_isVertexCase)
1795 vtx << "layout(location = " << 1 + padding << ") out " << precName << " " << typeName << " v_coords;\n";
1796 frag << "layout(location = " << 1 + padding << ") in " << precName << " " << typeName << " v_coords;\n";
1797 passVars.push_back("coords");
1800 inValue = m_isVertexCase ? "a_coords" : "v_coords";
1803 else if (in.inputType == INPUTTYPE_UNIFORM)
1805 op << "layout(std140, set = 0, binding = " << uniformBinding++ << ") uniform buffer"<< inNdx <<" { " << precName << " " << typeName << " u_in" << inNdx << "; };\n";
1806 inValue = string("u_in") + de::toString(inNdx);
1808 else if (in.inputType == INPUTTYPE_CONST)
1810 op << "const " << precName << " " << typeName << " in" << inNdx << " = ";
1812 // Generate declaration.
1813 switch (in.dataType)
1815 case TYPE_FLOAT: op << de::floatToString(s_constInFloat[inNdx], 1); break;
1816 case TYPE_FLOAT_VEC2: writeVectorConstructor<2>(op, s_constInVec2[inNdx]); break;
1817 case TYPE_FLOAT_VEC3: writeVectorConstructor<3>(op, s_constInVec3[inNdx]); break;
1818 case TYPE_FLOAT_VEC4: writeVectorConstructor<4>(op, s_constInVec4[inNdx]); break;
1819 case TYPE_FLOAT_MAT2: writeMatrixConstructor<2, 2>(op, Mat2(s_constInMat2x2[inNdx])); break;
1820 case TYPE_FLOAT_MAT2X3: writeMatrixConstructor<2, 3>(op, Mat2x3(s_constInMat2x3[inNdx])); break;
1821 case TYPE_FLOAT_MAT2X4: writeMatrixConstructor<2, 4>(op, Mat2x4(s_constInMat2x4[inNdx])); break;
1822 case TYPE_FLOAT_MAT3X2: writeMatrixConstructor<3, 2>(op, Mat3x2(s_constInMat3x2[inNdx])); break;
1823 case TYPE_FLOAT_MAT3: writeMatrixConstructor<3, 3>(op, Mat3(s_constInMat3x3[inNdx])); break;
1824 case TYPE_FLOAT_MAT3X4: writeMatrixConstructor<3, 4>(op, Mat3x4(s_constInMat3x4[inNdx])); break;
1825 case TYPE_FLOAT_MAT4X2: writeMatrixConstructor<4, 2>(op, Mat4x2(s_constInMat4x2[inNdx])); break;
1826 case TYPE_FLOAT_MAT4X3: writeMatrixConstructor<4, 3>(op, Mat4x3(s_constInMat4x3[inNdx])); break;
1827 case TYPE_FLOAT_MAT4: writeMatrixConstructor<4, 4>(op, Mat4(s_constInMat4x4[inNdx])); break;
1830 DE_ASSERT(DE_FALSE);
1835 inValue = string("in") + de::toString(inNdx);
1840 << "void main (void)\n"
1842 << " gl_Position = a_position;\n";
1844 << "void main (void)\n"
1848 frag << " dEQP_FragColor = v_color;\n";
1851 for (vector<string>::const_iterator copyIter = passVars.begin(); copyIter != passVars.end(); copyIter++)
1852 vtx << " v_" << *copyIter << " = " << "a_" << *copyIter << ";\n";
1857 switch (getOperationNature(m_op))
1859 case OPERATIONNATURE_PURE:
1860 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1862 operationValue0 = inValue0;
1863 operationValue1 = inValue1;
1866 case OPERATIONNATURE_MUTATING:
1867 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1869 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " tmpValue = " << inValue0 << ";\n";
1871 operationValue0 = "tmpValue";
1872 operationValue1 = inValue1;
1875 case OPERATIONNATURE_ASSIGNMENT:
1876 DE_ASSERT(getOperationType(m_op) == OPERATIONTYPE_ASSIGNMENT);
1878 operationValue0 = inValue0;
1879 operationValue1 = inValue1;
1883 DE_ASSERT(DE_FALSE);
1886 switch (getOperationType(m_op))
1888 case OPERATIONTYPE_BINARY_OPERATOR:
1889 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << " " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1892 case OPERATIONTYPE_UNARY_PREFIX_OPERATOR:
1893 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << operationValue0 << ";\n";
1896 case OPERATIONTYPE_UNARY_POSTFIX_OPERATOR:
1897 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << getOperationName(m_op) << ";\n";
1900 case OPERATIONTYPE_BINARY_FUNCTION:
1901 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ", " << operationValue1 << ");\n";
1904 case OPERATIONTYPE_UNARY_FUNCTION:
1905 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ");\n";
1908 case OPERATIONTYPE_ASSIGNMENT:
1909 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << ";\n";
1910 op << " res " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1914 DE_ASSERT(DE_FALSE);
1917 // Reduction to vec3 (rgb). Check the used value too if it was modified
1918 op << " " << (m_isVertexCase ? "v_color" : "dEQP_FragColor") << " = ";
1920 if (isOperationValueModifying(m_op))
1921 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0) + vec4(" << genGLSLMatToVec3Reduction(resultType, "tmpValue") << ", 0.0);\n";
1923 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0);\n";
1928 m_vertShaderSource = vtx.str();
1929 m_fragShaderSource = frag.str();
1932 std::string ShaderMatrixCase::genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName)
1934 std::ostringstream op;
1938 case TYPE_FLOAT: op << varName << ", " << varName << ", " << varName << ""; break;
1939 case TYPE_FLOAT_VEC2: op << varName << ".x, " << varName << ".y, " << varName << ".x"; break;
1940 case TYPE_FLOAT_VEC3: op << varName << ""; break;
1941 case TYPE_FLOAT_VEC4: op << varName << ".x, " << varName << ".y, " << varName << ".z+" << varName << ".w"; break;
1942 case TYPE_FLOAT_MAT2: op << varName << "[0][0], " << varName << "[1][0], " << varName << "[0][1]+" << varName << "[1][1]"; break;
1943 case TYPE_FLOAT_MAT2X3: op << varName << "[0] + " << varName << "[1]"; break;
1944 case TYPE_FLOAT_MAT2X4: op << varName << "[0].xyz + " << varName << "[1].yzw"; break;
1945 case TYPE_FLOAT_MAT3X2: op << varName << "[0][0]+" << varName << "[0][1], " << varName << "[1][0]+" << varName << "[1][1], " << varName << "[2][0]+" << varName << "[2][1]"; break;
1946 case TYPE_FLOAT_MAT3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2]"; break;
1947 case TYPE_FLOAT_MAT3X4: op << varName << "[0].xyz + " << varName << "[1].yzw + " << varName << "[2].zwx"; break;
1948 case TYPE_FLOAT_MAT4X2: op << varName << "[0][0]+" << varName << "[0][1]+" << varName << "[3][0], " << varName << "[1][0]+" << varName << "[1][1]+" << varName << "[3][1], " << varName << "[2][0]+" << varName << "[2][1]"; break;
1949 case TYPE_FLOAT_MAT4X3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2] + " << varName << "[3]"; break;
1950 case TYPE_FLOAT_MAT4: op << varName << "[0].xyz+" << varName << "[1].yzw+" << varName << "[2].zwx+" << varName << "[3].wxy"; break;
1953 DE_ASSERT(DE_FALSE);
1959 class ShaderMatrixTests : public tcu::TestCaseGroup
1962 ShaderMatrixTests (tcu::TestContext& testCtx);
1963 virtual ~ShaderMatrixTests (void);
1965 virtual void init (void);
1968 ShaderMatrixTests (const ShaderMatrixTests&); // not allowed!
1969 ShaderMatrixTests& operator= (const ShaderMatrixTests&); // not allowed!
1972 ShaderMatrixTests::ShaderMatrixTests (tcu::TestContext& testCtx)
1973 : TestCaseGroup(testCtx, "matrix", "Matrix Tests")
1977 ShaderMatrixTests::~ShaderMatrixTests (void)
1981 void ShaderMatrixTests::init (void)
1988 const bool extendedInputTypeCases; // !< test with const and uniform types too
1989 const bool createInputTypeGroup; // !< create group for input types
1992 { "add", "Matrix addition tests", OP_ADD, true, true },
1993 { "sub", "Matrix subtraction tests", OP_SUB, true, true },
1994 { "mul", "Matrix multiplication tests", OP_MUL, true, true },
1995 { "div", "Matrix division tests", OP_DIV, true, true },
1996 { "matrixcompmult", "Matrix component-wise multiplication tests", OP_COMP_MUL, false, true },
1997 { "outerproduct", "Matrix outerProduct() tests", OP_OUTER_PRODUCT, false, true },
1998 { "transpose", "Matrix transpose() tests", OP_TRANSPOSE, false, true },
1999 { "determinant", "Matrix determinant() tests", OP_DETERMINANT, false, true },
2000 { "inverse", "Matrix inverse() tests", OP_INVERSE, false, true },
2001 { "unary_addition", "Matrix unary addition tests", OP_UNARY_PLUS, false, false },
2002 { "negation", "Matrix negation tests", OP_NEGATION, false, false },
2003 { "pre_increment", "Matrix prefix increment tests", OP_PRE_INCREMENT, false, false },
2004 { "pre_decrement", "Matrix prefix decrement tests", OP_PRE_DECREMENT, false, false },
2005 { "post_increment", "Matrix postfix increment tests", OP_POST_INCREMENT, false, false },
2006 { "post_decrement", "Matrix postfix decrement tests", OP_POST_DECREMENT, false, false },
2007 { "add_assign", "Matrix add into tests", OP_ADD_INTO, false, false },
2008 { "sub_assign", "Matrix subtract from tests", OP_SUBTRACT_FROM, false, false },
2009 { "mul_assign", "Matrix multiply into tests", OP_MULTIPLY_INTO, false, false },
2010 { "div_assign", "Matrix divide into tests", OP_DIVIDE_INTO, false, false },
2013 struct InputTypeSpec
2017 const InputType type;
2019 static const InputTypeSpec extendedInputTypes[] =
2021 { "const", "Constant matrix input", INPUTTYPE_CONST },
2022 { "uniform", "Uniform matrix input", INPUTTYPE_UNIFORM },
2023 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC }
2025 static const InputTypeSpec reducedInputTypes[] =
2027 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC }
2030 static const DataType matrixTypes[] =
2043 static const Precision precisions[] =
2049 for (int opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
2051 const InputTypeSpec* inTypeList = (ops[opNdx].extendedInputTypeCases) ? (extendedInputTypes) : (reducedInputTypes);
2052 const int inTypeListSize = (ops[opNdx].extendedInputTypeCases) ? (DE_LENGTH_OF_ARRAY(extendedInputTypes)) : (DE_LENGTH_OF_ARRAY(reducedInputTypes));
2053 const MatrixOp op = ops[opNdx].op;
2054 tcu::TestCaseGroup* opGroup = new tcu::TestCaseGroup(m_testCtx, ops[opNdx].name, ops[opNdx].desc);
2058 for (int inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++)
2060 const InputType inputType = inTypeList[inTypeNdx].type;
2061 tcu::TestCaseGroup* inGroup;
2063 if (ops[opNdx].createInputTypeGroup)
2065 inGroup = new tcu::TestCaseGroup(m_testCtx, inTypeList[inTypeNdx].name, inTypeList[inTypeNdx].desc);
2066 opGroup->addChild(inGroup);
2071 for (int matTypeNdx = 0; matTypeNdx < DE_LENGTH_OF_ARRAY(matrixTypes); matTypeNdx++)
2073 DataType matType = matrixTypes[matTypeNdx];
2074 int numCols = getDataTypeMatrixNumColumns(matType);
2075 int numRows = getDataTypeMatrixNumRows(matType);
2076 const char* matTypeName = getDataTypeName(matType);
2078 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
2080 Precision precision = precisions[precNdx];
2081 const char* precName = getPrecisionName(precision);
2082 string baseName = string(precName) + "_" + matTypeName + "_";
2083 ShaderInput matIn (inputType, matType, precision);
2085 if (isOperationMatrixScalar(op))
2087 // Matrix-scalar \note For div cases we use uniform input.
2088 ShaderInput scalarIn(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, TYPE_FLOAT, precision);
2089 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Matrix-scalar case", matIn, scalarIn, op, true));
2090 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Matrix-scalar case", matIn, scalarIn, op, false));
2093 if (isOperationMatrixVector(op))
2096 DataType colVecType = getDataTypeFloatVec(numCols);
2097 ShaderInput colVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, colVecType, precision);
2099 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_vertex").c_str(), "Matrix-vector case", matIn, colVecIn, op, true));
2100 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_fragment").c_str(), "Matrix-vector case", matIn, colVecIn, op, false));
2103 DataType rowVecType = getDataTypeFloatVec(numRows);
2104 ShaderInput rowVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, rowVecType, precision);
2105 string vecMatName = string(precName) + "_" + getDataTypeName(rowVecType) + "_" + matTypeName;
2107 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_vertex").c_str(), "Vector-matrix case", rowVecIn, matIn, op, true));
2108 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_fragment").c_str(), "Vector-matrix case", rowVecIn, matIn, op, false));
2111 if (isOperationArithmeticMatrixMatrix(op))
2113 // Arithmetic matrix-matrix multiplication.
2114 for (int otherCols = 2; otherCols <= 4; otherCols++)
2116 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, getDataTypeMatrix(otherCols, numCols /* rows */), precision);
2117 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true));
2118 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false));
2121 else if (isOperationComponentwiseMatrixMatrix(op))
2124 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2125 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true));
2126 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false));
2129 if (isOperationVectorVector(op))
2131 ShaderInput vec1In(inputType, getDataTypeFloatVec(numRows), precision);
2132 ShaderInput vec2In((inputType == INPUTTYPE_DYNAMIC) ? (INPUTTYPE_UNIFORM) : (inputType), getDataTypeFloatVec(numCols), precision);
2134 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Vector-vector case", vec1In, vec2In, op, true));
2135 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Vector-vector case", vec1In, vec2In, op, false));
2138 if ((isOperationUnaryAnyMatrix(op)) ||
2139 (isOperationUnarySymmetricMatrix(op) && numCols == numRows))
2141 ShaderInput voidInput(INPUTTYPE_LAST, TYPE_LAST, PRECISION_LAST);
2142 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Matrix case", matIn, voidInput, op, true));
2143 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Matrix case", matIn, voidInput, op, false));
2146 if ((isOperationAssignmentAnyMatrix(op)) ||
2147 (isOperationAssignmentSymmetricMatrix(op) && numCols == numRows))
2149 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2150 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Matrix assignment case", matIn, otherMatIn, op, true));
2151 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Matrix assignment case", matIn, otherMatIn, op, false));
2161 tcu::TestCaseGroup* createMatrixTests (tcu::TestContext& testCtx)
2163 return new ShaderMatrixTests(testCtx);