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> outerProduct (const tcu::Vector<T, Cols>& a, const tcu::Vector<T, Rows>& b)
635 tcu::Matrix<T, Rows, Cols> retVal;
637 for (int r = 0; r < Rows; ++r)
638 for (int c = 0; c < Cols; ++c)
639 retVal(r,c) = a[c] * b[r];
641 return transpose(retVal); // to gl-form (column-major)
647 float determinant (const tcu::Matrix<float, Size, Size>& mat);
650 float determinant<2> (const tcu::Matrix<float, 2, 2>& mat)
652 return mat(0,0) * mat(1,1) - mat(1,0) * mat(0,1);
656 float determinant<3> (const tcu::Matrix<float, 3, 3>& mat)
658 return + mat(0,0) * mat(1,1) * mat(2,2)
659 + mat(0,1) * mat(1,2) * mat(2,0)
660 + mat(0,2) * mat(1,0) * mat(2,1)
661 - mat(0,0) * mat(1,2) * mat(2,1)
662 - mat(0,1) * mat(1,0) * mat(2,2)
663 - mat(0,2) * mat(1,1) * mat(2,0);
667 float determinant<4> (const tcu::Matrix<float, 4, 4>& mat)
669 const float minorMatrices[4][3*3] =
672 mat(1,1), mat(2,1), mat(3,1),
673 mat(1,2), mat(2,2), mat(3,2),
674 mat(1,3), mat(2,3), mat(3,3),
677 mat(1,0), mat(2,0), mat(3,0),
678 mat(1,2), mat(2,2), mat(3,2),
679 mat(1,3), mat(2,3), mat(3,3),
682 mat(1,0), mat(2,0), mat(3,0),
683 mat(1,1), mat(2,1), mat(3,1),
684 mat(1,3), mat(2,3), mat(3,3),
687 mat(1,0), mat(2,0), mat(3,0),
688 mat(1,1), mat(2,1), mat(3,1),
689 mat(1,2), mat(2,2), mat(3,2),
693 return + mat(0,0) * determinant(tcu::Mat3(minorMatrices[0]))
694 - mat(0,1) * determinant(tcu::Mat3(minorMatrices[1]))
695 + mat(0,2) * determinant(tcu::Mat3(minorMatrices[2]))
696 - mat(0,3) * determinant(tcu::Mat3(minorMatrices[3]));
702 tcu::Matrix<float, Size, Size> inverse (const tcu::Matrix<float, Size, Size>& mat);
705 tcu::Matrix<float, 2, 2> inverse<2> (const tcu::Matrix<float, 2, 2>& mat)
707 const float det = determinant(mat);
708 tcu::Matrix<float, 2, 2> retVal;
710 DE_ASSERT(det != 0.0f);
712 retVal(0, 0) = mat(1, 1) / det;
713 retVal(0, 1) = -mat(0, 1) / det;
714 retVal(1, 0) = -mat(1, 0) / det;
715 retVal(1, 1) = mat(0, 0) / det;
721 tcu::Matrix<float, 3, 3> inverse<3> (const tcu::Matrix<float, 3, 3>& mat)
723 // Blockwise inversion
725 DE_ASSERT(determinant(mat) != 0.0f);
727 const float areaA[2*2] =
732 const float areaB[2] =
737 const float areaC[2] =
741 const float areaD[1] =
745 const float nullField[4] = { 0.0f };
747 const tcu::Matrix<float, 2, 2> invA = inverse(tcu::Matrix<float, 2, 2>(areaA));
748 const tcu::Matrix<float, 2, 1> matB = tcu::Matrix<float, 2, 1>(areaB);
749 const tcu::Matrix<float, 1, 2> matC = tcu::Matrix<float, 1, 2>(areaC);
750 const tcu::Matrix<float, 1, 1> matD = tcu::Matrix<float, 1, 1>(areaD);
752 const float schurComplement = 1.0f / (matD - matC*invA*matB)(0,0);
753 const tcu::Matrix<float, 2, 2> zeroMat = Mat2(nullField);
755 const tcu::Matrix<float, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA;
756 const tcu::Matrix<float, 2, 1> blockB = (zeroMat-invA)*matB*schurComplement;
757 const tcu::Matrix<float, 1, 2> blockC = matC*invA*(-schurComplement);
758 const float blockD = schurComplement;
760 const float result[3*3] =
762 blockA(0,0), blockA(0,1), blockB(0,0),
763 blockA(1,0), blockA(1,1), blockB(1,0),
764 blockC(0,0), blockC(0,1), blockD,
771 tcu::Matrix<float, 4, 4> inverse<4> (const tcu::Matrix<float, 4, 4>& mat)
773 // Blockwise inversion
775 DE_ASSERT(determinant(mat) != 0.0f);
777 const float areaA[2*2] =
782 const float areaB[2*2] =
787 const float areaC[2*2] =
792 const float areaD[2*2] =
797 const float nullField[4] = { 0.0f };
799 const tcu::Matrix<float, 2, 2> invA = inverse(Mat2(areaA));
800 const tcu::Matrix<float, 2, 2> matB = Mat2(areaB);
801 const tcu::Matrix<float, 2, 2> matC = Mat2(areaC);
802 const tcu::Matrix<float, 2, 2> matD = Mat2(areaD);
804 const tcu::Matrix<float, 2, 2> schurComplement = inverse(matD - matC*invA*matB);
805 const tcu::Matrix<float, 2, 2> zeroMat = Mat2(nullField);
807 const tcu::Matrix<float, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA;
808 const tcu::Matrix<float, 2, 2> blockB = (zeroMat-invA)*matB*schurComplement;
809 const tcu::Matrix<float, 2, 2> blockC = (zeroMat-schurComplement)*matC*invA;
810 const tcu::Matrix<float, 2, 2> blockD = schurComplement;
812 const float result[4*4] =
814 blockA(0,0), blockA(0,1), blockB(0,0), blockB(0,1),
815 blockA(1,0), blockA(1,1), blockB(1,0), blockB(1,1),
816 blockC(0,0), blockC(0,1), blockD(0,0), blockD(0,1),
817 blockC(1,0), blockC(1,1), blockD(1,0), blockD(1,1),
825 template <typename T, int Rows, int Cols>
826 tcu::Matrix<T, Rows, Cols> negate (const tcu::Matrix<T, Rows, Cols>& mat)
828 tcu::Matrix<T, Rows, Cols> retVal;
830 for (int r = 0; r < Rows; ++r)
831 for (int c = 0; c < Cols; ++c)
832 retVal(r,c) = -mat(r, c);
837 // increment/decrement
839 template <typename T, int Rows, int Cols>
840 tcu::Matrix<T, Rows, Cols> increment (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) + 1.0f;
851 template <typename T, int Rows, int Cols>
852 tcu::Matrix<T, Rows, Cols> decrement (const tcu::Matrix<T, Rows, Cols>& mat)
854 tcu::Matrix<T, Rows, Cols> retVal;
856 for (int r = 0; r < Rows; ++r)
857 for (int c = 0; c < Cols; ++c)
858 retVal(r,c) = mat(r, c) - 1.0f;
863 // Evaluator template.
865 typedef void (*MatrixShaderEvalFunc) (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type);
867 template <int Op, int In0DataType, int In1DataType>
870 template <int In0DataType, int In1DataType>
871 struct Evaluator<OP_ADD, In0DataType, In1DataType>
873 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
875 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
876 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
877 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
878 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
879 evalCtx.color.xyz() = reduceToVec3(in0 + in1);
883 template <int In0DataType, int In1DataType>
884 struct Evaluator<OP_SUB, In0DataType, In1DataType>
886 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
888 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
889 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
890 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
891 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
892 evalCtx.color.xyz() = reduceToVec3(in0 - in1);
896 template <int In0DataType, int In1DataType>
897 struct Evaluator<OP_MUL, In0DataType, In1DataType>
899 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
901 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
902 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
903 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
904 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
905 evalCtx.color.xyz() = reduceToVec3(in0 * in1);
909 template <int In0DataType, int In1DataType>
910 struct Evaluator<OP_DIV, In0DataType, In1DataType>
912 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
914 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
915 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
916 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
917 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
918 evalCtx.color.xyz() = reduceToVec3(in0 / in1);
922 template <int In0DataType, int In1DataType>
923 struct Evaluator<OP_COMP_MUL, In0DataType, In1DataType>
925 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
927 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
928 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
929 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
930 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
931 evalCtx.color.xyz() = reduceToVec3(matrixCompMult(in0, in1));
935 template <int In0DataType, int In1DataType>
936 struct Evaluator<OP_OUTER_PRODUCT, In0DataType, In1DataType>
938 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
940 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
941 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
942 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
943 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
944 evalCtx.color.xyz() = reduceToVec3(outerProduct(in0, in1));
948 template <int In0DataType, int In1DataType>
949 struct Evaluator<OP_TRANSPOSE, In0DataType, In1DataType>
951 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 evalCtx.color.xyz() = reduceToVec3(transpose(in0));
960 template <int In0DataType, int In1DataType>
961 struct Evaluator<OP_INVERSE, In0DataType, In1DataType>
963 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
966 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
967 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
968 evalCtx.color.xyz() = reduceToVec3(inverse(in0));
972 template <int In0DataType, int In1DataType>
973 struct Evaluator<OP_DETERMINANT, In0DataType, In1DataType>
975 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
978 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
979 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
980 evalCtx.color.xyz() = Vec3(determinant(in0));
984 template <int In0DataType, int In1DataType>
985 struct Evaluator<OP_UNARY_PLUS, In0DataType, In1DataType>
987 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
990 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
991 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
992 evalCtx.color.xyz() = reduceToVec3(in0);
996 template <int In0DataType, int In1DataType>
997 struct Evaluator<OP_NEGATION, In0DataType, In1DataType>
999 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1002 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1003 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1004 evalCtx.color.xyz() = reduceToVec3(negate(in0));
1008 template <int In0DataType, int In1DataType>
1009 struct Evaluator<OP_PRE_INCREMENT, In0DataType, In1DataType>
1011 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1014 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1015 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1017 // modifying reduction: sum modified value too
1018 evalCtx.color.xyz() = reduceToVec3(increment(in0)) + reduceToVec3(increment(in0));
1022 template <int In0DataType, int In1DataType>
1023 struct Evaluator<OP_PRE_DECREMENT, 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(decrement(in0)) + reduceToVec3(decrement(in0));
1036 template <int In0DataType, int In1DataType>
1037 struct Evaluator<OP_POST_INCREMENT, 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(in0) + reduceToVec3(increment(in0));
1050 template <int In0DataType, int In1DataType>
1051 struct Evaluator<OP_POST_DECREMENT, 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(decrement(in0));
1064 template <int In0DataType, int In1DataType>
1065 struct Evaluator<OP_ADD_INTO, In0DataType, In1DataType>
1067 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1069 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1070 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1071 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1072 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
1073 evalCtx.color.xyz() = reduceToVec3(in0 + in1);
1077 template <int In0DataType, int In1DataType>
1078 struct Evaluator<OP_SUBTRACT_FROM, In0DataType, In1DataType>
1080 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1082 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1083 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1084 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1085 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
1086 evalCtx.color.xyz() = reduceToVec3(in0 - in1);
1090 template <int In0DataType, int In1DataType>
1091 struct Evaluator<OP_MULTIPLY_INTO, In0DataType, In1DataType>
1093 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1095 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1096 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1097 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1098 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
1099 evalCtx.color.xyz() = reduceToVec3(in0 * in1);
1103 template <int In0DataType, int In1DataType>
1104 struct Evaluator<OP_DIVIDE_INTO, In0DataType, In1DataType>
1106 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1108 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1109 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0);
1110 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1111 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1);
1112 evalCtx.color.xyz() = reduceToVec3(in0 / in1);
1116 MatrixShaderEvalFunc getEvalFunc (const ShaderInput& in0, const ShaderInput& in1, MatrixOp op)
1118 // Evaluator is selected based on op and input data types.
1119 // For efficient lookup the types and op enums are packed together to form a 19-bit key:
1120 // [18..14 OP] [13..7 TYPE0] [6..0 TYPE1]
1122 DE_STATIC_ASSERT(TYPE_LAST <= (1<<7));
1123 DE_STATIC_ASSERT(OP_LAST <= (1<<5));
1125 #define PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE) (((OP) << 14) | ((IN0DATATYPE) << 7) | (IN1DATATYPE))
1127 #define MAKE_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE) \
1128 case PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE): \
1129 return Evaluator<OP, IN0DATATYPE, IN1DATATYPE>::evaluate
1131 #define MAKE_SCALAR_OPS(IN0DATATYPE, IN1DATATYPE) \
1132 MAKE_EVAL_CASE(OP_ADD, IN0DATATYPE, IN1DATATYPE); \
1133 MAKE_EVAL_CASE(OP_SUB, IN0DATATYPE, IN1DATATYPE); \
1134 MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE); \
1135 MAKE_EVAL_CASE(OP_DIV, IN0DATATYPE, IN1DATATYPE)
1137 #define MAKE_CWISE_OPS(IN0DATATYPE, IN1DATATYPE) \
1138 MAKE_EVAL_CASE(OP_ADD, IN0DATATYPE, IN1DATATYPE); \
1139 MAKE_EVAL_CASE(OP_SUB, IN0DATATYPE, IN1DATATYPE); \
1140 MAKE_EVAL_CASE(OP_DIV, IN0DATATYPE, IN1DATATYPE); \
1141 MAKE_EVAL_CASE(OP_COMP_MUL, IN0DATATYPE, IN1DATATYPE)
1143 #define MAKE_MUL_OP(IN0DATATYPE, IN1DATATYPE) \
1144 MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE)
1146 #define MAKE_VECVEC_OP(IN0DATATYPE, IN1DATATYPE) \
1147 MAKE_EVAL_CASE(OP_OUTER_PRODUCT, IN0DATATYPE, IN1DATATYPE)
1149 #define MAKE_UNARY_OP(IN0DATATYPE) \
1150 MAKE_EVAL_CASE(OP_TRANSPOSE, IN0DATATYPE, TYPE_LAST); \
1151 MAKE_EVAL_CASE(OP_UNARY_PLUS, IN0DATATYPE, TYPE_LAST); \
1152 MAKE_EVAL_CASE(OP_NEGATION, IN0DATATYPE, TYPE_LAST); \
1153 MAKE_EVAL_CASE(OP_PRE_INCREMENT, IN0DATATYPE, TYPE_LAST); \
1154 MAKE_EVAL_CASE(OP_PRE_DECREMENT, IN0DATATYPE, TYPE_LAST); \
1155 MAKE_EVAL_CASE(OP_POST_INCREMENT, IN0DATATYPE, TYPE_LAST); \
1156 MAKE_EVAL_CASE(OP_POST_DECREMENT, IN0DATATYPE, TYPE_LAST)
1158 #define MAKE_UNARY_SYMMETRIC_OP(IN0DATATYPE) \
1159 MAKE_UNARY_OP(IN0DATATYPE); \
1160 MAKE_EVAL_CASE(OP_DETERMINANT, IN0DATATYPE, TYPE_LAST); \
1161 MAKE_EVAL_CASE(OP_INVERSE, IN0DATATYPE, TYPE_LAST)
1163 #define MAKE_ASSIGNMENT_OP(IN0DATATYPE) \
1164 MAKE_EVAL_CASE(OP_ADD_INTO, IN0DATATYPE, IN0DATATYPE); \
1165 MAKE_EVAL_CASE(OP_SUBTRACT_FROM, IN0DATATYPE, IN0DATATYPE); \
1166 MAKE_EVAL_CASE(OP_DIVIDE_INTO, IN0DATATYPE, IN0DATATYPE)
1168 #define MAKE_ASSIGNMENT_SYMMETRIC_OP(IN0DATATYPE) \
1169 MAKE_ASSIGNMENT_OP(IN0DATATYPE); \
1170 MAKE_EVAL_CASE(OP_MULTIPLY_INTO, IN0DATATYPE, IN0DATATYPE)
1172 switch (PACK_EVAL_CASE(op, in0.dataType, in1.dataType))
1175 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2, TYPE_FLOAT);
1176 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X3, TYPE_FLOAT);
1177 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X4, TYPE_FLOAT);
1178 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X2, TYPE_FLOAT);
1179 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3, TYPE_FLOAT);
1180 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X4, TYPE_FLOAT);
1181 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X2, TYPE_FLOAT);
1182 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X3, TYPE_FLOAT);
1183 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4, TYPE_FLOAT);
1186 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_VEC2);
1187 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_VEC2);
1188 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_VEC2);
1189 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_VEC3);
1190 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_VEC3);
1191 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_VEC3);
1192 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_VEC4);
1193 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_VEC4);
1194 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_VEC4);
1197 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT2);
1198 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT2X3);
1199 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT2X4);
1200 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT3X2);
1201 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT3);
1202 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT3X4);
1203 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT4X2);
1204 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT4X3);
1205 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT4);
1208 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT2);
1209 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT2);
1210 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT3X2);
1211 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT4X2);
1213 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2X3);
1214 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2);
1215 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT3X2);
1216 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT4X2);
1218 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT2X4);
1219 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT2);
1220 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT3X2);
1221 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT4X2);
1223 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3X2);
1224 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT2X3);
1225 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3);
1226 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT4X3);
1228 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT3);
1229 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT2X3);
1230 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT3);
1231 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT4X3);
1233 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT3X4);
1234 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT2X3);
1235 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT3);
1236 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT4X3);
1238 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4X2);
1239 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT2X4);
1240 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT3X4);
1241 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4);
1243 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4X3);
1244 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT2X4);
1245 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT3X4);
1246 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4);
1248 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT4);
1249 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT2X4);
1250 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT3X4);
1251 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT4);
1254 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC2);
1255 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3);
1256 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC4);
1257 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC2);
1258 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC3);
1259 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4);
1260 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC2);
1261 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC3);
1262 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4);
1265 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT2);
1266 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X3);
1267 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X4);
1268 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X2);
1269 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT3);
1270 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X4);
1271 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X2);
1272 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X3);
1273 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT4);
1276 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT2);
1277 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X3);
1278 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X4);
1279 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X2);
1280 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT3);
1281 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X4);
1282 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X2);
1283 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X3);
1284 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT4);
1287 DE_ASSERT(DE_FALSE);
1291 #undef PACK_EVAL_CASE
1292 #undef MAKE_EVAL_CASE
1295 #undef MAKE_MAT_SCALAR_VEC_CASES
1296 #undef MAKE_MAT_MAT_CASES
1299 // Shader source format utilities.
1302 void writeVectorConstructor (std::ostream& str, const tcu::Vector<float, Size>& v)
1304 str << "vec" << Size << "(";
1305 for (int ndx = 0; ndx < Size; ndx++)
1309 str << de::floatToString(v[ndx], 1);
1314 template <int Cols, int Rows>
1315 void writeMatrixConstructor (std::ostream& str, const tcu::Matrix<float, Rows, Cols>& m)
1318 str << "mat" << Cols;
1320 str << "mat" << Cols << "x" << Rows;
1323 for (int colNdx = 0; colNdx < Cols; colNdx++)
1325 for (int rowNdx = 0; rowNdx < Rows; rowNdx++)
1327 if (rowNdx > 0 || colNdx > 0)
1329 str << de::floatToString(m(rowNdx, colNdx), 1);
1335 } // MatrixCaseUtils
1337 using namespace MatrixCaseUtils;
1339 class MatrixShaderEvaluator : public ShaderEvaluator
1342 MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1);
1344 virtual void evaluate (ShaderEvalContext& evalCtx) const;
1347 MatrixShaderEvalFunc m_matEvalFunc;
1348 InputType m_inType0;
1349 InputType m_inType1;
1352 MatrixShaderEvaluator::MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1)
1353 : m_matEvalFunc (evalFunc)
1354 , m_inType0 (inType0)
1355 , m_inType1 (inType1)
1359 void MatrixShaderEvaluator::evaluate (ShaderEvalContext& evalCtx) const
1361 m_matEvalFunc(evalCtx, m_inType0, m_inType1);
1365 BaseAttributeType getAttributeType(const glu::DataType dataType)
1369 case TYPE_FLOAT_MAT2: return MAT2;
1370 case TYPE_FLOAT_MAT2X3: return MAT2x3;
1371 case TYPE_FLOAT_MAT2X4: return MAT2x4;
1372 case TYPE_FLOAT_MAT3X2: return MAT3x2;
1373 case TYPE_FLOAT_MAT3: return MAT3;
1374 case TYPE_FLOAT_MAT3X4: return MAT3x4;
1375 case TYPE_FLOAT_MAT4X2: return MAT4x2;
1376 case TYPE_FLOAT_MAT4X3: return MAT4x3;
1377 case TYPE_FLOAT_MAT4: return MAT4;
1379 TCU_THROW(InternalError, "Not supported");
1383 // ShaderMatrixInstance
1385 class ShaderMatrixInstance : public ShaderRenderCaseInstance
1388 ShaderMatrixInstance (Context& context,
1390 const ShaderEvaluator& evaluator,
1391 const ShaderInput in0,
1392 const ShaderInput in1,
1393 const MatrixOp m_op);
1394 virtual ~ShaderMatrixInstance (void);
1397 virtual void setupUniforms (const tcu::Vec4&);
1400 void addMatrixUniform (deUint32 bindingLocation, DataType dataType, const float* dataPtr);
1402 const ShaderInput m_in0;
1403 const ShaderInput m_in1;
1404 const MatrixOp m_op;
1407 ShaderMatrixInstance::ShaderMatrixInstance (Context& context,
1409 const ShaderEvaluator& evaluator,
1410 const ShaderInput in0,
1411 const ShaderInput in1,
1413 : ShaderRenderCaseInstance (context, isVertex, evaluator, DE_NULL, DE_NULL, IMAGE_BACKING_MODE_REGULAR, isVertex && op == OP_INVERSE ? 64 : GRID_SIZE_DEFAULTS)
1418 m_userAttribTransforms.resize(4);
1419 for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1421 m_userAttribTransforms[attribNdx] = Mat4(0.0f);
1422 m_userAttribTransforms[attribNdx]( 0, 3) = (op == OP_INVERSE ? -0.5f : 0.2f); // prevent matrix*vec from going into zero (assuming vec.w != 0).
1423 m_userAttribTransforms[attribNdx]( 1, 3) = (op == OP_INVERSE ? -1.3f : 0.1f); // Modified input for OP_INVERSE case, as determinant of final input
1424 m_userAttribTransforms[attribNdx]( 2, 3) = 0.4f + 0.15f * float(attribNdx); // matrix is spanning both sides of 0, so 0 (and division by 0) may happen on mediump.
1425 m_userAttribTransforms[attribNdx]( 3, 3) = (op == OP_INVERSE ? -3.0f : 0.7f); // Modified OP_INVERSE final input matrix is same signed in whole input range.
1426 m_userAttribTransforms[attribNdx]((0 + attribNdx) % 4, 0) = 1.0f;
1427 m_userAttribTransforms[attribNdx]((1 + attribNdx) % 4, 1) = 1.0f;
1428 m_userAttribTransforms[attribNdx]((2 + attribNdx) % 4, 2) = 1.0f;
1429 m_userAttribTransforms[attribNdx]((3 + attribNdx) % 4, 3) = 1.0f;
1432 // prevent bad reference cases such as black result images by fine-tuning used matrices
1433 if (getOperationTestMatrixType(m_op) != TESTMATRIXTYPE_DEFAULT)
1435 for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1437 for (int row = 0; row < 4; row++)
1438 for (int col = 0; col < 4; col++)
1440 switch (getOperationTestMatrixType(m_op))
1442 case TESTMATRIXTYPE_NEGATED:
1443 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col);
1445 case TESTMATRIXTYPE_INCREMENTED:
1446 m_userAttribTransforms[attribNdx](row, col) += 0.3f;
1448 case TESTMATRIXTYPE_DECREMENTED:
1449 m_userAttribTransforms[attribNdx](row, col) -= 0.3f;
1451 case TESTMATRIXTYPE_NEGATED_INCREMENTED:
1452 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col) + 0.3f;
1454 case TESTMATRIXTYPE_INCREMENTED_LESS:
1455 m_userAttribTransforms[attribNdx](row, col) -= 0.1f;
1459 DE_ASSERT(DE_FALSE);
1466 int numInputs = isOperationBinary(m_op) ? 2 : 1;
1468 for (int inNdx = 0; inNdx < numInputs; inNdx++)
1470 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1472 if (in.inputType == INPUTTYPE_DYNAMIC && isDataTypeMatrix(in.dataType))
1474 useAttribute(4u + inNdx, getAttributeType(in.dataType));
1480 ShaderMatrixInstance::~ShaderMatrixInstance (void)
1484 void ShaderMatrixInstance::addMatrixUniform(deUint32 bindingLocation, DataType dataType, const float *dataPtr)
1487 const size_t matrixSize = sizeof(float) * 4 * 4;
1491 case TYPE_FLOAT_MAT2:
1493 Mat2 matrix = Mat2(dataPtr);
1494 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1495 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1498 case TYPE_FLOAT_MAT2X3:
1500 Mat2x3 matrix = Mat2x3(dataPtr);
1501 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1502 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1505 case TYPE_FLOAT_MAT2X4:
1507 Mat2x4 matrix = Mat2x4(dataPtr);
1508 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1509 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1512 case TYPE_FLOAT_MAT3X2:
1514 Mat3x2 matrix = Mat3x2(dataPtr);
1515 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1516 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1517 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1520 case TYPE_FLOAT_MAT3:
1522 Mat3 matrix = Mat3(dataPtr);
1523 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1524 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1525 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1528 case TYPE_FLOAT_MAT3X4:
1530 Mat3x4 matrix = Mat3x4(dataPtr);
1531 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1532 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1533 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1536 case TYPE_FLOAT_MAT4X2:
1538 Mat4x2 matrix = Mat4x2(dataPtr);
1539 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1540 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1541 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1542 result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1545 case TYPE_FLOAT_MAT4X3:
1547 Mat4x3 matrix = Mat4x3(dataPtr);
1548 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1549 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1550 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1551 result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1554 case TYPE_FLOAT_MAT4:
1556 Mat4 matrix = Mat4(dataPtr);
1557 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1558 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1559 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1560 result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1568 addUniform(bindingLocation, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, matrixSize, result.getColumnMajorData().getPtr());
1571 void ShaderMatrixInstance::setupUniforms (const tcu::Vec4&)
1573 const int numInputs = isOperationBinary(m_op) ? 2 : 1;
1574 deUint32 uniformBinding = 0;
1576 for (int inNdx = 0; inNdx < numInputs; inNdx++)
1578 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1580 if (in.inputType == INPUTTYPE_UNIFORM)
1582 switch (in.dataType)
1584 case TYPE_FLOAT: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(float), &s_constInFloat[inNdx]); break;
1585 case TYPE_FLOAT_VEC2: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec2[inNdx]); break;
1586 case TYPE_FLOAT_VEC3: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec3[inNdx]); break;
1587 case TYPE_FLOAT_VEC4: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec4[inNdx]); break;
1588 // \note GLES3 supports transpose in matrix upload.
1589 case TYPE_FLOAT_MAT2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x2[inNdx]); break;
1590 case TYPE_FLOAT_MAT2X3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x3[inNdx]); break;
1591 case TYPE_FLOAT_MAT2X4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x4[inNdx]); break;
1592 case TYPE_FLOAT_MAT3X2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x2[inNdx]); break;
1593 case TYPE_FLOAT_MAT3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x3[inNdx]); break;
1594 case TYPE_FLOAT_MAT3X4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x4[inNdx]); break;
1595 case TYPE_FLOAT_MAT4X2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x2[inNdx]); break;
1596 case TYPE_FLOAT_MAT4X3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x3[inNdx]); break;
1597 case TYPE_FLOAT_MAT4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x4[inNdx]); break;
1608 class ShaderMatrixCase : public ShaderRenderCase
1611 ShaderMatrixCase (tcu::TestContext& testCtx,
1612 const std::string& name,
1613 const std::string& desc,
1614 const ShaderInput& in0,
1615 const ShaderInput& in1,
1618 ~ShaderMatrixCase (void);
1620 virtual TestInstance* createInstance (Context& context) const;
1623 void setupShader (void);
1624 std::string genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName);
1627 const ShaderInput m_in0;
1628 const ShaderInput m_in1;
1629 const MatrixOp m_op;
1632 ShaderMatrixCase::ShaderMatrixCase (tcu::TestContext& testCtx,
1633 const std::string& name,
1634 const std::string& desc,
1635 const ShaderInput& in0,
1636 const ShaderInput& in1,
1639 : ShaderRenderCase (testCtx,
1643 new MatrixShaderEvaluator(getEvalFunc(in0, in1, op), in0.inputType, in1.inputType),
1644 DE_NULL /* uniform setup */,
1645 DE_NULL /* attribute setup */)
1653 ShaderMatrixCase::~ShaderMatrixCase (void)
1657 TestInstance* ShaderMatrixCase::createInstance (Context& context) const
1659 return new ShaderMatrixInstance(context, m_isVertexCase, *m_evaluator, m_in0, m_in1, m_op);
1662 void ShaderMatrixCase::setupShader (void)
1664 std::ostringstream vtx;
1665 std::ostringstream frag;
1666 std::ostringstream& op = m_isVertexCase ? vtx : frag;
1668 bool isInDynMat0 = isDataTypeMatrix(m_in0.dataType) && m_in0.inputType == INPUTTYPE_DYNAMIC;
1669 bool isInDynMat1 = isDataTypeMatrix(m_in1.dataType) && m_in1.inputType == INPUTTYPE_DYNAMIC;
1672 DataType resultType = TYPE_LAST;
1673 Precision resultPrec = m_in0.precision;
1674 vector<string> passVars;
1675 int numInputs = (isOperationBinary(m_op)) ? (2) : (1);
1677 std::string operationValue0;
1678 std::string operationValue1;
1680 DE_ASSERT(!isInDynMat0 || !isInDynMat1); // Only single dynamic matrix input is allowed.
1681 DE_UNREF(isInDynMat0 && isInDynMat1);
1683 // Compute result type.
1684 if (m_op == OP_MUL && isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1686 resultType = getDataTypeMatrix(getDataTypeMatrixNumColumns(m_in1.dataType), getDataTypeMatrixNumRows(m_in0.dataType));
1688 else if (m_op == OP_OUTER_PRODUCT)
1690 resultType = getDataTypeMatrix(getDataTypeScalarSize(m_in1.dataType), getDataTypeScalarSize(m_in0.dataType));
1692 else if (m_op == OP_TRANSPOSE)
1694 resultType = getDataTypeMatrix(getDataTypeMatrixNumRows(m_in0.dataType), getDataTypeMatrixNumColumns(m_in0.dataType));
1696 else if (m_op == OP_INVERSE)
1698 resultType = m_in0.dataType;
1700 else if (m_op == OP_DETERMINANT)
1702 resultType = TYPE_FLOAT;
1704 else if (getOperationType(m_op) == OPERATIONTYPE_UNARY_PREFIX_OPERATOR ||
1705 getOperationType(m_op) == OPERATIONTYPE_UNARY_POSTFIX_OPERATOR)
1707 resultType = m_in0.dataType;
1709 else if (isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1711 DE_ASSERT(m_in0.dataType == m_in1.dataType);
1712 resultType = m_in0.dataType;
1714 else if (isDataTypeMatrix(m_in0.dataType) || isDataTypeMatrix(m_in1.dataType))
1716 int matNdx = isDataTypeMatrix(m_in0.dataType) ? 0 : 1;
1717 DataType matrixType = matNdx == 0 ? m_in0.dataType : m_in1.dataType;
1718 DataType otherType = matNdx == 0 ? m_in1.dataType : m_in0.dataType;
1720 if (otherType == TYPE_FLOAT)
1721 resultType = matrixType;
1724 DE_ASSERT(isDataTypeVector(otherType));
1725 resultType = getDataTypeFloatVec(matNdx == 0 ? getDataTypeMatrixNumRows(matrixType) : getDataTypeMatrixNumColumns(matrixType));
1730 DE_ASSERT(DE_FALSE);
1733 static const std::string header =
1734 "#version 310 es\n";
1739 vtx << "layout(location = 0) in highp vec4 a_position;\n";
1740 frag << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1743 vtx << "layout(location = 0) out mediump vec4 v_color;\n";
1744 frag << "layout(location = 0) in mediump vec4 v_color;\n";
1747 // Input declarations.
1748 deUint32 uniformBinding = 0;
1749 deUint32 padding = 0;
1750 for (int inNdx = 0; inNdx < numInputs; inNdx++)
1752 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1753 const char* precName = getPrecisionName(in.precision);
1754 const char* typeName = getDataTypeName(in.dataType);
1755 string& inValue = inNdx > 0 ? inValue1 : inValue0;
1757 if (in.inputType == INPUTTYPE_DYNAMIC)
1759 if (isDataTypeMatrix(in.dataType))
1761 vtx << "layout(location = " << 4 + inNdx + padding << ") in " << precName << " " << typeName << " a_";
1763 vtx << typeName << ";\n";
1764 if (!m_isVertexCase)
1766 vtx << "layout(location = " << 1 + inNdx + padding << ") out " << precName << " " << typeName << " v_" << typeName << ";\n";
1767 frag << "layout(location = " << 1 + inNdx + padding << ") in " << precName << " " << typeName << " v_" << typeName << ";\n";
1768 passVars.push_back(typeName);
1771 inValue = string(m_isVertexCase ? "a_" : "v_") + getDataTypeName(in.dataType);
1772 padding += getDataTypeMatrixNumColumns(in.dataType);
1776 // a_coords, v_coords
1777 vtx << "layout(location = 1) in " << precName << " " << typeName << " a_coords;\n";
1778 if (!m_isVertexCase)
1780 vtx << "layout(location = " << 1 + padding << ") out " << precName << " " << typeName << " v_coords;\n";
1781 frag << "layout(location = " << 1 + padding << ") in " << precName << " " << typeName << " v_coords;\n";
1782 passVars.push_back("coords");
1785 inValue = m_isVertexCase ? "a_coords" : "v_coords";
1788 else if (in.inputType == INPUTTYPE_UNIFORM)
1790 op << "layout(std140, set = 0, binding = " << uniformBinding++ << ") uniform buffer"<< inNdx <<" { " << precName << " " << typeName << " u_in" << inNdx << "; };\n";
1791 inValue = string("u_in") + de::toString(inNdx);
1793 else if (in.inputType == INPUTTYPE_CONST)
1795 op << "const " << precName << " " << typeName << " in" << inNdx << " = ";
1797 // Generate declaration.
1798 switch (in.dataType)
1800 case TYPE_FLOAT: op << de::floatToString(s_constInFloat[inNdx], 1); break;
1801 case TYPE_FLOAT_VEC2: writeVectorConstructor<2>(op, s_constInVec2[inNdx]); break;
1802 case TYPE_FLOAT_VEC3: writeVectorConstructor<3>(op, s_constInVec3[inNdx]); break;
1803 case TYPE_FLOAT_VEC4: writeVectorConstructor<4>(op, s_constInVec4[inNdx]); break;
1804 case TYPE_FLOAT_MAT2: writeMatrixConstructor<2, 2>(op, Mat2(s_constInMat2x2[inNdx])); break;
1805 case TYPE_FLOAT_MAT2X3: writeMatrixConstructor<2, 3>(op, Mat2x3(s_constInMat2x3[inNdx])); break;
1806 case TYPE_FLOAT_MAT2X4: writeMatrixConstructor<2, 4>(op, Mat2x4(s_constInMat2x4[inNdx])); break;
1807 case TYPE_FLOAT_MAT3X2: writeMatrixConstructor<3, 2>(op, Mat3x2(s_constInMat3x2[inNdx])); break;
1808 case TYPE_FLOAT_MAT3: writeMatrixConstructor<3, 3>(op, Mat3(s_constInMat3x3[inNdx])); break;
1809 case TYPE_FLOAT_MAT3X4: writeMatrixConstructor<3, 4>(op, Mat3x4(s_constInMat3x4[inNdx])); break;
1810 case TYPE_FLOAT_MAT4X2: writeMatrixConstructor<4, 2>(op, Mat4x2(s_constInMat4x2[inNdx])); break;
1811 case TYPE_FLOAT_MAT4X3: writeMatrixConstructor<4, 3>(op, Mat4x3(s_constInMat4x3[inNdx])); break;
1812 case TYPE_FLOAT_MAT4: writeMatrixConstructor<4, 4>(op, Mat4(s_constInMat4x4[inNdx])); break;
1815 DE_ASSERT(DE_FALSE);
1820 inValue = string("in") + de::toString(inNdx);
1825 << "void main (void)\n"
1827 << " gl_Position = a_position;\n";
1829 << "void main (void)\n"
1833 frag << " dEQP_FragColor = v_color;\n";
1836 for (vector<string>::const_iterator copyIter = passVars.begin(); copyIter != passVars.end(); copyIter++)
1837 vtx << " v_" << *copyIter << " = " << "a_" << *copyIter << ";\n";
1842 switch (getOperationNature(m_op))
1844 case OPERATIONNATURE_PURE:
1845 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1847 operationValue0 = inValue0;
1848 operationValue1 = inValue1;
1851 case OPERATIONNATURE_MUTATING:
1852 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1854 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " tmpValue = " << inValue0 << ";\n";
1856 operationValue0 = "tmpValue";
1857 operationValue1 = inValue1;
1860 case OPERATIONNATURE_ASSIGNMENT:
1861 DE_ASSERT(getOperationType(m_op) == OPERATIONTYPE_ASSIGNMENT);
1863 operationValue0 = inValue0;
1864 operationValue1 = inValue1;
1868 DE_ASSERT(DE_FALSE);
1871 switch (getOperationType(m_op))
1873 case OPERATIONTYPE_BINARY_OPERATOR:
1874 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << " " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1877 case OPERATIONTYPE_UNARY_PREFIX_OPERATOR:
1878 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << operationValue0 << ";\n";
1881 case OPERATIONTYPE_UNARY_POSTFIX_OPERATOR:
1882 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << getOperationName(m_op) << ";\n";
1885 case OPERATIONTYPE_BINARY_FUNCTION:
1886 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ", " << operationValue1 << ");\n";
1889 case OPERATIONTYPE_UNARY_FUNCTION:
1890 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ");\n";
1893 case OPERATIONTYPE_ASSIGNMENT:
1894 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << ";\n";
1895 op << " res " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1899 DE_ASSERT(DE_FALSE);
1902 // Reduction to vec3 (rgb). Check the used value too if it was modified
1903 op << " " << (m_isVertexCase ? "v_color" : "dEQP_FragColor") << " = ";
1905 if (isOperationValueModifying(m_op))
1906 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0) + vec4(" << genGLSLMatToVec3Reduction(resultType, "tmpValue") << ", 0.0);\n";
1908 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0);\n";
1913 m_vertShaderSource = vtx.str();
1914 m_fragShaderSource = frag.str();
1917 std::string ShaderMatrixCase::genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName)
1919 std::ostringstream op;
1923 case TYPE_FLOAT: op << varName << ", " << varName << ", " << varName << ""; break;
1924 case TYPE_FLOAT_VEC2: op << varName << ".x, " << varName << ".y, " << varName << ".x"; break;
1925 case TYPE_FLOAT_VEC3: op << varName << ""; break;
1926 case TYPE_FLOAT_VEC4: op << varName << ".x, " << varName << ".y, " << varName << ".z+" << varName << ".w"; break;
1927 case TYPE_FLOAT_MAT2: op << varName << "[0][0], " << varName << "[1][0], " << varName << "[0][1]+" << varName << "[1][1]"; break;
1928 case TYPE_FLOAT_MAT2X3: op << varName << "[0] + " << varName << "[1]"; break;
1929 case TYPE_FLOAT_MAT2X4: op << varName << "[0].xyz + " << varName << "[1].yzw"; break;
1930 case TYPE_FLOAT_MAT3X2: op << varName << "[0][0]+" << varName << "[0][1], " << varName << "[1][0]+" << varName << "[1][1], " << varName << "[2][0]+" << varName << "[2][1]"; break;
1931 case TYPE_FLOAT_MAT3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2]"; break;
1932 case TYPE_FLOAT_MAT3X4: op << varName << "[0].xyz + " << varName << "[1].yzw + " << varName << "[2].zwx"; break;
1933 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;
1934 case TYPE_FLOAT_MAT4X3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2] + " << varName << "[3]"; break;
1935 case TYPE_FLOAT_MAT4: op << varName << "[0].xyz+" << varName << "[1].yzw+" << varName << "[2].zwx+" << varName << "[3].wxy"; break;
1938 DE_ASSERT(DE_FALSE);
1944 class ShaderMatrixTests : public tcu::TestCaseGroup
1947 ShaderMatrixTests (tcu::TestContext& testCtx);
1948 virtual ~ShaderMatrixTests (void);
1950 virtual void init (void);
1953 ShaderMatrixTests (const ShaderMatrixTests&); // not allowed!
1954 ShaderMatrixTests& operator= (const ShaderMatrixTests&); // not allowed!
1957 ShaderMatrixTests::ShaderMatrixTests (tcu::TestContext& testCtx)
1958 : TestCaseGroup(testCtx, "matrix", "Matrix Tests")
1962 ShaderMatrixTests::~ShaderMatrixTests (void)
1966 void ShaderMatrixTests::init (void)
1973 const bool extendedInputTypeCases; // !< test with const and uniform types too
1974 const bool createInputTypeGroup; // !< create group for input types
1977 { "add", "Matrix addition tests", OP_ADD, true, true },
1978 { "sub", "Matrix subtraction tests", OP_SUB, true, true },
1979 { "mul", "Matrix multiplication tests", OP_MUL, true, true },
1980 { "div", "Matrix division tests", OP_DIV, true, true },
1981 { "matrixcompmult", "Matrix component-wise multiplication tests", OP_COMP_MUL, false, true },
1982 { "outerproduct", "Matrix outerProduct() tests", OP_OUTER_PRODUCT, false, true },
1983 { "transpose", "Matrix transpose() tests", OP_TRANSPOSE, false, true },
1984 { "determinant", "Matrix determinant() tests", OP_DETERMINANT, false, true },
1985 { "inverse", "Matrix inverse() tests", OP_INVERSE, false, true },
1986 { "unary_addition", "Matrix unary addition tests", OP_UNARY_PLUS, false, false },
1987 { "negation", "Matrix negation tests", OP_NEGATION, false, false },
1988 { "pre_increment", "Matrix prefix increment tests", OP_PRE_INCREMENT, false, false },
1989 { "pre_decrement", "Matrix prefix decrement tests", OP_PRE_DECREMENT, false, false },
1990 { "post_increment", "Matrix postfix increment tests", OP_POST_INCREMENT, false, false },
1991 { "post_decrement", "Matrix postfix decrement tests", OP_POST_DECREMENT, false, false },
1992 { "add_assign", "Matrix add into tests", OP_ADD_INTO, false, false },
1993 { "sub_assign", "Matrix subtract from tests", OP_SUBTRACT_FROM, false, false },
1994 { "mul_assign", "Matrix multiply into tests", OP_MULTIPLY_INTO, false, false },
1995 { "div_assign", "Matrix divide into tests", OP_DIVIDE_INTO, false, false },
1998 struct InputTypeSpec
2002 const InputType type;
2004 static const InputTypeSpec extendedInputTypes[] =
2006 { "const", "Constant matrix input", INPUTTYPE_CONST },
2007 { "uniform", "Uniform matrix input", INPUTTYPE_UNIFORM },
2008 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC }
2010 static const InputTypeSpec reducedInputTypes[] =
2012 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC }
2015 static const DataType matrixTypes[] =
2028 static const Precision precisions[] =
2034 for (int opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
2036 const InputTypeSpec* inTypeList = (ops[opNdx].extendedInputTypeCases) ? (extendedInputTypes) : (reducedInputTypes);
2037 const int inTypeListSize = (ops[opNdx].extendedInputTypeCases) ? (DE_LENGTH_OF_ARRAY(extendedInputTypes)) : (DE_LENGTH_OF_ARRAY(reducedInputTypes));
2038 const MatrixOp op = ops[opNdx].op;
2039 tcu::TestCaseGroup* opGroup = new tcu::TestCaseGroup(m_testCtx, ops[opNdx].name, ops[opNdx].desc);
2043 for (int inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++)
2045 const InputType inputType = inTypeList[inTypeNdx].type;
2046 tcu::TestCaseGroup* inGroup;
2048 if (ops[opNdx].createInputTypeGroup)
2050 inGroup = new tcu::TestCaseGroup(m_testCtx, inTypeList[inTypeNdx].name, inTypeList[inTypeNdx].desc);
2051 opGroup->addChild(inGroup);
2056 for (int matTypeNdx = 0; matTypeNdx < DE_LENGTH_OF_ARRAY(matrixTypes); matTypeNdx++)
2058 DataType matType = matrixTypes[matTypeNdx];
2059 int numCols = getDataTypeMatrixNumColumns(matType);
2060 int numRows = getDataTypeMatrixNumRows(matType);
2061 const char* matTypeName = getDataTypeName(matType);
2063 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
2065 Precision precision = precisions[precNdx];
2066 const char* precName = getPrecisionName(precision);
2067 string baseName = string(precName) + "_" + matTypeName + "_";
2068 ShaderInput matIn (inputType, matType, precision);
2070 if (isOperationMatrixScalar(op))
2072 // Matrix-scalar \note For div cases we use uniform input.
2073 ShaderInput scalarIn(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, TYPE_FLOAT, precision);
2074 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Matrix-scalar case", matIn, scalarIn, op, true));
2075 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Matrix-scalar case", matIn, scalarIn, op, false));
2078 if (isOperationMatrixVector(op))
2081 DataType colVecType = getDataTypeFloatVec(numCols);
2082 ShaderInput colVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, colVecType, precision);
2084 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_vertex").c_str(), "Matrix-vector case", matIn, colVecIn, op, true));
2085 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_fragment").c_str(), "Matrix-vector case", matIn, colVecIn, op, false));
2088 DataType rowVecType = getDataTypeFloatVec(numRows);
2089 ShaderInput rowVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, rowVecType, precision);
2090 string vecMatName = string(precName) + "_" + getDataTypeName(rowVecType) + "_" + matTypeName;
2092 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_vertex").c_str(), "Vector-matrix case", rowVecIn, matIn, op, true));
2093 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_fragment").c_str(), "Vector-matrix case", rowVecIn, matIn, op, false));
2096 if (isOperationArithmeticMatrixMatrix(op))
2098 // Arithmetic matrix-matrix multiplication.
2099 for (int otherCols = 2; otherCols <= 4; otherCols++)
2101 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, getDataTypeMatrix(otherCols, numCols /* rows */), precision);
2102 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true));
2103 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false));
2106 else if (isOperationComponentwiseMatrixMatrix(op))
2109 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2110 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true));
2111 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false));
2114 if (isOperationVectorVector(op))
2116 ShaderInput vec1In(inputType, getDataTypeFloatVec(numRows), precision);
2117 ShaderInput vec2In((inputType == INPUTTYPE_DYNAMIC) ? (INPUTTYPE_UNIFORM) : (inputType), getDataTypeFloatVec(numCols), precision);
2119 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Vector-vector case", vec1In, vec2In, op, true));
2120 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Vector-vector case", vec1In, vec2In, op, false));
2123 if ((isOperationUnaryAnyMatrix(op)) ||
2124 (isOperationUnarySymmetricMatrix(op) && numCols == numRows))
2126 ShaderInput voidInput(INPUTTYPE_LAST, TYPE_LAST, PRECISION_LAST);
2127 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Matrix case", matIn, voidInput, op, true));
2128 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Matrix case", matIn, voidInput, op, false));
2131 if ((isOperationAssignmentAnyMatrix(op)) ||
2132 (isOperationAssignmentSymmetricMatrix(op) && numCols == numRows))
2134 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2135 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Matrix assignment case", matIn, otherMatIn, op, true));
2136 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Matrix assignment case", matIn, otherMatIn, op, false));
2146 tcu::TestCaseGroup* createMatrixTests (tcu::TestContext& testCtx)
2148 return new ShaderMatrixTests(testCtx);