1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Shader matrix arithmetic tests. 22 * 23 * Variables: 24 * + operation 25 * - mat OP mat 26 * - mat OP vec 27 * - vec OP mat 28 * - mat OP scalar 29 * - OP ( mat ) 30 * - vec OP vec 31 * - OP mat 32 * + matrix source 33 * - constant (ctor) 34 * - uniform 35 * - vertex input 36 * - fragment input 37 * + other operand: always dynamic data? 38 * + how to reduce to vec3? 39 *//*--------------------------------------------------------------------*/ 40 41 #include "es3fShaderMatrixTests.hpp" 42 #include "glsShaderRenderCase.hpp" 43 #include "gluShaderUtil.hpp" 44 #include "tcuVector.hpp" 45 #include "tcuMatrix.hpp" 46 #include "tcuMatrixUtil.hpp" 47 #include "deStringUtil.hpp" 48 49 #include "glwEnums.hpp" 50 #include "glwFunctions.hpp" 51 52 namespace deqp 53 { 54 namespace gles3 55 { 56 namespace Functional 57 { 58 59 using std::string; 60 using std::vector; 61 using namespace glu; 62 using namespace deqp::gls; 63 64 using tcu::Vec2; 65 using tcu::Vec3; 66 using tcu::Vec4; 67 using tcu::Mat2; 68 using tcu::Mat2x3; 69 using tcu::Mat2x4; 70 using tcu::Mat3x2; 71 using tcu::Mat3; 72 using tcu::Mat3x4; 73 using tcu::Mat4x2; 74 using tcu::Mat4x3; 75 using tcu::Mat4; 76 77 // Uniform / constant values for tests. 78 // \note Input1 should not contain 0 components as it is used as divisor in div cases. 79 // \todo [2012-02-14 pyry] Make these dynamic. 80 static const float s_constInFloat[2] = { 0.5f, -0.2f }; 81 static const Vec2 s_constInVec2[2] = { Vec2(1.2f, 0.5f), Vec2(0.5f, 1.0f) }; 82 static const Vec3 s_constInVec3[2] = { Vec3(1.1f, 0.1f, 0.5f), Vec3(-0.2f, 0.5f, 0.8f) }; 83 static const Vec4 s_constInVec4[2] = { Vec4(1.4f, 0.2f, -0.5f, 0.7f), Vec4(0.2f, -1.0f, 0.5f, 0.8f) }; 84 85 static const float s_constInMat2x2[2][4] = 86 { 87 { 88 -0.1f, 1.0f, 89 -0.2f, 0.0f, 90 }, 91 { 92 0.8f, 0.1f, 93 0.5f, -0.9f, 94 }, 95 }; 96 static const float s_constInMat3x2[2][6] = 97 { 98 { 99 0.8f, -0.3f, 0.3f, 100 1.0f, 1.2f, -1.2f, 101 }, 102 { 103 1.2f, -1.0f, 0.5f, 104 -0.8f, 1.1f, 0.3f, 105 }, 106 }; 107 static const float s_constInMat4x2[2][8] = 108 { 109 { 110 -0.2f, 0.5f, 0.0f, -1.0f, 111 1.2f, -0.5f, 0.3f, -0.9f, 112 }, 113 { 114 1.0f, 0.1f, -1.1f, 0.6f, 115 0.8f, -1.2f, -1.1f, 0.7f, 116 }, 117 }; 118 static const float s_constInMat2x3[2][6] = 119 { 120 { 121 -0.6f, -0.1f, 122 -0.7f, -1.2f, 123 -0.2f, 0.0f, 124 }, 125 { 126 1.1f, 0.6f, 127 0.8f, 1.0f, 128 0.7f, 0.1f, 129 }, 130 }; 131 static const float s_constInMat3x3[2][9] = 132 { 133 { 134 -0.2f, 1.1f, 1.2f, 135 -1.0f, 1.2f, 0.5f, 136 0.7f, -0.2f, 1.0f, 137 }, 138 { 139 -0.1f, -0.1f, 0.1f, 140 -0.1f, -0.2f, 1.0f, 141 -0.5f, 0.1f, -0.4f, 142 }, 143 }; 144 static const float s_constInMat4x3[2][12] = 145 { 146 { 147 -0.9f, 0.0f, 0.6f, 0.2f, 148 0.9f, -0.1f, -0.3f, -0.7f, 149 -0.1f, 0.1f, 1.0f, 0.0f, 150 }, 151 { 152 0.5f, 0.7f, 0.7f, 1.2f, 153 1.1f, 0.1f, 1.0f, -1.0f, 154 -0.2f, -0.2f, -0.3f, -0.5f, 155 }, 156 }; 157 static const float s_constInMat2x4[2][8] = 158 { 159 { 160 -0.6f, -1.1f, 161 -0.6f, -0.6f, 162 -0.2f, -0.6f, 163 -0.1f, -0.1f, 164 }, 165 { 166 -1.2f, -1.0f, 167 0.7f, -1.0f, 168 0.7f, 0.7f, 169 -0.4f, -0.3f, 170 }, 171 }; 172 static const float s_constInMat3x4[2][12] = 173 { 174 { 175 0.6f, -0.4f, 1.2f, 176 0.9f, 0.8f, 0.4f, 177 1.1f, 0.3f, 0.5f, 178 -0.2f, 0.0f, 1.1f, 179 }, 180 { 181 -0.8f, 1.2f, -0.2f, 182 -1.1f, -0.9f, -0.5f, 183 -1.2f, 1.0f, 1.2f, 184 0.1f, -0.7f, -0.5f, 185 }, 186 }; 187 static const float s_constInMat4x4[2][16] = 188 { 189 { 190 0.3f, 0.9f, -0.2f, 1.0f, 191 -0.4f, -0.6f, 0.6f, -1.0f, 192 -0.9f, -0.1f, 0.3f, -0.2f, 193 -0.3f, -0.9f, 1.0f, 0.1f, 194 }, 195 { 196 0.4f, -0.7f, -0.8f, 0.7f, 197 -0.4f, -0.8f, 0.6f, -0.3f, 198 0.7f, -1.0f, 0.1f, -0.3f, 199 0.2f, 0.6f, 0.4f, -1.0f, 200 }, 201 }; 202 203 namespace MatrixCaseUtils 204 { 205 206 enum InputType 207 { 208 INPUTTYPE_CONST = 0, 209 INPUTTYPE_UNIFORM, 210 INPUTTYPE_DYNAMIC, 211 212 INPUTTYPE_LAST 213 }; 214 215 struct ShaderInput 216 { 217 ShaderInput (InputType inputType_, DataType dataType_, Precision precision_) 218 : inputType (inputType_) 219 , dataType (dataType_) 220 , precision (precision_) 221 { 222 } 223 224 InputType inputType; 225 DataType dataType; 226 Precision precision; 227 }; 228 229 enum MatrixOp 230 { 231 OP_ADD = 0, 232 OP_SUB, 233 OP_MUL, 234 OP_DIV, 235 OP_COMP_MUL, 236 OP_OUTER_PRODUCT, 237 OP_TRANSPOSE, 238 OP_INVERSE, 239 OP_DETERMINANT, 240 OP_UNARY_PLUS, 241 OP_NEGATION, 242 OP_PRE_INCREMENT, 243 OP_PRE_DECREMENT, 244 OP_POST_INCREMENT, 245 OP_POST_DECREMENT, 246 OP_ADD_INTO, 247 OP_SUBTRACT_FROM, 248 OP_MULTIPLY_INTO, 249 OP_DIVIDE_INTO, 250 OP_LAST 251 }; 252 253 // Type traits. 254 255 template <int DataT> 256 struct TypeTraits; 257 258 #define DECLARE_TYPE_TRAIT(DATATYPE, TYPE) \ 259 template<> \ 260 struct TypeTraits<DATATYPE> { \ 261 typedef TYPE Type; \ 262 } 263 264 DECLARE_TYPE_TRAIT(TYPE_FLOAT, float); 265 DECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC2, tcu::Vec2); 266 DECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC3, tcu::Vec3); 267 DECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC4, tcu::Vec4); 268 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT2, tcu::Mat2); 269 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT2X3, tcu::Mat2x3); 270 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT2X4, tcu::Mat2x4); 271 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT3X2, tcu::Mat3x2); 272 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT3, tcu::Mat3); 273 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT3X4, tcu::Mat3x4); 274 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT4X2, tcu::Mat4x2); 275 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT4X3, tcu::Mat4x3); 276 DECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT4, tcu::Mat4); 277 278 // Operation info 279 280 enum OperationType 281 { 282 OPERATIONTYPE_BINARY_OPERATOR = 0, 283 OPERATIONTYPE_BINARY_FUNCTION, 284 OPERATIONTYPE_UNARY_PREFIX_OPERATOR, 285 OPERATIONTYPE_UNARY_POSTFIX_OPERATOR, 286 OPERATIONTYPE_UNARY_FUNCTION, 287 OPERATIONTYPE_ASSIGNMENT, 288 289 OPERATIONTYPE_LAST 290 }; 291 292 static const char* getOperationName (MatrixOp op) 293 { 294 switch (op) 295 { 296 case OP_ADD: return "+"; 297 case OP_SUB: return "-"; 298 case OP_MUL: return "*"; 299 case OP_DIV: return "/"; 300 case OP_COMP_MUL: return "matrixCompMult"; 301 case OP_OUTER_PRODUCT: return "outerProduct"; 302 case OP_TRANSPOSE: return "transpose"; 303 case OP_INVERSE: return "inverse"; 304 case OP_DETERMINANT: return "determinant"; 305 case OP_UNARY_PLUS: return "+"; 306 case OP_NEGATION: return "-"; 307 case OP_PRE_INCREMENT: return "++"; 308 case OP_PRE_DECREMENT: return "--"; 309 case OP_POST_INCREMENT: return "++"; 310 case OP_POST_DECREMENT: return "--"; 311 case OP_ADD_INTO: return "+="; 312 case OP_SUBTRACT_FROM: return "-="; 313 case OP_MULTIPLY_INTO: return "*="; 314 case OP_DIVIDE_INTO: return "/="; 315 316 default: 317 DE_ASSERT(DE_FALSE); 318 return ""; 319 } 320 } 321 322 static OperationType getOperationType (MatrixOp op) 323 { 324 switch (op) 325 { 326 case OP_ADD: return OPERATIONTYPE_BINARY_OPERATOR; 327 case OP_SUB: return OPERATIONTYPE_BINARY_OPERATOR; 328 case OP_MUL: return OPERATIONTYPE_BINARY_OPERATOR; 329 case OP_DIV: return OPERATIONTYPE_BINARY_OPERATOR; 330 case OP_COMP_MUL: return OPERATIONTYPE_BINARY_FUNCTION; 331 case OP_OUTER_PRODUCT: return OPERATIONTYPE_BINARY_FUNCTION; 332 case OP_TRANSPOSE: return OPERATIONTYPE_UNARY_FUNCTION; 333 case OP_INVERSE: return OPERATIONTYPE_UNARY_FUNCTION; 334 case OP_DETERMINANT: return OPERATIONTYPE_UNARY_FUNCTION; 335 case OP_UNARY_PLUS: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR; 336 case OP_NEGATION: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR; 337 case OP_PRE_INCREMENT: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR; 338 case OP_PRE_DECREMENT: return OPERATIONTYPE_UNARY_PREFIX_OPERATOR; 339 case OP_POST_INCREMENT: return OPERATIONTYPE_UNARY_POSTFIX_OPERATOR; 340 case OP_POST_DECREMENT: return OPERATIONTYPE_UNARY_POSTFIX_OPERATOR; 341 case OP_ADD_INTO: return OPERATIONTYPE_ASSIGNMENT; 342 case OP_SUBTRACT_FROM: return OPERATIONTYPE_ASSIGNMENT; 343 case OP_MULTIPLY_INTO: return OPERATIONTYPE_ASSIGNMENT; 344 case OP_DIVIDE_INTO: return OPERATIONTYPE_ASSIGNMENT; 345 default: 346 DE_ASSERT(DE_FALSE); 347 return OPERATIONTYPE_LAST; 348 } 349 } 350 351 enum TestMatrixType 352 { 353 TESTMATRIXTYPE_DEFAULT = 0, 354 TESTMATRIXTYPE_NEGATED, 355 TESTMATRIXTYPE_INCREMENTED, 356 TESTMATRIXTYPE_DECREMENTED, 357 TESTMATRIXTYPE_NEGATED_INCREMENTED, 358 TESTMATRIXTYPE_INCREMENTED_LESS, 359 360 TESTMATRIXTYPE_LAST 361 }; 362 363 static TestMatrixType getOperationTestMatrixType (MatrixOp op) 364 { 365 switch(op) 366 { 367 case OP_ADD: return TESTMATRIXTYPE_DEFAULT; 368 case OP_SUB: return TESTMATRIXTYPE_DEFAULT; 369 case OP_MUL: return TESTMATRIXTYPE_DEFAULT; 370 case OP_DIV: return TESTMATRIXTYPE_DEFAULT; 371 case OP_COMP_MUL: return TESTMATRIXTYPE_DEFAULT; 372 case OP_OUTER_PRODUCT: return TESTMATRIXTYPE_DEFAULT; 373 case OP_TRANSPOSE: return TESTMATRIXTYPE_DEFAULT; 374 case OP_INVERSE: return TESTMATRIXTYPE_DEFAULT; 375 case OP_DETERMINANT: return TESTMATRIXTYPE_DEFAULT; 376 case OP_UNARY_PLUS: return TESTMATRIXTYPE_DECREMENTED; 377 case OP_NEGATION: return TESTMATRIXTYPE_NEGATED_INCREMENTED; 378 case OP_PRE_INCREMENT: return TESTMATRIXTYPE_NEGATED; 379 case OP_PRE_DECREMENT: return TESTMATRIXTYPE_INCREMENTED; 380 case OP_POST_INCREMENT: return TESTMATRIXTYPE_NEGATED; 381 case OP_POST_DECREMENT: return TESTMATRIXTYPE_DEFAULT; 382 case OP_ADD_INTO: return TESTMATRIXTYPE_DEFAULT; 383 case OP_SUBTRACT_FROM: return TESTMATRIXTYPE_INCREMENTED_LESS; 384 case OP_MULTIPLY_INTO: return TESTMATRIXTYPE_NEGATED; 385 case OP_DIVIDE_INTO: return TESTMATRIXTYPE_DECREMENTED; 386 387 default: 388 DE_ASSERT(DE_FALSE); 389 return TESTMATRIXTYPE_LAST; 390 } 391 } 392 393 static bool isOperationBinary (MatrixOp op) 394 { 395 return getOperationType(op) == OPERATIONTYPE_BINARY_OPERATOR || 396 getOperationType(op) == OPERATIONTYPE_BINARY_FUNCTION || 397 getOperationType(op) == OPERATIONTYPE_ASSIGNMENT; 398 } 399 400 static bool isOperationMatrixScalar (MatrixOp op) 401 { 402 return op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV; 403 } 404 405 static bool isOperationMatrixVector (MatrixOp op) 406 { 407 return op == OP_MUL; 408 } 409 410 static bool isOperationArithmeticMatrixMatrix (MatrixOp op) 411 { 412 return op == OP_MUL; 413 } 414 415 static bool isOperationComponentwiseMatrixMatrix (MatrixOp op) 416 { 417 return op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV || op == OP_COMP_MUL; 418 } 419 420 static bool isOperationVectorVector (MatrixOp op) 421 { 422 return op == OP_OUTER_PRODUCT; 423 } 424 425 static bool isOperationUnaryAnyMatrix (MatrixOp op) 426 { 427 return op == OP_TRANSPOSE || 428 op == OP_UNARY_PLUS || 429 op == OP_NEGATION || 430 op == OP_PRE_INCREMENT || 431 op == OP_PRE_DECREMENT || 432 op == OP_POST_INCREMENT || 433 op == OP_POST_DECREMENT; 434 } 435 436 static bool isOperationUnarySymmetricMatrix (MatrixOp op) 437 { 438 return op == OP_INVERSE || op == OP_DETERMINANT; 439 } 440 441 static bool isOperationValueModifying (MatrixOp op) 442 { 443 return op == OP_PRE_INCREMENT || 444 op == OP_PRE_DECREMENT || 445 op == OP_POST_INCREMENT || 446 op == OP_POST_DECREMENT; 447 } 448 449 static bool isOperationAssignment (MatrixOp op) 450 { 451 return op == OP_ADD_INTO || 452 op == OP_SUBTRACT_FROM || 453 op == OP_MULTIPLY_INTO || 454 op == OP_DIVIDE_INTO; 455 } 456 457 static bool isOperationAssignmentAnyMatrix (MatrixOp op) 458 { 459 return op == OP_ADD_INTO || 460 op == OP_SUBTRACT_FROM || 461 op == OP_DIVIDE_INTO; 462 } 463 464 static bool isOperationAssignmentSymmetricMatrix (MatrixOp op) 465 { 466 return op == OP_MULTIPLY_INTO; 467 } 468 469 // Operation nature 470 471 enum OperationNature 472 { 473 OPERATIONNATURE_PURE = 0, 474 OPERATIONNATURE_MUTATING, 475 OPERATIONNATURE_ASSIGNMENT, 476 477 OPERATIONNATURE_LAST 478 }; 479 480 static OperationNature getOperationNature (MatrixOp op) 481 { 482 if (isOperationAssignment(op)) 483 return OPERATIONNATURE_ASSIGNMENT; 484 485 if (isOperationValueModifying(op)) 486 return OPERATIONNATURE_MUTATING; 487 488 return OPERATIONNATURE_PURE; 489 } 490 491 // Input value loader. 492 493 template <int InputT, int DataT> 494 typename TypeTraits<DataT>::Type getInputValue (const ShaderEvalContext& evalCtx, int inputNdx); 495 496 template <> inline float getInputValue<INPUTTYPE_CONST, TYPE_FLOAT> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInFloat[inputNdx]; } 497 template <> inline tcu::Vec2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_VEC2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec2[inputNdx]; } 498 template <> inline tcu::Vec3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_VEC3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec3[inputNdx]; } 499 template <> inline tcu::Vec4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_VEC4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec4[inputNdx]; } 500 501 template <> inline tcu::Mat2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat2(s_constInMat2x2[inputNdx]); } 502 template <> inline tcu::Mat2x3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT2X3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat2x3(s_constInMat2x3[inputNdx]); } 503 template <> inline tcu::Mat2x4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT2X4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat2x4(s_constInMat2x4[inputNdx]); } 504 template <> inline tcu::Mat3x2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT3X2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat3x2(s_constInMat3x2[inputNdx]); } 505 template <> inline tcu::Mat3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat3(s_constInMat3x3[inputNdx]); } 506 template <> inline tcu::Mat3x4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT3X4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat3x4(s_constInMat3x4[inputNdx]); } 507 template <> inline tcu::Mat4x2 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT4X2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat4x2(s_constInMat4x2[inputNdx]); } 508 template <> inline tcu::Mat4x3 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT4X3> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat4x3(s_constInMat4x3[inputNdx]); } 509 template <> inline tcu::Mat4 getInputValue<INPUTTYPE_CONST, TYPE_FLOAT_MAT4> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return tcu::Mat4(s_constInMat4x4[inputNdx]); } 510 511 template <> inline float getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.x(); } 512 template <> inline tcu::Vec2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_VEC2> (const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.swizzle(0, 1); } 513 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); } 514 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); } 515 516 template <> inline tcu::Mat2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT2> (const ShaderEvalContext& evalCtx, int inputNdx) 517 { 518 DE_UNREF(inputNdx); // Not used. 519 tcu::Mat2 m; 520 m.setColumn(0, evalCtx.in[0].swizzle(0,1)); 521 m.setColumn(1, evalCtx.in[1].swizzle(0,1)); 522 return m; 523 } 524 525 template <> inline tcu::Mat2x3 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT2X3> (const ShaderEvalContext& evalCtx, int inputNdx) 526 { 527 DE_UNREF(inputNdx); // Not used. 528 tcu::Mat2x3 m; 529 m.setColumn(0, evalCtx.in[0].swizzle(0,1,2)); 530 m.setColumn(1, evalCtx.in[1].swizzle(0,1,2)); 531 return m; 532 } 533 534 template <> inline tcu::Mat2x4 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT2X4> (const ShaderEvalContext& evalCtx, int inputNdx) 535 { 536 DE_UNREF(inputNdx); // Not used. 537 tcu::Mat2x4 m; 538 m.setColumn(0, evalCtx.in[0]); 539 m.setColumn(1, evalCtx.in[1]); 540 return m; 541 } 542 543 template <> inline tcu::Mat3x2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT3X2> (const ShaderEvalContext& evalCtx, int inputNdx) 544 { 545 DE_UNREF(inputNdx); // Not used. 546 tcu::Mat3x2 m; 547 m.setColumn(0, evalCtx.in[0].swizzle(0,1)); 548 m.setColumn(1, evalCtx.in[1].swizzle(0,1)); 549 m.setColumn(2, evalCtx.in[2].swizzle(0,1)); 550 return m; 551 } 552 553 template <> inline tcu::Mat3 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT3> (const ShaderEvalContext& evalCtx, int inputNdx) 554 { 555 DE_UNREF(inputNdx); // Not used. 556 tcu::Mat3 m; 557 m.setColumn(0, evalCtx.in[0].swizzle(0,1,2)); 558 m.setColumn(1, evalCtx.in[1].swizzle(0,1,2)); 559 m.setColumn(2, evalCtx.in[2].swizzle(0,1,2)); 560 return m; 561 } 562 563 template <> inline tcu::Mat3x4 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT3X4> (const ShaderEvalContext& evalCtx, int inputNdx) 564 { 565 DE_UNREF(inputNdx); // Not used. 566 tcu::Mat3x4 m; 567 m.setColumn(0, evalCtx.in[0]); 568 m.setColumn(1, evalCtx.in[1]); 569 m.setColumn(2, evalCtx.in[2]); 570 return m; 571 } 572 573 template <> inline tcu::Mat4x2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT4X2> (const ShaderEvalContext& evalCtx, int inputNdx) 574 { 575 DE_UNREF(inputNdx); // Not used. 576 tcu::Mat4x2 m; 577 m.setColumn(0, evalCtx.in[0].swizzle(0,1)); 578 m.setColumn(1, evalCtx.in[1].swizzle(0,1)); 579 m.setColumn(2, evalCtx.in[2].swizzle(0,1)); 580 m.setColumn(3, evalCtx.in[3].swizzle(0,1)); 581 return m; 582 } 583 584 template <> inline tcu::Mat4x3 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT4X3> (const ShaderEvalContext& evalCtx, int inputNdx) 585 { 586 DE_UNREF(inputNdx); // Not used. 587 tcu::Mat4x3 m; 588 m.setColumn(0, evalCtx.in[0].swizzle(0,1,2)); 589 m.setColumn(1, evalCtx.in[1].swizzle(0,1,2)); 590 m.setColumn(2, evalCtx.in[2].swizzle(0,1,2)); 591 m.setColumn(3, evalCtx.in[3].swizzle(0,1,2)); 592 return m; 593 } 594 595 template <> inline tcu::Mat4 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT4> (const ShaderEvalContext& evalCtx, int inputNdx) 596 { 597 DE_UNREF(inputNdx); // Not used. 598 tcu::Mat4 m; 599 m.setColumn(0, evalCtx.in[0]); 600 m.setColumn(1, evalCtx.in[1]); 601 m.setColumn(2, evalCtx.in[2]); 602 m.setColumn(3, evalCtx.in[3]); 603 return m; 604 } 605 606 // Reduction from expression result to vec3. 607 608 inline tcu::Vec3 reduceToVec3 (const tcu::Vec2& value) { return value.swizzle(0,1,0); } 609 inline tcu::Vec3 reduceToVec3 (const tcu::Vec3& value) { return value; } 610 inline tcu::Vec3 reduceToVec3 (const tcu::Vec4& value) { return tcu::Vec3(value.x(), value.y(), value.z()+value.w()); } 611 inline tcu::Vec3 reduceToVec3 (const tcu::Mat2& value) { return tcu::Vec3(value(0, 0), value(0, 1), value(1, 0)+value(1, 1)); } 612 inline tcu::Vec3 reduceToVec3 (const tcu::Mat2x3& value) { return value.getColumn(0) + value.getColumn(1); } 613 inline tcu::Vec3 reduceToVec3 (const tcu::Mat2x4& value) { return value.getColumn(0).swizzle(0,1,2) + value.getColumn(1).swizzle(1,2,3); } 614 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)); } 615 inline tcu::Vec3 reduceToVec3 (const tcu::Mat3& value) { return value.getColumn(0) + value.getColumn(1) + value.getColumn(2); } 616 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); } 617 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)); } 618 inline tcu::Vec3 reduceToVec3 (const tcu::Mat4x3& value) { return value.getColumn(0) + value.getColumn(1) + value.getColumn(2) + value.getColumn(3); } 619 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); } 620 621 // matrixCompMult 622 623 template <typename T, int Rows, int Cols> 624 tcu::Matrix<T, Rows, Cols> matrixCompMult (const tcu::Matrix<T, Rows, Cols>& a, const tcu::Matrix<T, Rows, Cols>& b) 625 { 626 tcu::Matrix<T, Rows, Cols> retVal; 627 628 for (int r = 0; r < Rows; ++r) 629 for (int c = 0; c < Cols; ++c) 630 retVal(r,c) = a(r,c) * b(r, c); 631 632 return retVal; 633 } 634 635 // transpose 636 637 template <typename T, int Rows, int Cols> 638 tcu::Matrix<T, Cols, Rows> transpose (const tcu::Matrix<T, Rows, Cols>& mat) 639 { 640 tcu::Matrix<T, Cols, Rows> retVal; 641 642 for (int r = 0; r < Rows; ++r) 643 for (int c = 0; c < Cols; ++c) 644 retVal(c, r) = mat(r, c); 645 646 return retVal; 647 } 648 649 // outerProduct 650 651 template <typename T, int Rows, int Cols> 652 tcu::Matrix<T, Cols, Rows> outerProduct (const tcu::Vector<T, Cols>& a, const tcu::Vector<T, Rows>& b) 653 { 654 tcu::Matrix<T, Rows, Cols> retVal; 655 656 for (int r = 0; r < Rows; ++r) 657 for (int c = 0; c < Cols; ++c) 658 retVal(r,c) = a[c] * b[r]; 659 660 return transpose(retVal); // to gl-form (column-major) 661 } 662 663 // Determinant 664 665 template <int Size> 666 float determinant (const tcu::Matrix<float, Size, Size>& mat); 667 668 template <> 669 float determinant<2> (const tcu::Matrix<float, 2, 2>& mat) 670 { 671 return mat(0,0) * mat(1,1) - mat(1,0) * mat(0,1); 672 } 673 674 template <> 675 float determinant<3> (const tcu::Matrix<float, 3, 3>& mat) 676 { 677 return + mat(0,0) * mat(1,1) * mat(2,2) 678 + mat(0,1) * mat(1,2) * mat(2,0) 679 + mat(0,2) * mat(1,0) * mat(2,1) 680 - mat(0,0) * mat(1,2) * mat(2,1) 681 - mat(0,1) * mat(1,0) * mat(2,2) 682 - mat(0,2) * mat(1,1) * mat(2,0); 683 } 684 685 template <> 686 float determinant<4> (const tcu::Matrix<float, 4, 4>& mat) 687 { 688 const float minorMatrices[4][3*3] = 689 { 690 { 691 mat(1,1), mat(2,1), mat(3,1), 692 mat(1,2), mat(2,2), mat(3,2), 693 mat(1,3), mat(2,3), mat(3,3), 694 }, 695 { 696 mat(1,0), mat(2,0), mat(3,0), 697 mat(1,2), mat(2,2), mat(3,2), 698 mat(1,3), mat(2,3), mat(3,3), 699 }, 700 { 701 mat(1,0), mat(2,0), mat(3,0), 702 mat(1,1), mat(2,1), mat(3,1), 703 mat(1,3), mat(2,3), mat(3,3), 704 }, 705 { 706 mat(1,0), mat(2,0), mat(3,0), 707 mat(1,1), mat(2,1), mat(3,1), 708 mat(1,2), mat(2,2), mat(3,2), 709 } 710 }; 711 712 return + mat(0,0) * determinant(tcu::Mat3(minorMatrices[0])) 713 - mat(0,1) * determinant(tcu::Mat3(minorMatrices[1])) 714 + mat(0,2) * determinant(tcu::Mat3(minorMatrices[2])) 715 - mat(0,3) * determinant(tcu::Mat3(minorMatrices[3])); 716 } 717 718 // Inverse 719 720 template <int Size> 721 tcu::Matrix<float, Size, Size> inverse (const tcu::Matrix<float, Size, Size>& mat); 722 723 template <> 724 tcu::Matrix<float, 2, 2> inverse<2> (const tcu::Matrix<float, 2, 2>& mat) 725 { 726 const float det = determinant(mat); 727 tcu::Matrix<float, 2, 2> retVal; 728 729 DE_ASSERT(det != 0.0f); 730 731 retVal(0, 0) = mat(1, 1) / det; 732 retVal(0, 1) = -mat(0, 1) / det; 733 retVal(1, 0) = -mat(1, 0) / det; 734 retVal(1, 1) = mat(0, 0) / det; 735 736 return retVal; 737 } 738 739 template <> 740 tcu::Matrix<float, 3, 3> inverse<3> (const tcu::Matrix<float, 3, 3>& mat) 741 { 742 // Blockwise inversion 743 744 DE_ASSERT(determinant(mat) != 0.0f); 745 746 const float areaA[2*2] = 747 { 748 mat(0,0), mat(0,1), 749 mat(1,0), mat(1,1) 750 }; 751 const float areaB[2] = 752 { 753 mat(0,2), 754 mat(1,2), 755 }; 756 const float areaC[2] = 757 { 758 mat(2,0), mat(2,1), 759 }; 760 const float areaD[1] = 761 { 762 mat(2,2) 763 }; 764 const float nullField[4] = { 0.0f }; 765 766 const tcu::Matrix<float, 2, 2> invA = inverse(tcu::Matrix<float, 2, 2>(areaA)); 767 const tcu::Matrix<float, 2, 1> matB = tcu::Matrix<float, 2, 1>(areaB); 768 const tcu::Matrix<float, 1, 2> matC = tcu::Matrix<float, 1, 2>(areaC); 769 const tcu::Matrix<float, 1, 1> matD = tcu::Matrix<float, 1, 1>(areaD); 770 771 const float schurComplement = 1.0f / (matD - matC*invA*matB)(0,0); 772 const tcu::Matrix<float, 2, 2> zeroMat = Mat2(nullField); 773 774 const tcu::Matrix<float, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA; 775 const tcu::Matrix<float, 2, 1> blockB = (zeroMat-invA)*matB*schurComplement; 776 const tcu::Matrix<float, 1, 2> blockC = matC*invA*(-schurComplement); 777 const float blockD = schurComplement; 778 779 const float result[3*3] = 780 { 781 blockA(0,0), blockA(0,1), blockB(0,0), 782 blockA(1,0), blockA(1,1), blockB(1,0), 783 blockC(0,0), blockC(0,1), blockD, 784 }; 785 786 return Mat3(result); 787 } 788 789 template <> 790 tcu::Matrix<float, 4, 4> inverse<4> (const tcu::Matrix<float, 4, 4>& mat) 791 { 792 // Blockwise inversion 793 794 DE_ASSERT(determinant(mat) != 0.0f); 795 796 const float areaA[2*2] = 797 { 798 mat(0,0), mat(0,1), 799 mat(1,0), mat(1,1) 800 }; 801 const float areaB[2*2] = 802 { 803 mat(0,2), mat(0,3), 804 mat(1,2), mat(1,3) 805 }; 806 const float areaC[2*2] = 807 { 808 mat(2,0), mat(2,1), 809 mat(3,0), mat(3,1) 810 }; 811 const float areaD[2*2] = 812 { 813 mat(2,2), mat(2,3), 814 mat(3,2), mat(3,3) 815 }; 816 const float nullField[4] = { 0.0f }; 817 818 const tcu::Matrix<float, 2, 2> invA = inverse(Mat2(areaA)); 819 const tcu::Matrix<float, 2, 2> matB = Mat2(areaB); 820 const tcu::Matrix<float, 2, 2> matC = Mat2(areaC); 821 const tcu::Matrix<float, 2, 2> matD = Mat2(areaD); 822 823 const tcu::Matrix<float, 2, 2> schurComplement = inverse(matD - matC*invA*matB); 824 const tcu::Matrix<float, 2, 2> zeroMat = Mat2(nullField); 825 826 const tcu::Matrix<float, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA; 827 const tcu::Matrix<float, 2, 2> blockB = (zeroMat-invA)*matB*schurComplement; 828 const tcu::Matrix<float, 2, 2> blockC = (zeroMat-schurComplement)*matC*invA; 829 const tcu::Matrix<float, 2, 2> blockD = schurComplement; 830 831 const float result[4*4] = 832 { 833 blockA(0,0), blockA(0,1), blockB(0,0), blockB(0,1), 834 blockA(1,0), blockA(1,1), blockB(1,0), blockB(1,1), 835 blockC(0,0), blockC(0,1), blockD(0,0), blockD(0,1), 836 blockC(1,0), blockC(1,1), blockD(1,0), blockD(1,1), 837 }; 838 839 return Mat4(result); 840 } 841 842 // negate 843 844 template <typename T, int Rows, int Cols> 845 tcu::Matrix<T, Rows, Cols> negate (const tcu::Matrix<T, Rows, Cols>& mat) 846 { 847 tcu::Matrix<T, Rows, Cols> retVal; 848 849 for (int r = 0; r < Rows; ++r) 850 for (int c = 0; c < Cols; ++c) 851 retVal(r,c) = -mat(r, c); 852 853 return retVal; 854 } 855 856 // increment/decrement 857 858 template <typename T, int Rows, int Cols> 859 tcu::Matrix<T, Rows, Cols> increment (const tcu::Matrix<T, Rows, Cols>& mat) 860 { 861 tcu::Matrix<T, Rows, Cols> retVal; 862 863 for (int r = 0; r < Rows; ++r) 864 for (int c = 0; c < Cols; ++c) 865 retVal(r,c) = mat(r, c) + 1.0f; 866 867 return retVal; 868 } 869 870 template <typename T, int Rows, int Cols> 871 tcu::Matrix<T, Rows, Cols> decrement (const tcu::Matrix<T, Rows, Cols>& mat) 872 { 873 tcu::Matrix<T, Rows, Cols> retVal; 874 875 for (int r = 0; r < Rows; ++r) 876 for (int c = 0; c < Cols; ++c) 877 retVal(r,c) = mat(r, c) - 1.0f; 878 879 return retVal; 880 } 881 882 // Evaluator template. 883 884 typedef void (*MatrixShaderEvalFunc) (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type); 885 886 template <int Op, int In0DataType, int In1DataType> 887 struct Evaluator; 888 889 template <int In0DataType, int In1DataType> 890 struct Evaluator<OP_ADD, In0DataType, In1DataType> 891 { 892 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 893 { 894 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 895 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 896 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 897 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 898 evalCtx.color.xyz() = reduceToVec3(in0 + in1); 899 } 900 }; 901 902 template <int In0DataType, int In1DataType> 903 struct Evaluator<OP_SUB, In0DataType, In1DataType> 904 { 905 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 906 { 907 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 908 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 909 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 910 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 911 evalCtx.color.xyz() = reduceToVec3(in0 - in1); 912 } 913 }; 914 915 template <int In0DataType, int In1DataType> 916 struct Evaluator<OP_MUL, In0DataType, In1DataType> 917 { 918 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 919 { 920 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 921 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 922 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 923 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 924 evalCtx.color.xyz() = reduceToVec3(in0 * in1); 925 } 926 }; 927 928 template <int In0DataType, int In1DataType> 929 struct Evaluator<OP_DIV, In0DataType, In1DataType> 930 { 931 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 932 { 933 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 934 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 935 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 936 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 937 evalCtx.color.xyz() = reduceToVec3(in0 / in1); 938 } 939 }; 940 941 template <int In0DataType, int In1DataType> 942 struct Evaluator<OP_COMP_MUL, In0DataType, In1DataType> 943 { 944 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 945 { 946 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 947 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 948 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 949 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 950 evalCtx.color.xyz() = reduceToVec3(matrixCompMult(in0, in1)); 951 } 952 }; 953 954 template <int In0DataType, int In1DataType> 955 struct Evaluator<OP_OUTER_PRODUCT, In0DataType, In1DataType> 956 { 957 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 958 { 959 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 960 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 961 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 962 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 963 evalCtx.color.xyz() = reduceToVec3(outerProduct(in0, in1)); 964 } 965 }; 966 967 template <int In0DataType, int In1DataType> 968 struct Evaluator<OP_TRANSPOSE, In0DataType, In1DataType> 969 { 970 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 971 { 972 DE_UNREF(in1Type); 973 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 974 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 975 evalCtx.color.xyz() = reduceToVec3(transpose(in0)); 976 } 977 }; 978 979 template <int In0DataType, int In1DataType> 980 struct Evaluator<OP_INVERSE, In0DataType, In1DataType> 981 { 982 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 983 { 984 DE_UNREF(in1Type); 985 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 986 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 987 evalCtx.color.xyz() = reduceToVec3(inverse(in0)); 988 } 989 }; 990 991 template <int In0DataType, int In1DataType> 992 struct Evaluator<OP_DETERMINANT, In0DataType, In1DataType> 993 { 994 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 995 { 996 DE_UNREF(in1Type); 997 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 998 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 999 evalCtx.color.xyz() = Vec3(determinant(in0)); 1000 } 1001 }; 1002 1003 template <int In0DataType, int In1DataType> 1004 struct Evaluator<OP_UNARY_PLUS, In0DataType, In1DataType> 1005 { 1006 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1007 { 1008 DE_UNREF(in1Type); 1009 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1010 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1011 evalCtx.color.xyz() = reduceToVec3(in0); 1012 } 1013 }; 1014 1015 template <int In0DataType, int In1DataType> 1016 struct Evaluator<OP_NEGATION, In0DataType, In1DataType> 1017 { 1018 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1019 { 1020 DE_UNREF(in1Type); 1021 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1022 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1023 evalCtx.color.xyz() = reduceToVec3(negate(in0)); 1024 } 1025 }; 1026 1027 template <int In0DataType, int In1DataType> 1028 struct Evaluator<OP_PRE_INCREMENT, In0DataType, In1DataType> 1029 { 1030 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1031 { 1032 DE_UNREF(in1Type); 1033 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1034 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1035 1036 // modifying reduction: sum modified value too 1037 evalCtx.color.xyz() = reduceToVec3(increment(in0)) + reduceToVec3(increment(in0)); 1038 } 1039 }; 1040 1041 template <int In0DataType, int In1DataType> 1042 struct Evaluator<OP_PRE_DECREMENT, In0DataType, In1DataType> 1043 { 1044 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1045 { 1046 DE_UNREF(in1Type); 1047 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1048 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1049 1050 // modifying reduction: sum modified value too 1051 evalCtx.color.xyz() = reduceToVec3(decrement(in0)) + reduceToVec3(decrement(in0)); 1052 } 1053 }; 1054 1055 template <int In0DataType, int In1DataType> 1056 struct Evaluator<OP_POST_INCREMENT, In0DataType, In1DataType> 1057 { 1058 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1059 { 1060 DE_UNREF(in1Type); 1061 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1062 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1063 1064 // modifying reduction: sum modified value too 1065 evalCtx.color.xyz() = reduceToVec3(in0) + reduceToVec3(increment(in0)); 1066 } 1067 }; 1068 1069 template <int In0DataType, int In1DataType> 1070 struct Evaluator<OP_POST_DECREMENT, In0DataType, In1DataType> 1071 { 1072 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1073 { 1074 DE_UNREF(in1Type); 1075 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1076 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1077 1078 // modifying reduction: sum modified value too 1079 evalCtx.color.xyz() = reduceToVec3(in0) + reduceToVec3(decrement(in0)); 1080 } 1081 }; 1082 1083 template <int In0DataType, int In1DataType> 1084 struct Evaluator<OP_ADD_INTO, In0DataType, In1DataType> 1085 { 1086 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1087 { 1088 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1089 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1090 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 1091 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 1092 evalCtx.color.xyz() = reduceToVec3(in0 + in1); 1093 } 1094 }; 1095 1096 template <int In0DataType, int In1DataType> 1097 struct Evaluator<OP_SUBTRACT_FROM, In0DataType, In1DataType> 1098 { 1099 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1100 { 1101 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1102 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1103 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 1104 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 1105 evalCtx.color.xyz() = reduceToVec3(in0 - in1); 1106 } 1107 }; 1108 1109 template <int In0DataType, int In1DataType> 1110 struct Evaluator<OP_MULTIPLY_INTO, In0DataType, In1DataType> 1111 { 1112 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1113 { 1114 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1115 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1116 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 1117 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 1118 evalCtx.color.xyz() = reduceToVec3(in0 * in1); 1119 } 1120 }; 1121 1122 template <int In0DataType, int In1DataType> 1123 struct Evaluator<OP_DIVIDE_INTO, In0DataType, In1DataType> 1124 { 1125 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1126 { 1127 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1128 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1129 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 1130 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 1131 evalCtx.color.xyz() = reduceToVec3(in0 / in1); 1132 } 1133 }; 1134 1135 MatrixShaderEvalFunc getEvalFunc (const ShaderInput& in0, const ShaderInput& in1, MatrixOp op) 1136 { 1137 // Evaluator is selected based on op and input data types. 1138 // For efficient lookup the types and op enums are packed together to form a 19-bit key: 1139 // [18..14 OP] [13..7 TYPE0] [6..0 TYPE1] 1140 1141 DE_STATIC_ASSERT(TYPE_LAST <= (1<<7)); 1142 DE_STATIC_ASSERT(OP_LAST <= (1<<5)); 1143 1144 #define PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE) (((OP) << 14) | ((IN0DATATYPE) << 7) | (IN1DATATYPE)) 1145 1146 #define MAKE_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE) \ 1147 case PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE): \ 1148 return Evaluator<OP, IN0DATATYPE, IN1DATATYPE>::evaluate 1149 1150 #define MAKE_SCALAR_OPS(IN0DATATYPE, IN1DATATYPE) \ 1151 MAKE_EVAL_CASE(OP_ADD, IN0DATATYPE, IN1DATATYPE); \ 1152 MAKE_EVAL_CASE(OP_SUB, IN0DATATYPE, IN1DATATYPE); \ 1153 MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE); \ 1154 MAKE_EVAL_CASE(OP_DIV, IN0DATATYPE, IN1DATATYPE) 1155 1156 #define MAKE_CWISE_OPS(IN0DATATYPE, IN1DATATYPE) \ 1157 MAKE_EVAL_CASE(OP_ADD, IN0DATATYPE, IN1DATATYPE); \ 1158 MAKE_EVAL_CASE(OP_SUB, IN0DATATYPE, IN1DATATYPE); \ 1159 MAKE_EVAL_CASE(OP_DIV, IN0DATATYPE, IN1DATATYPE); \ 1160 MAKE_EVAL_CASE(OP_COMP_MUL, IN0DATATYPE, IN1DATATYPE) 1161 1162 #define MAKE_MUL_OP(IN0DATATYPE, IN1DATATYPE) \ 1163 MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE) 1164 1165 #define MAKE_VECVEC_OP(IN0DATATYPE, IN1DATATYPE) \ 1166 MAKE_EVAL_CASE(OP_OUTER_PRODUCT, IN0DATATYPE, IN1DATATYPE) 1167 1168 #define MAKE_UNARY_OP(IN0DATATYPE) \ 1169 MAKE_EVAL_CASE(OP_TRANSPOSE, IN0DATATYPE, TYPE_LAST); \ 1170 MAKE_EVAL_CASE(OP_UNARY_PLUS, IN0DATATYPE, TYPE_LAST); \ 1171 MAKE_EVAL_CASE(OP_NEGATION, IN0DATATYPE, TYPE_LAST); \ 1172 MAKE_EVAL_CASE(OP_PRE_INCREMENT, IN0DATATYPE, TYPE_LAST); \ 1173 MAKE_EVAL_CASE(OP_PRE_DECREMENT, IN0DATATYPE, TYPE_LAST); \ 1174 MAKE_EVAL_CASE(OP_POST_INCREMENT, IN0DATATYPE, TYPE_LAST); \ 1175 MAKE_EVAL_CASE(OP_POST_DECREMENT, IN0DATATYPE, TYPE_LAST) 1176 1177 #define MAKE_UNARY_SYMMETRIC_OP(IN0DATATYPE) \ 1178 MAKE_UNARY_OP(IN0DATATYPE); \ 1179 MAKE_EVAL_CASE(OP_DETERMINANT, IN0DATATYPE, TYPE_LAST); \ 1180 MAKE_EVAL_CASE(OP_INVERSE, IN0DATATYPE, TYPE_LAST) 1181 1182 #define MAKE_ASSIGNMENT_OP(IN0DATATYPE) \ 1183 MAKE_EVAL_CASE(OP_ADD_INTO, IN0DATATYPE, IN0DATATYPE); \ 1184 MAKE_EVAL_CASE(OP_SUBTRACT_FROM, IN0DATATYPE, IN0DATATYPE); \ 1185 MAKE_EVAL_CASE(OP_DIVIDE_INTO, IN0DATATYPE, IN0DATATYPE) 1186 1187 #define MAKE_ASSIGNMENT_SYMMETRIC_OP(IN0DATATYPE) \ 1188 MAKE_ASSIGNMENT_OP(IN0DATATYPE); \ 1189 MAKE_EVAL_CASE(OP_MULTIPLY_INTO, IN0DATATYPE, IN0DATATYPE) 1190 1191 switch (PACK_EVAL_CASE(op, in0.dataType, in1.dataType)) 1192 { 1193 // Matrix-scalar. 1194 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2, TYPE_FLOAT); 1195 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X3, TYPE_FLOAT); 1196 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X4, TYPE_FLOAT); 1197 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X2, TYPE_FLOAT); 1198 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3, TYPE_FLOAT); 1199 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X4, TYPE_FLOAT); 1200 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X2, TYPE_FLOAT); 1201 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X3, TYPE_FLOAT); 1202 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4, TYPE_FLOAT); 1203 1204 // Matrix-vector. 1205 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_VEC2); 1206 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_VEC2); 1207 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_VEC2); 1208 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_VEC3); 1209 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_VEC3); 1210 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_VEC3); 1211 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_VEC4); 1212 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_VEC4); 1213 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_VEC4); 1214 1215 // Vector-matrix. 1216 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT2); 1217 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT2X3); 1218 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT2X4); 1219 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT3X2); 1220 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT3); 1221 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT3X4); 1222 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT4X2); 1223 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT4X3); 1224 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT4); 1225 1226 // Matrix-matrix. 1227 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT2); 1228 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT2); 1229 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT3X2); 1230 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT4X2); 1231 1232 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2X3); 1233 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2); 1234 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT3X2); 1235 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT4X2); 1236 1237 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT2X4); 1238 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT2); 1239 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT3X2); 1240 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT4X2); 1241 1242 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3X2); 1243 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT2X3); 1244 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3); 1245 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT4X3); 1246 1247 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT3); 1248 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT2X3); 1249 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT3); 1250 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT4X3); 1251 1252 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT3X4); 1253 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT2X3); 1254 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT3); 1255 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT4X3); 1256 1257 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4X2); 1258 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT2X4); 1259 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT3X4); 1260 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4); 1261 1262 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4X3); 1263 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT2X4); 1264 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT3X4); 1265 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4); 1266 1267 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT4); 1268 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT2X4); 1269 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT3X4); 1270 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT4); 1271 1272 // Vector-vector. 1273 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC2); 1274 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3); 1275 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC4); 1276 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC2); 1277 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC3); 1278 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4); 1279 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC2); 1280 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC3); 1281 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4); 1282 1283 // Unary Matrix. 1284 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT2); 1285 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X3); 1286 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X4); 1287 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X2); 1288 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT3); 1289 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X4); 1290 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X2); 1291 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X3); 1292 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT4); 1293 1294 // Assignments 1295 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT2); 1296 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X3); 1297 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X4); 1298 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X2); 1299 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT3); 1300 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X4); 1301 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X2); 1302 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X3); 1303 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT4); 1304 1305 default: 1306 DE_ASSERT(DE_FALSE); 1307 return DE_NULL; 1308 } 1309 1310 #undef PACK_EVAL_CASE 1311 #undef MAKE_EVAL_CASE 1312 #undef MUL_OP 1313 #undef ALL_OPS 1314 #undef MAKE_MAT_SCALAR_VEC_CASES 1315 #undef MAKE_MAT_MAT_CASES 1316 } 1317 1318 // Shader source format utilities. 1319 1320 template <int Size> 1321 void writeVectorConstructor (std::ostream& str, const tcu::Vector<float, Size>& v) 1322 { 1323 str << "vec" << Size << "("; 1324 for (int ndx = 0; ndx < Size; ndx++) 1325 { 1326 if (ndx != 0) 1327 str << ", "; 1328 str << de::floatToString(v[ndx], 1); 1329 } 1330 str << ")"; 1331 } 1332 1333 template <int Cols, int Rows> 1334 void writeMatrixConstructor (std::ostream& str, const tcu::Matrix<float, Rows, Cols>& m) 1335 { 1336 if (Rows == Cols) 1337 str << "mat" << Cols; 1338 else 1339 str << "mat" << Cols << "x" << Rows; 1340 1341 str << "("; 1342 for (int colNdx = 0; colNdx < Cols; colNdx++) 1343 { 1344 for (int rowNdx = 0; rowNdx < Rows; rowNdx++) 1345 { 1346 if (rowNdx > 0 || colNdx > 0) 1347 str << ", "; 1348 str << de::floatToString(m(rowNdx, colNdx), 1); 1349 } 1350 } 1351 str << ")"; 1352 } 1353 1354 } // MatrixCaseUtils 1355 1356 using namespace MatrixCaseUtils; 1357 1358 class MatrixShaderEvaluator : public ShaderEvaluator 1359 { 1360 public: 1361 MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1); 1362 1363 virtual void evaluate (ShaderEvalContext& evalCtx); 1364 1365 private: 1366 MatrixShaderEvalFunc m_matEvalFunc; 1367 InputType m_inType0; 1368 InputType m_inType1; 1369 }; 1370 1371 MatrixShaderEvaluator::MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1) 1372 : m_matEvalFunc (evalFunc) 1373 , m_inType0 (inType0) 1374 , m_inType1 (inType1) 1375 { 1376 } 1377 1378 void MatrixShaderEvaluator::evaluate (ShaderEvalContext& evalCtx) 1379 { 1380 m_matEvalFunc(evalCtx, m_inType0, m_inType1); 1381 } 1382 1383 class ShaderMatrixCase : public ShaderRenderCase 1384 { 1385 public: 1386 ShaderMatrixCase (Context& context, const char* name, const char* desc, const ShaderInput& in0, const ShaderInput& in1, MatrixOp op, bool isVertexCase); 1387 ~ShaderMatrixCase (void); 1388 1389 void init (void); 1390 1391 protected: 1392 std::string genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName); 1393 void setupUniforms (int programID, const tcu::Vec4& constCoords); 1394 1395 private: 1396 ShaderInput m_in0; 1397 ShaderInput m_in1; 1398 MatrixOp m_op; 1399 MatrixShaderEvaluator m_matEvaluator; 1400 }; 1401 1402 ShaderMatrixCase::ShaderMatrixCase (Context& context, const char* name, const char* desc, const ShaderInput& in0, const ShaderInput& in1, MatrixOp op, bool isVertexCase) 1403 : ShaderRenderCase (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_matEvaluator) 1404 , m_in0 (in0) 1405 , m_in1 (in1) 1406 , m_op (op) 1407 , m_matEvaluator (getEvalFunc(in0, in1, op), in0.inputType, in1.inputType) 1408 { 1409 } 1410 1411 ShaderMatrixCase::~ShaderMatrixCase (void) 1412 { 1413 } 1414 1415 void ShaderMatrixCase::init (void) 1416 { 1417 std::ostringstream vtx; 1418 std::ostringstream frag; 1419 std::ostringstream& op = m_isVertexCase ? vtx : frag; 1420 1421 bool isInDynMat0 = isDataTypeMatrix(m_in0.dataType) && m_in0.inputType == INPUTTYPE_DYNAMIC; 1422 bool isInDynMat1 = isDataTypeMatrix(m_in1.dataType) && m_in1.inputType == INPUTTYPE_DYNAMIC; 1423 string inValue0; 1424 string inValue1; 1425 DataType resultType = TYPE_LAST; 1426 Precision resultPrec = m_in0.precision; 1427 vector<string> passVars; 1428 int numInputs = (isOperationBinary(m_op)) ? (2) : (1); 1429 1430 std::string operationValue0; 1431 std::string operationValue1; 1432 1433 DE_ASSERT(!isInDynMat0 || !isInDynMat1); // Only single dynamic matrix input is allowed. 1434 DE_UNREF(isInDynMat0 && isInDynMat1); 1435 1436 // Compute result type. 1437 if (m_op == OP_MUL && isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType)) 1438 { 1439 resultType = getDataTypeMatrix(getDataTypeMatrixNumColumns(m_in1.dataType), getDataTypeMatrixNumRows(m_in0.dataType)); 1440 } 1441 else if (m_op == OP_OUTER_PRODUCT) 1442 { 1443 resultType = getDataTypeMatrix(getDataTypeScalarSize(m_in1.dataType), getDataTypeScalarSize(m_in0.dataType)); 1444 } 1445 else if (m_op == OP_TRANSPOSE) 1446 { 1447 resultType = getDataTypeMatrix(getDataTypeMatrixNumRows(m_in0.dataType), getDataTypeMatrixNumColumns(m_in0.dataType)); 1448 } 1449 else if (m_op == OP_INVERSE) 1450 { 1451 resultType = m_in0.dataType; 1452 } 1453 else if (m_op == OP_DETERMINANT) 1454 { 1455 resultType = TYPE_FLOAT; 1456 } 1457 else if (getOperationType(m_op) == OPERATIONTYPE_UNARY_PREFIX_OPERATOR || 1458 getOperationType(m_op) == OPERATIONTYPE_UNARY_POSTFIX_OPERATOR) 1459 { 1460 resultType = m_in0.dataType; 1461 } 1462 else if (isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType)) 1463 { 1464 DE_ASSERT(m_in0.dataType == m_in1.dataType); 1465 resultType = m_in0.dataType; 1466 } 1467 else if (isDataTypeMatrix(m_in0.dataType) || isDataTypeMatrix(m_in1.dataType)) 1468 { 1469 int matNdx = isDataTypeMatrix(m_in0.dataType) ? 0 : 1; 1470 DataType matrixType = matNdx == 0 ? m_in0.dataType : m_in1.dataType; 1471 DataType otherType = matNdx == 0 ? m_in1.dataType : m_in0.dataType; 1472 1473 if (otherType == TYPE_FLOAT) 1474 resultType = matrixType; 1475 else 1476 { 1477 DE_ASSERT(isDataTypeVector(otherType)); 1478 resultType = getDataTypeFloatVec(matNdx == 0 ? getDataTypeMatrixNumRows(matrixType) : getDataTypeMatrixNumColumns(matrixType)); 1479 } 1480 } 1481 else 1482 { 1483 DE_ASSERT(DE_FALSE); 1484 } 1485 1486 vtx << "#version 300 es\n"; 1487 frag << "#version 300 es\n"; 1488 1489 vtx << "in highp vec4 a_position;\n"; 1490 frag << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 1491 if (m_isVertexCase) 1492 { 1493 vtx << "out mediump vec4 v_color;\n"; 1494 frag << "in mediump vec4 v_color;\n"; 1495 } 1496 1497 // Input declarations. 1498 for (int inNdx = 0; inNdx < numInputs; inNdx++) 1499 { 1500 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0; 1501 const char* precName = getPrecisionName(in.precision); 1502 const char* typeName = getDataTypeName(in.dataType); 1503 string& inValue = inNdx > 0 ? inValue1 : inValue0; 1504 1505 if (in.inputType == INPUTTYPE_DYNAMIC) 1506 { 1507 vtx << "in " << precName << " " << typeName << " a_"; 1508 1509 if (isDataTypeMatrix(in.dataType)) 1510 { 1511 // a_matN, v_matN 1512 vtx << typeName << ";\n"; 1513 if (!m_isVertexCase) 1514 { 1515 vtx << "out " << precName << " " << typeName << " v_" << typeName << ";\n"; 1516 frag << "in " << precName << " " << typeName << " v_" << typeName << ";\n"; 1517 passVars.push_back(typeName); 1518 } 1519 1520 inValue = string(m_isVertexCase ? "a_" : "v_") + getDataTypeName(in.dataType); 1521 } 1522 else 1523 { 1524 // a_coords, v_coords 1525 vtx << "coords;\n"; 1526 if (!m_isVertexCase) 1527 { 1528 vtx << "out " << precName << " " << typeName << " v_coords;\n"; 1529 frag << "in " << precName << " " << typeName << " v_coords;\n"; 1530 passVars.push_back("coords"); 1531 } 1532 1533 inValue = m_isVertexCase ? "a_coords" : "v_coords"; 1534 } 1535 } 1536 else if (in.inputType == INPUTTYPE_UNIFORM) 1537 { 1538 op << "uniform " << precName << " " << typeName << " u_in" << inNdx << ";\n"; 1539 inValue = string("u_in") + de::toString(inNdx); 1540 } 1541 else if (in.inputType == INPUTTYPE_CONST) 1542 { 1543 op << "const " << precName << " " << typeName << " in" << inNdx << " = "; 1544 1545 // Generate declaration. 1546 switch (in.dataType) 1547 { 1548 case TYPE_FLOAT: op << de::floatToString(s_constInFloat[inNdx], 1); break; 1549 case TYPE_FLOAT_VEC2: writeVectorConstructor<2>(op, s_constInVec2[inNdx]); break; 1550 case TYPE_FLOAT_VEC3: writeVectorConstructor<3>(op, s_constInVec3[inNdx]); break; 1551 case TYPE_FLOAT_VEC4: writeVectorConstructor<4>(op, s_constInVec4[inNdx]); break; 1552 case TYPE_FLOAT_MAT2: writeMatrixConstructor<2, 2>(op, Mat2(s_constInMat2x2[inNdx])); break; 1553 case TYPE_FLOAT_MAT2X3: writeMatrixConstructor<2, 3>(op, Mat2x3(s_constInMat2x3[inNdx])); break; 1554 case TYPE_FLOAT_MAT2X4: writeMatrixConstructor<2, 4>(op, Mat2x4(s_constInMat2x4[inNdx])); break; 1555 case TYPE_FLOAT_MAT3X2: writeMatrixConstructor<3, 2>(op, Mat3x2(s_constInMat3x2[inNdx])); break; 1556 case TYPE_FLOAT_MAT3: writeMatrixConstructor<3, 3>(op, Mat3(s_constInMat3x3[inNdx])); break; 1557 case TYPE_FLOAT_MAT3X4: writeMatrixConstructor<3, 4>(op, Mat3x4(s_constInMat3x4[inNdx])); break; 1558 case TYPE_FLOAT_MAT4X2: writeMatrixConstructor<4, 2>(op, Mat4x2(s_constInMat4x2[inNdx])); break; 1559 case TYPE_FLOAT_MAT4X3: writeMatrixConstructor<4, 3>(op, Mat4x3(s_constInMat4x3[inNdx])); break; 1560 case TYPE_FLOAT_MAT4: writeMatrixConstructor<4, 4>(op, Mat4(s_constInMat4x4[inNdx])); break; 1561 1562 default: 1563 DE_ASSERT(DE_FALSE); 1564 } 1565 1566 op << ";\n"; 1567 1568 inValue = string("in") + de::toString(inNdx); 1569 } 1570 } 1571 1572 vtx << "\n" 1573 << "void main (void)\n" 1574 << "{\n" 1575 << " gl_Position = a_position;\n"; 1576 frag << "\n" 1577 << "void main (void)\n" 1578 << "{\n"; 1579 1580 if (m_isVertexCase) 1581 frag << " dEQP_FragColor = v_color;\n"; 1582 else 1583 { 1584 for (vector<string>::const_iterator copyIter = passVars.begin(); copyIter != passVars.end(); copyIter++) 1585 vtx << " v_" << *copyIter << " = " << "a_" << *copyIter << ";\n"; 1586 } 1587 1588 // Operation. 1589 1590 switch (getOperationNature(m_op)) 1591 { 1592 case OPERATIONNATURE_PURE: 1593 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT); 1594 1595 operationValue0 = inValue0; 1596 operationValue1 = inValue1; 1597 break; 1598 1599 case OPERATIONNATURE_MUTATING: 1600 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT); 1601 1602 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " tmpValue = " << inValue0 << ";\n"; 1603 1604 operationValue0 = "tmpValue"; 1605 operationValue1 = inValue1; 1606 break; 1607 1608 case OPERATIONNATURE_ASSIGNMENT: 1609 DE_ASSERT(getOperationType(m_op) == OPERATIONTYPE_ASSIGNMENT); 1610 1611 operationValue0 = inValue0; 1612 operationValue1 = inValue1; 1613 break; 1614 1615 default: 1616 DE_ASSERT(DE_FALSE); 1617 } 1618 1619 switch (getOperationType(m_op)) 1620 { 1621 case OPERATIONTYPE_BINARY_OPERATOR: 1622 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << " " << getOperationName(m_op) << " " << operationValue1 << ";\n"; 1623 break; 1624 1625 case OPERATIONTYPE_UNARY_PREFIX_OPERATOR: 1626 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << operationValue0 << ";\n"; 1627 break; 1628 1629 case OPERATIONTYPE_UNARY_POSTFIX_OPERATOR: 1630 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << getOperationName(m_op) << ";\n"; 1631 break; 1632 1633 case OPERATIONTYPE_BINARY_FUNCTION: 1634 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ", " << operationValue1 << ");\n"; 1635 break; 1636 1637 case OPERATIONTYPE_UNARY_FUNCTION: 1638 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ");\n"; 1639 break; 1640 1641 case OPERATIONTYPE_ASSIGNMENT: 1642 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << ";\n"; 1643 op << " res " << getOperationName(m_op) << " " << operationValue1 << ";\n"; 1644 break; 1645 1646 default: 1647 DE_ASSERT(DE_FALSE); 1648 } 1649 1650 // Reduction to vec3 (rgb). Check the used value too if it was modified 1651 op << " " << (m_isVertexCase ? "v_color" : "dEQP_FragColor") << " = "; 1652 1653 if (isOperationValueModifying(m_op)) 1654 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0) + vec4(" << genGLSLMatToVec3Reduction(resultType, "tmpValue") << ", 0.0);\n"; 1655 else 1656 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0);\n"; 1657 1658 vtx << "}\n"; 1659 frag << "}\n"; 1660 1661 m_vertShaderSource = vtx.str(); 1662 m_fragShaderSource = frag.str(); 1663 1664 // \todo [2012-02-14 pyry] Compute better values for matrix tests. 1665 m_userAttribTransforms.resize(4); 1666 for (int attribNdx = 0; attribNdx < 4; attribNdx++) 1667 { 1668 m_userAttribTransforms[attribNdx] = Mat4(0.0f); 1669 m_userAttribTransforms[attribNdx]( 0, 3) = 0.2f; // !< prevent matrix*vec from going into zero (assuming vec.w != 0) 1670 m_userAttribTransforms[attribNdx]( 1, 3) = 0.1f; // !< 1671 m_userAttribTransforms[attribNdx]( 2, 3) = 0.4f + 0.15f * float(attribNdx); // !< 1672 m_userAttribTransforms[attribNdx]( 3, 3) = 0.7f; // !< 1673 m_userAttribTransforms[attribNdx]((0 + attribNdx) % 4, 0) = 1.0f; 1674 m_userAttribTransforms[attribNdx]((1 + attribNdx) % 4, 1) = 1.0f; 1675 m_userAttribTransforms[attribNdx]((2 + attribNdx) % 4, 2) = 1.0f; 1676 m_userAttribTransforms[attribNdx]((3 + attribNdx) % 4, 3) = 1.0f; 1677 } 1678 1679 // prevent bad reference cases such as black result images by fine-tuning used matrices 1680 if (getOperationTestMatrixType(m_op) != TESTMATRIXTYPE_DEFAULT) 1681 { 1682 for (int attribNdx = 0; attribNdx < 4; attribNdx++) 1683 { 1684 for (int row = 0; row < 4; row++) 1685 for (int col = 0; col < 4; col++) 1686 { 1687 switch (getOperationTestMatrixType(m_op)) 1688 { 1689 case TESTMATRIXTYPE_NEGATED: 1690 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col); 1691 break; 1692 case TESTMATRIXTYPE_INCREMENTED: 1693 m_userAttribTransforms[attribNdx](row, col) += 0.3f; 1694 break; 1695 case TESTMATRIXTYPE_DECREMENTED: 1696 m_userAttribTransforms[attribNdx](row, col) -= 0.3f; 1697 break; 1698 case TESTMATRIXTYPE_NEGATED_INCREMENTED: 1699 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col) + 0.3f; 1700 break; 1701 case TESTMATRIXTYPE_INCREMENTED_LESS: 1702 m_userAttribTransforms[attribNdx](row, col) -= 0.1f; 1703 break; 1704 1705 default: 1706 DE_ASSERT(DE_FALSE); 1707 break; 1708 } 1709 } 1710 } 1711 } 1712 1713 ShaderRenderCase::init(); 1714 } 1715 1716 std::string ShaderMatrixCase::genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName) 1717 { 1718 std::ostringstream op; 1719 1720 switch (matType) 1721 { 1722 case TYPE_FLOAT: op << varName << ", " << varName << ", " << varName << ""; break; 1723 case TYPE_FLOAT_VEC2: op << varName << ".x, " << varName << ".y, " << varName << ".x"; break; 1724 case TYPE_FLOAT_VEC3: op << varName << ""; break; 1725 case TYPE_FLOAT_VEC4: op << varName << ".x, " << varName << ".y, " << varName << ".z+" << varName << ".w"; break; 1726 case TYPE_FLOAT_MAT2: op << varName << "[0][0], " << varName << "[1][0], " << varName << "[0][1]+" << varName << "[1][1]"; break; 1727 case TYPE_FLOAT_MAT2X3: op << varName << "[0] + " << varName << "[1]"; break; 1728 case TYPE_FLOAT_MAT2X4: op << varName << "[0].xyz + " << varName << "[1].yzw"; break; 1729 case TYPE_FLOAT_MAT3X2: op << varName << "[0][0]+" << varName << "[0][1], " << varName << "[1][0]+" << varName << "[1][1], " << varName << "[2][0]+" << varName << "[2][1]"; break; 1730 case TYPE_FLOAT_MAT3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2]"; break; 1731 case TYPE_FLOAT_MAT3X4: op << varName << "[0].xyz + " << varName << "[1].yzw + " << varName << "[2].zwx"; break; 1732 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; 1733 case TYPE_FLOAT_MAT4X3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2] + " << varName << "[3]"; break; 1734 case TYPE_FLOAT_MAT4: op << varName << "[0].xyz+" << varName << "[1].yzw+" << varName << "[2].zwx+" << varName << "[3].wxy"; break; 1735 1736 default: 1737 DE_ASSERT(DE_FALSE); 1738 } 1739 1740 return op.str(); 1741 } 1742 1743 void ShaderMatrixCase::setupUniforms (int programID, const tcu::Vec4& constCoords) 1744 { 1745 const glw::Functions& gl = m_renderCtx.getFunctions(); 1746 1747 DE_UNREF(constCoords); 1748 1749 for (int inNdx = 0; inNdx < 2; inNdx++) 1750 { 1751 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0; 1752 1753 if (in.inputType == INPUTTYPE_UNIFORM) 1754 { 1755 int loc = gl.getUniformLocation(programID, (string("u_in") + de::toString(inNdx)).c_str()); 1756 1757 if (loc < 0) 1758 continue; 1759 1760 switch (in.dataType) 1761 { 1762 case TYPE_FLOAT: gl.uniform1f(loc, s_constInFloat[inNdx]); break; 1763 case TYPE_FLOAT_VEC2: gl.uniform2fv(loc, 1, s_constInVec2[inNdx].getPtr()); break; 1764 case TYPE_FLOAT_VEC3: gl.uniform3fv(loc, 1, s_constInVec3[inNdx].getPtr()); break; 1765 case TYPE_FLOAT_VEC4: gl.uniform4fv(loc, 1, s_constInVec4[inNdx].getPtr()); break; 1766 // \note GLES3 supports transpose in matrix upload. 1767 case TYPE_FLOAT_MAT2: gl.uniformMatrix2fv (loc, 1, GL_TRUE, s_constInMat2x2[inNdx]); break; 1768 case TYPE_FLOAT_MAT2X3: gl.uniformMatrix2x3fv(loc, 1, GL_TRUE, s_constInMat2x3[inNdx]); break; 1769 case TYPE_FLOAT_MAT2X4: gl.uniformMatrix2x4fv(loc, 1, GL_TRUE, s_constInMat2x4[inNdx]); break; 1770 case TYPE_FLOAT_MAT3X2: gl.uniformMatrix3x2fv(loc, 1, GL_TRUE, s_constInMat3x2[inNdx]); break; 1771 case TYPE_FLOAT_MAT3: gl.uniformMatrix3fv (loc, 1, GL_TRUE, s_constInMat3x3[inNdx]); break; 1772 case TYPE_FLOAT_MAT3X4: gl.uniformMatrix3x4fv(loc, 1, GL_TRUE, s_constInMat3x4[inNdx]); break; 1773 case TYPE_FLOAT_MAT4X2: gl.uniformMatrix4x2fv(loc, 1, GL_TRUE, s_constInMat4x2[inNdx]); break; 1774 case TYPE_FLOAT_MAT4X3: gl.uniformMatrix4x3fv(loc, 1, GL_TRUE, s_constInMat4x3[inNdx]); break; 1775 case TYPE_FLOAT_MAT4: gl.uniformMatrix4fv (loc, 1, GL_TRUE, s_constInMat4x4[inNdx]); break; 1776 default: 1777 DE_ASSERT(false); 1778 } 1779 } 1780 } 1781 } 1782 1783 ShaderMatrixTests::ShaderMatrixTests (Context& context) 1784 : TestCaseGroup(context, "matrix", "Matrix Tests") 1785 { 1786 } 1787 1788 ShaderMatrixTests::~ShaderMatrixTests (void) 1789 { 1790 } 1791 1792 void ShaderMatrixTests::init (void) 1793 { 1794 static const struct 1795 { 1796 const char* name; 1797 const char* desc; 1798 MatrixOp op; 1799 bool extendedInputTypeCases; // !< test with const and uniform types too 1800 bool createInputTypeGroup; // !< create group for input types 1801 } ops[] = 1802 { 1803 { "add", "Matrix addition tests", OP_ADD, true, true }, 1804 { "sub", "Matrix subtraction tests", OP_SUB, true, true }, 1805 { "mul", "Matrix multiplication tests", OP_MUL, true, true }, 1806 { "div", "Matrix division tests", OP_DIV, true, true }, 1807 { "matrixcompmult", "Matrix component-wise multiplication tests", OP_COMP_MUL, false, true }, 1808 { "outerproduct", "Matrix outerProduct() tests", OP_OUTER_PRODUCT, false, true }, 1809 { "transpose", "Matrix transpose() tests", OP_TRANSPOSE, false, true }, 1810 { "determinant", "Matrix determinant() tests", OP_DETERMINANT, false, true }, 1811 { "inverse", "Matrix inverse() tests", OP_INVERSE, false, true }, 1812 { "unary_addition", "Matrix unary addition tests", OP_UNARY_PLUS, false, false }, 1813 { "negation", "Matrix negation tests", OP_NEGATION, false, false }, 1814 { "pre_increment", "Matrix prefix increment tests", OP_PRE_INCREMENT, false, false }, 1815 { "pre_decrement", "Matrix prefix decrement tests", OP_PRE_DECREMENT, false, false }, 1816 { "post_increment", "Matrix postfix increment tests", OP_POST_INCREMENT, false, false }, 1817 { "post_decrement", "Matrix postfix decrement tests", OP_POST_DECREMENT, false, false }, 1818 { "add_assign", "Matrix add into tests", OP_ADD_INTO, false, false }, 1819 { "sub_assign", "Matrix subtract from tests", OP_SUBTRACT_FROM, false, false }, 1820 { "mul_assign", "Matrix multiply into tests", OP_MULTIPLY_INTO, false, false }, 1821 { "div_assign", "Matrix divide into tests", OP_DIVIDE_INTO, false, false }, 1822 }; 1823 1824 struct InputTypeSpec 1825 { 1826 const char* name; 1827 const char* desc; 1828 InputType type; 1829 }; 1830 static const InputTypeSpec extendedInputTypes[] = 1831 { 1832 { "const", "Constant matrix input", INPUTTYPE_CONST }, 1833 { "uniform", "Uniform matrix input", INPUTTYPE_UNIFORM }, 1834 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC } 1835 }; 1836 static const InputTypeSpec reducedInputTypes[] = 1837 { 1838 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC } 1839 }; 1840 1841 static const DataType matrixTypes[] = 1842 { 1843 TYPE_FLOAT_MAT2, 1844 TYPE_FLOAT_MAT2X3, 1845 TYPE_FLOAT_MAT2X4, 1846 TYPE_FLOAT_MAT3X2, 1847 TYPE_FLOAT_MAT3, 1848 TYPE_FLOAT_MAT3X4, 1849 TYPE_FLOAT_MAT4X2, 1850 TYPE_FLOAT_MAT4X3, 1851 TYPE_FLOAT_MAT4 1852 }; 1853 1854 static const Precision precisions[] = 1855 { 1856 PRECISION_LOWP, 1857 PRECISION_MEDIUMP, 1858 PRECISION_HIGHP 1859 }; 1860 1861 for (int opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++) 1862 { 1863 const InputTypeSpec* inTypeList = (ops[opNdx].extendedInputTypeCases) ? (extendedInputTypes) : (reducedInputTypes); 1864 const int inTypeListSize = (ops[opNdx].extendedInputTypeCases) ? (DE_LENGTH_OF_ARRAY(extendedInputTypes)) : (DE_LENGTH_OF_ARRAY(reducedInputTypes)); 1865 const MatrixOp op = ops[opNdx].op; 1866 tcu::TestCaseGroup* opGroup = new tcu::TestCaseGroup(m_testCtx, ops[opNdx].name, ops[opNdx].desc); 1867 1868 addChild(opGroup); 1869 1870 for (int inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++) 1871 { 1872 const InputType inputType = inTypeList[inTypeNdx].type; 1873 tcu::TestCaseGroup* inGroup; 1874 1875 if (ops[opNdx].createInputTypeGroup) 1876 { 1877 inGroup = new tcu::TestCaseGroup(m_testCtx, inTypeList[inTypeNdx].name, inTypeList[inTypeNdx].desc); 1878 opGroup->addChild(inGroup); 1879 } 1880 else 1881 inGroup = opGroup; 1882 1883 for (int matTypeNdx = 0; matTypeNdx < DE_LENGTH_OF_ARRAY(matrixTypes); matTypeNdx++) 1884 { 1885 DataType matType = matrixTypes[matTypeNdx]; 1886 int numCols = getDataTypeMatrixNumColumns(matType); 1887 int numRows = getDataTypeMatrixNumRows(matType); 1888 const char* matTypeName = getDataTypeName(matType); 1889 1890 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1891 { 1892 Precision precision = precisions[precNdx]; 1893 const char* precName = getPrecisionName(precision); 1894 string baseName = string(precName) + "_" + matTypeName + "_"; 1895 ShaderInput matIn (inputType, matType, precision); 1896 1897 if (isOperationMatrixScalar(op)) 1898 { 1899 // Matrix-scalar \note For div cases we use uniform input. 1900 ShaderInput scalarIn(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, TYPE_FLOAT, precision); 1901 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(), "Matrix-scalar case", matIn, scalarIn, op, true)); 1902 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(), "Matrix-scalar case", matIn, scalarIn, op, false)); 1903 } 1904 1905 if (isOperationMatrixVector(op)) 1906 { 1907 // Matrix-vector. 1908 DataType colVecType = getDataTypeFloatVec(numCols); 1909 ShaderInput colVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, colVecType, precision); 1910 1911 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(colVecType) + "_vertex").c_str(), "Matrix-vector case", matIn, colVecIn, op, true)); 1912 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(colVecType) + "_fragment").c_str(), "Matrix-vector case", matIn, colVecIn, op, false)); 1913 1914 // Vector-matrix. 1915 DataType rowVecType = getDataTypeFloatVec(numRows); 1916 ShaderInput rowVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, rowVecType, precision); 1917 string vecMatName = string(precName) + "_" + getDataTypeName(rowVecType) + "_" + matTypeName; 1918 1919 inGroup->addChild(new ShaderMatrixCase(m_context, (vecMatName + "_vertex").c_str(), "Vector-matrix case", rowVecIn, matIn, op, true)); 1920 inGroup->addChild(new ShaderMatrixCase(m_context, (vecMatName + "_fragment").c_str(), "Vector-matrix case", rowVecIn, matIn, op, false)); 1921 } 1922 1923 if (isOperationArithmeticMatrixMatrix(op)) 1924 { 1925 // Arithmetic matrix-matrix multiplication. 1926 for (int otherCols = 2; otherCols <= 4; otherCols++) 1927 { 1928 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, getDataTypeMatrix(otherCols, numCols /* rows */), precision); 1929 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(otherMatIn.dataType) + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true)); 1930 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(otherMatIn.dataType) + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false)); 1931 } 1932 } 1933 else if (isOperationComponentwiseMatrixMatrix(op)) 1934 { 1935 // Component-wise. 1936 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision); 1937 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + matTypeName + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true)); 1938 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + matTypeName + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false)); 1939 } 1940 1941 if (isOperationVectorVector(op)) 1942 { 1943 ShaderInput vec1In(inputType, getDataTypeFloatVec(numRows), precision); 1944 ShaderInput vec2In((inputType == INPUTTYPE_DYNAMIC) ? (INPUTTYPE_UNIFORM) : (inputType), getDataTypeFloatVec(numCols), precision); 1945 1946 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(), "Vector-vector case", vec1In, vec2In, op, true)); 1947 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(), "Vector-vector case", vec1In, vec2In, op, false)); 1948 } 1949 1950 if ((isOperationUnaryAnyMatrix(op)) || 1951 (isOperationUnarySymmetricMatrix(op) && numCols == numRows)) 1952 { 1953 ShaderInput voidInput(INPUTTYPE_LAST, TYPE_LAST, PRECISION_LAST); 1954 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(), "Matrix case", matIn, voidInput, op, true)); 1955 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(), "Matrix case", matIn, voidInput, op, false)); 1956 } 1957 1958 if ((isOperationAssignmentAnyMatrix(op)) || 1959 (isOperationAssignmentSymmetricMatrix(op) && numCols == numRows)) 1960 { 1961 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision); 1962 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(), "Matrix assignment case", matIn, otherMatIn, op, true)); 1963 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(), "Matrix assignment case", matIn, otherMatIn, op, false)); 1964 } 1965 } 1966 } 1967 } 1968 } 1969 } 1970 1971 } // Functional 1972 } // gles3 1973 } // deqp 1974