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