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