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