1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Shader matrix arithmetic tests. 22 * 23 * Variables: 24 * + operation 25 * - mat OP mat 26 * - mat OP vec 27 * - vec OP mat 28 * - mat OP scalar 29 * - OP ( mat ) 30 * - vec OP vec 31 * - OP mat 32 * + matrix source 33 * - constant (ctor) 34 * - uniform 35 * - vertex input 36 * - fragment input 37 * + other operand: always dynamic data? 38 * + how to reduce to vec3? 39 *//*--------------------------------------------------------------------*/ 40 41#include "es3fShaderMatrixTests.hpp" 42#include "glsShaderRenderCase.hpp" 43#include "gluShaderUtil.hpp" 44#include "tcuVector.hpp" 45#include "tcuMatrix.hpp" 46#include "tcuMatrixUtil.hpp" 47#include "deStringUtil.hpp" 48#include "deFloat16.h" 49 50#include "glwEnums.hpp" 51#include "glwFunctions.hpp" 52 53namespace deqp 54{ 55namespace gles3 56{ 57namespace Functional 58{ 59 60using std::string; 61using std::vector; 62using namespace glu; 63using namespace deqp::gls; 64 65using tcu::Vec2; 66using tcu::Vec3; 67using tcu::Vec4; 68using tcu::Mat2; 69using tcu::Mat2x3; 70using tcu::Mat2x4; 71using tcu::Mat3x2; 72using tcu::Mat3; 73using tcu::Mat3x4; 74using tcu::Mat4x2; 75using tcu::Mat4x3; 76using tcu::Mat4; 77 78// Uniform / constant values for tests. 79// \note Input1 should not contain 0 components as it is used as divisor in div cases. 80// \todo [2012-02-14 pyry] Make these dynamic. 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// outerProduct 637 638template <typename T, int Rows, int Cols> 639tcu::Matrix<T, Cols, Rows> outerProduct (const tcu::Vector<T, Cols>& a, const tcu::Vector<T, Rows>& b) 640{ 641 tcu::Matrix<T, Rows, Cols> retVal; 642 643 for (int r = 0; r < Rows; ++r) 644 for (int c = 0; c < Cols; ++c) 645 retVal(r,c) = a[c] * b[r]; 646 647 return transpose(retVal); // to gl-form (column-major) 648} 649 650// Determinant 651 652template <int Size> 653float determinant (const tcu::Matrix<float, Size, Size>& mat); 654 655template <> 656float determinant<2> (const tcu::Matrix<float, 2, 2>& mat) 657{ 658 return mat(0,0) * mat(1,1) - mat(1,0) * mat(0,1); 659} 660 661template <> 662float determinant<3> (const tcu::Matrix<float, 3, 3>& mat) 663{ 664 return + mat(0,0) * mat(1,1) * mat(2,2) 665 + mat(0,1) * mat(1,2) * mat(2,0) 666 + mat(0,2) * mat(1,0) * mat(2,1) 667 - mat(0,0) * mat(1,2) * mat(2,1) 668 - mat(0,1) * mat(1,0) * mat(2,2) 669 - mat(0,2) * mat(1,1) * mat(2,0); 670} 671 672template <> 673float determinant<4> (const tcu::Matrix<float, 4, 4>& mat) 674{ 675 const float minorMatrices[4][3*3] = 676 { 677 { 678 mat(1,1), mat(2,1), mat(3,1), 679 mat(1,2), mat(2,2), mat(3,2), 680 mat(1,3), mat(2,3), mat(3,3), 681 }, 682 { 683 mat(1,0), mat(2,0), mat(3,0), 684 mat(1,2), mat(2,2), mat(3,2), 685 mat(1,3), mat(2,3), mat(3,3), 686 }, 687 { 688 mat(1,0), mat(2,0), mat(3,0), 689 mat(1,1), mat(2,1), mat(3,1), 690 mat(1,3), mat(2,3), mat(3,3), 691 }, 692 { 693 mat(1,0), mat(2,0), mat(3,0), 694 mat(1,1), mat(2,1), mat(3,1), 695 mat(1,2), mat(2,2), mat(3,2), 696 } 697 }; 698 699 return + mat(0,0) * determinant(tcu::Mat3(minorMatrices[0])) 700 - mat(0,1) * determinant(tcu::Mat3(minorMatrices[1])) 701 + mat(0,2) * determinant(tcu::Mat3(minorMatrices[2])) 702 - mat(0,3) * determinant(tcu::Mat3(minorMatrices[3])); 703} 704 705// Inverse 706 707template <int Size> 708tcu::Matrix<float, Size, Size> inverse (const tcu::Matrix<float, Size, Size>& mat); 709 710template <> 711tcu::Matrix<float, 2, 2> inverse<2> (const tcu::Matrix<float, 2, 2>& mat) 712{ 713 const float det = determinant(mat); 714 tcu::Matrix<float, 2, 2> retVal; 715 716 DE_ASSERT(det != 0.0f); 717 718 retVal(0, 0) = mat(1, 1) / det; 719 retVal(0, 1) = -mat(0, 1) / det; 720 retVal(1, 0) = -mat(1, 0) / det; 721 retVal(1, 1) = mat(0, 0) / det; 722 723 return retVal; 724} 725 726template <> 727tcu::Matrix<float, 3, 3> inverse<3> (const tcu::Matrix<float, 3, 3>& mat) 728{ 729 // Blockwise inversion 730 731 DE_ASSERT(determinant(mat) != 0.0f); 732 733 const float areaA[2*2] = 734 { 735 mat(0,0), mat(0,1), 736 mat(1,0), mat(1,1) 737 }; 738 const float areaB[2] = 739 { 740 mat(0,2), 741 mat(1,2), 742 }; 743 const float areaC[2] = 744 { 745 mat(2,0), mat(2,1), 746 }; 747 const float areaD[1] = 748 { 749 mat(2,2) 750 }; 751 const float nullField[4] = { 0.0f }; 752 753 const tcu::Matrix<float, 2, 2> invA = inverse(tcu::Matrix<float, 2, 2>(areaA)); 754 const tcu::Matrix<float, 2, 1> matB = tcu::Matrix<float, 2, 1>(areaB); 755 const tcu::Matrix<float, 1, 2> matC = tcu::Matrix<float, 1, 2>(areaC); 756 const tcu::Matrix<float, 1, 1> matD = tcu::Matrix<float, 1, 1>(areaD); 757 758 const float schurComplement = 1.0f / (matD - matC*invA*matB)(0,0); 759 const tcu::Matrix<float, 2, 2> zeroMat = Mat2(nullField); 760 761 const tcu::Matrix<float, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA; 762 const tcu::Matrix<float, 2, 1> blockB = (zeroMat-invA)*matB*schurComplement; 763 const tcu::Matrix<float, 1, 2> blockC = matC*invA*(-schurComplement); 764 const float blockD = schurComplement; 765 766 const float result[3*3] = 767 { 768 blockA(0,0), blockA(0,1), blockB(0,0), 769 blockA(1,0), blockA(1,1), blockB(1,0), 770 blockC(0,0), blockC(0,1), blockD, 771 }; 772 773 return Mat3(result); 774} 775 776template <> 777tcu::Matrix<float, 4, 4> inverse<4> (const tcu::Matrix<float, 4, 4>& mat) 778{ 779 // Blockwise inversion 780 781 DE_ASSERT(determinant(mat) != 0.0f); 782 783 const float areaA[2*2] = 784 { 785 mat(0,0), mat(0,1), 786 mat(1,0), mat(1,1) 787 }; 788 const float areaB[2*2] = 789 { 790 mat(0,2), mat(0,3), 791 mat(1,2), mat(1,3) 792 }; 793 const float areaC[2*2] = 794 { 795 mat(2,0), mat(2,1), 796 mat(3,0), mat(3,1) 797 }; 798 const float areaD[2*2] = 799 { 800 mat(2,2), mat(2,3), 801 mat(3,2), mat(3,3) 802 }; 803 const float nullField[4] = { 0.0f }; 804 805 const tcu::Matrix<float, 2, 2> invA = inverse(Mat2(areaA)); 806 const tcu::Matrix<float, 2, 2> matB = Mat2(areaB); 807 const tcu::Matrix<float, 2, 2> matC = Mat2(areaC); 808 const tcu::Matrix<float, 2, 2> matD = Mat2(areaD); 809 810 const tcu::Matrix<float, 2, 2> schurComplement = inverse(matD - matC*invA*matB); 811 const tcu::Matrix<float, 2, 2> zeroMat = Mat2(nullField); 812 813 const tcu::Matrix<float, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA; 814 const tcu::Matrix<float, 2, 2> blockB = (zeroMat-invA)*matB*schurComplement; 815 const tcu::Matrix<float, 2, 2> blockC = (zeroMat-schurComplement)*matC*invA; 816 const tcu::Matrix<float, 2, 2> blockD = schurComplement; 817 818 const float result[4*4] = 819 { 820 blockA(0,0), blockA(0,1), blockB(0,0), blockB(0,1), 821 blockA(1,0), blockA(1,1), blockB(1,0), blockB(1,1), 822 blockC(0,0), blockC(0,1), blockD(0,0), blockD(0,1), 823 blockC(1,0), blockC(1,1), blockD(1,0), blockD(1,1), 824 }; 825 826 return Mat4(result); 827} 828 829// negate 830 831template <typename T, int Rows, int Cols> 832tcu::Matrix<T, Rows, Cols> negate (const tcu::Matrix<T, Rows, Cols>& mat) 833{ 834 tcu::Matrix<T, Rows, Cols> retVal; 835 836 for (int r = 0; r < Rows; ++r) 837 for (int c = 0; c < Cols; ++c) 838 retVal(r,c) = -mat(r, c); 839 840 return retVal; 841} 842 843// increment/decrement 844 845template <typename T, int Rows, int Cols> 846tcu::Matrix<T, Rows, Cols> increment (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) + 1.0f; 853 854 return retVal; 855} 856 857template <typename T, int Rows, int Cols> 858tcu::Matrix<T, Rows, Cols> decrement (const tcu::Matrix<T, Rows, Cols>& mat) 859{ 860 tcu::Matrix<T, Rows, Cols> retVal; 861 862 for (int r = 0; r < Rows; ++r) 863 for (int c = 0; c < Cols; ++c) 864 retVal(r,c) = mat(r, c) - 1.0f; 865 866 return retVal; 867} 868 869// Evaluator template. 870 871typedef void (*MatrixShaderEvalFunc) (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type); 872 873template <int Op, int In0DataType, int In1DataType> 874struct Evaluator; 875 876template <int In0DataType, int In1DataType> 877struct Evaluator<OP_ADD, In0DataType, In1DataType> 878{ 879 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 880 { 881 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 882 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 883 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 884 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 885 evalCtx.color.xyz() = reduceToVec3(in0 + in1); 886 } 887}; 888 889template <int In0DataType, int In1DataType> 890struct Evaluator<OP_SUB, In0DataType, In1DataType> 891{ 892 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 893 { 894 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 895 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 896 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 897 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 898 evalCtx.color.xyz() = reduceToVec3(in0 - in1); 899 } 900}; 901 902template <int In0DataType, int In1DataType> 903struct Evaluator<OP_MUL, In0DataType, In1DataType> 904{ 905 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 906 { 907 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 908 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 909 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 910 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 911 evalCtx.color.xyz() = reduceToVec3(in0 * in1); 912 } 913}; 914 915template <int In0DataType, int In1DataType> 916struct Evaluator<OP_DIV, In0DataType, In1DataType> 917{ 918 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 919 { 920 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 921 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 922 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 923 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 924 evalCtx.color.xyz() = reduceToVec3(in0 / in1); 925 } 926}; 927 928template <int In0DataType, int In1DataType> 929struct Evaluator<OP_COMP_MUL, In0DataType, In1DataType> 930{ 931 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 932 { 933 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 934 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 935 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 936 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 937 evalCtx.color.xyz() = reduceToVec3(matrixCompMult(in0, in1)); 938 } 939}; 940 941template <int In0DataType, int In1DataType> 942struct Evaluator<OP_OUTER_PRODUCT, In0DataType, In1DataType> 943{ 944 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 945 { 946 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 947 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 948 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 949 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 950 evalCtx.color.xyz() = reduceToVec3(outerProduct(in0, in1)); 951 } 952}; 953 954template <int In0DataType, int In1DataType> 955struct Evaluator<OP_TRANSPOSE, In0DataType, In1DataType> 956{ 957 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 958 { 959 DE_UNREF(in1Type); 960 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 961 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 962 evalCtx.color.xyz() = reduceToVec3(transpose(in0)); 963 } 964}; 965 966template <int In0DataType, int In1DataType> 967struct Evaluator<OP_INVERSE, In0DataType, In1DataType> 968{ 969 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 970 { 971 DE_UNREF(in1Type); 972 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 973 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 974 evalCtx.color.xyz() = reduceToVec3(inverse(in0)); 975 } 976}; 977 978template <int In0DataType, int In1DataType> 979struct Evaluator<OP_DETERMINANT, In0DataType, In1DataType> 980{ 981 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 982 { 983 DE_UNREF(in1Type); 984 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 985 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 986 evalCtx.color.xyz() = Vec3(determinant(in0)); 987 } 988}; 989 990template <int In0DataType, int In1DataType> 991struct Evaluator<OP_UNARY_PLUS, In0DataType, In1DataType> 992{ 993 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 994 { 995 DE_UNREF(in1Type); 996 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 997 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 998 evalCtx.color.xyz() = reduceToVec3(in0); 999 } 1000}; 1001 1002template <int In0DataType, int In1DataType> 1003struct Evaluator<OP_NEGATION, In0DataType, In1DataType> 1004{ 1005 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1006 { 1007 DE_UNREF(in1Type); 1008 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1009 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1010 evalCtx.color.xyz() = reduceToVec3(negate(in0)); 1011 } 1012}; 1013 1014template <int In0DataType, int In1DataType> 1015struct Evaluator<OP_PRE_INCREMENT, In0DataType, In1DataType> 1016{ 1017 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1018 { 1019 DE_UNREF(in1Type); 1020 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1021 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1022 1023 // modifying reduction: sum modified value too 1024 evalCtx.color.xyz() = reduceToVec3(increment(in0)) + reduceToVec3(increment(in0)); 1025 } 1026}; 1027 1028template <int In0DataType, int In1DataType> 1029struct Evaluator<OP_PRE_DECREMENT, 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(decrement(in0)) + reduceToVec3(decrement(in0)); 1039 } 1040}; 1041 1042template <int In0DataType, int In1DataType> 1043struct Evaluator<OP_POST_INCREMENT, 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(in0) + reduceToVec3(increment(in0)); 1053 } 1054}; 1055 1056template <int In0DataType, int In1DataType> 1057struct Evaluator<OP_POST_DECREMENT, 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(decrement(in0)); 1067 } 1068}; 1069 1070template <int In0DataType, int In1DataType> 1071struct Evaluator<OP_ADD_INTO, In0DataType, In1DataType> 1072{ 1073 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1074 { 1075 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1076 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1077 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 1078 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 1079 evalCtx.color.xyz() = reduceToVec3(in0 + in1); 1080 } 1081}; 1082 1083template <int In0DataType, int In1DataType> 1084struct Evaluator<OP_SUBTRACT_FROM, In0DataType, In1DataType> 1085{ 1086 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1087 { 1088 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1089 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1090 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 1091 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 1092 evalCtx.color.xyz() = reduceToVec3(in0 - in1); 1093 } 1094}; 1095 1096template <int In0DataType, int In1DataType> 1097struct Evaluator<OP_MULTIPLY_INTO, In0DataType, In1DataType> 1098{ 1099 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1100 { 1101 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1102 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1103 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 1104 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 1105 evalCtx.color.xyz() = reduceToVec3(in0 * in1); 1106 } 1107}; 1108 1109template <int In0DataType, int In1DataType> 1110struct Evaluator<OP_DIVIDE_INTO, In0DataType, In1DataType> 1111{ 1112 static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type) 1113 { 1114 typename TypeTraits<In0DataType>::Type in0 = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0) 1115 : getInputValue<INPUTTYPE_CONST, In0DataType>(evalCtx, 0); 1116 typename TypeTraits<In1DataType>::Type in1 = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1) 1117 : getInputValue<INPUTTYPE_CONST, In1DataType>(evalCtx, 1); 1118 evalCtx.color.xyz() = reduceToVec3(in0 / in1); 1119 } 1120}; 1121 1122MatrixShaderEvalFunc getEvalFunc (const ShaderInput& in0, const ShaderInput& in1, MatrixOp op) 1123{ 1124 // Evaluator is selected based on op and input data types. 1125 // For efficient lookup the types and op enums are packed together to form a 19-bit key: 1126 // [18..14 OP] [13..7 TYPE0] [6..0 TYPE1] 1127 1128 DE_STATIC_ASSERT(TYPE_LAST <= (1<<7)); 1129 DE_STATIC_ASSERT(OP_LAST <= (1<<5)); 1130 1131#define PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE) (((OP) << 14) | ((IN0DATATYPE) << 7) | (IN1DATATYPE)) 1132 1133#define MAKE_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE) \ 1134 case PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE): \ 1135 return Evaluator<OP, IN0DATATYPE, IN1DATATYPE>::evaluate 1136 1137#define MAKE_SCALAR_OPS(IN0DATATYPE, IN1DATATYPE) \ 1138 MAKE_EVAL_CASE(OP_ADD, IN0DATATYPE, IN1DATATYPE); \ 1139 MAKE_EVAL_CASE(OP_SUB, IN0DATATYPE, IN1DATATYPE); \ 1140 MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE); \ 1141 MAKE_EVAL_CASE(OP_DIV, IN0DATATYPE, IN1DATATYPE) 1142 1143#define MAKE_CWISE_OPS(IN0DATATYPE, IN1DATATYPE) \ 1144 MAKE_EVAL_CASE(OP_ADD, IN0DATATYPE, IN1DATATYPE); \ 1145 MAKE_EVAL_CASE(OP_SUB, IN0DATATYPE, IN1DATATYPE); \ 1146 MAKE_EVAL_CASE(OP_DIV, IN0DATATYPE, IN1DATATYPE); \ 1147 MAKE_EVAL_CASE(OP_COMP_MUL, IN0DATATYPE, IN1DATATYPE) 1148 1149#define MAKE_MUL_OP(IN0DATATYPE, IN1DATATYPE) \ 1150 MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE) 1151 1152#define MAKE_VECVEC_OP(IN0DATATYPE, IN1DATATYPE) \ 1153 MAKE_EVAL_CASE(OP_OUTER_PRODUCT, IN0DATATYPE, IN1DATATYPE) 1154 1155#define MAKE_UNARY_OP(IN0DATATYPE) \ 1156 MAKE_EVAL_CASE(OP_TRANSPOSE, IN0DATATYPE, TYPE_LAST); \ 1157 MAKE_EVAL_CASE(OP_UNARY_PLUS, IN0DATATYPE, TYPE_LAST); \ 1158 MAKE_EVAL_CASE(OP_NEGATION, IN0DATATYPE, TYPE_LAST); \ 1159 MAKE_EVAL_CASE(OP_PRE_INCREMENT, IN0DATATYPE, TYPE_LAST); \ 1160 MAKE_EVAL_CASE(OP_PRE_DECREMENT, IN0DATATYPE, TYPE_LAST); \ 1161 MAKE_EVAL_CASE(OP_POST_INCREMENT, IN0DATATYPE, TYPE_LAST); \ 1162 MAKE_EVAL_CASE(OP_POST_DECREMENT, IN0DATATYPE, TYPE_LAST) 1163 1164#define MAKE_UNARY_SYMMETRIC_OP(IN0DATATYPE) \ 1165 MAKE_UNARY_OP(IN0DATATYPE); \ 1166 MAKE_EVAL_CASE(OP_DETERMINANT, IN0DATATYPE, TYPE_LAST); \ 1167 MAKE_EVAL_CASE(OP_INVERSE, IN0DATATYPE, TYPE_LAST) 1168 1169#define MAKE_ASSIGNMENT_OP(IN0DATATYPE) \ 1170 MAKE_EVAL_CASE(OP_ADD_INTO, IN0DATATYPE, IN0DATATYPE); \ 1171 MAKE_EVAL_CASE(OP_SUBTRACT_FROM, IN0DATATYPE, IN0DATATYPE); \ 1172 MAKE_EVAL_CASE(OP_DIVIDE_INTO, IN0DATATYPE, IN0DATATYPE) 1173 1174#define MAKE_ASSIGNMENT_SYMMETRIC_OP(IN0DATATYPE) \ 1175 MAKE_ASSIGNMENT_OP(IN0DATATYPE); \ 1176 MAKE_EVAL_CASE(OP_MULTIPLY_INTO, IN0DATATYPE, IN0DATATYPE) 1177 1178 switch (PACK_EVAL_CASE(op, in0.dataType, in1.dataType)) 1179 { 1180 // Matrix-scalar. 1181 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2, TYPE_FLOAT); 1182 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X3, TYPE_FLOAT); 1183 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X4, TYPE_FLOAT); 1184 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X2, TYPE_FLOAT); 1185 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3, TYPE_FLOAT); 1186 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X4, TYPE_FLOAT); 1187 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X2, TYPE_FLOAT); 1188 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X3, TYPE_FLOAT); 1189 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4, TYPE_FLOAT); 1190 1191 // Matrix-vector. 1192 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_VEC2); 1193 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_VEC2); 1194 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_VEC2); 1195 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_VEC3); 1196 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_VEC3); 1197 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_VEC3); 1198 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_VEC4); 1199 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_VEC4); 1200 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_VEC4); 1201 1202 // Vector-matrix. 1203 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT2); 1204 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT2X3); 1205 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT2X4); 1206 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT3X2); 1207 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT3); 1208 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT3X4); 1209 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT4X2); 1210 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT4X3); 1211 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT4); 1212 1213 // Matrix-matrix. 1214 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT2); 1215 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT2); 1216 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT3X2); 1217 MAKE_MUL_OP(TYPE_FLOAT_MAT2, TYPE_FLOAT_MAT4X2); 1218 1219 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2X3); 1220 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT2); 1221 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT3X2); 1222 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3, TYPE_FLOAT_MAT4X2); 1223 1224 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT2X4); 1225 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT2); 1226 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT3X2); 1227 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4, TYPE_FLOAT_MAT4X2); 1228 1229 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3X2); 1230 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT2X3); 1231 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT3); 1232 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2, TYPE_FLOAT_MAT4X3); 1233 1234 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT3); 1235 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT2X3); 1236 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT3); 1237 MAKE_MUL_OP(TYPE_FLOAT_MAT3, TYPE_FLOAT_MAT4X3); 1238 1239 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT3X4); 1240 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT2X3); 1241 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT3); 1242 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4, TYPE_FLOAT_MAT4X3); 1243 1244 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4X2); 1245 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT2X4); 1246 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT3X4); 1247 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2, TYPE_FLOAT_MAT4); 1248 1249 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4X3); 1250 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT2X4); 1251 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT3X4); 1252 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3, TYPE_FLOAT_MAT4); 1253 1254 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT4); 1255 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT2X4); 1256 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT3X4); 1257 MAKE_MUL_OP(TYPE_FLOAT_MAT4, TYPE_FLOAT_MAT4); 1258 1259 // Vector-vector. 1260 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC2); 1261 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3); 1262 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC4); 1263 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC2); 1264 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC3); 1265 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4); 1266 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC2); 1267 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC3); 1268 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4); 1269 1270 // Unary Matrix. 1271 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT2); 1272 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X3); 1273 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X4); 1274 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X2); 1275 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT3); 1276 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X4); 1277 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X2); 1278 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X3); 1279 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT4); 1280 1281 // Assignments 1282 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT2); 1283 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X3); 1284 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X4); 1285 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X2); 1286 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT3); 1287 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X4); 1288 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X2); 1289 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X3); 1290 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT4); 1291 1292 default: 1293 DE_ASSERT(DE_FALSE); 1294 return DE_NULL; 1295 } 1296 1297#undef PACK_EVAL_CASE 1298#undef MAKE_EVAL_CASE 1299#undef MUL_OP 1300#undef ALL_OPS 1301#undef MAKE_MAT_SCALAR_VEC_CASES 1302#undef MAKE_MAT_MAT_CASES 1303} 1304 1305// Shader source format utilities. 1306 1307template <int Size> 1308void writeVectorConstructor (std::ostream& str, const tcu::Vector<float, Size>& v) 1309{ 1310 str << "vec" << Size << "("; 1311 for (int ndx = 0; ndx < Size; ndx++) 1312 { 1313 if (ndx != 0) 1314 str << ", "; 1315 str << de::floatToString(v[ndx], 1); 1316 } 1317 str << ")"; 1318} 1319 1320template <int Cols, int Rows> 1321void writeMatrixConstructor (std::ostream& str, const tcu::Matrix<float, Rows, Cols>& m) 1322{ 1323 if (Rows == Cols) 1324 str << "mat" << Cols; 1325 else 1326 str << "mat" << Cols << "x" << Rows; 1327 1328 str << "("; 1329 for (int colNdx = 0; colNdx < Cols; colNdx++) 1330 { 1331 for (int rowNdx = 0; rowNdx < Rows; rowNdx++) 1332 { 1333 if (rowNdx > 0 || colNdx > 0) 1334 str << ", "; 1335 str << de::floatToString(m(rowNdx, colNdx), 1); 1336 } 1337 } 1338 str << ")"; 1339} 1340 1341} // MatrixCaseUtils 1342 1343using namespace MatrixCaseUtils; 1344 1345class MatrixShaderEvaluator : public ShaderEvaluator 1346{ 1347public: 1348 MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1); 1349 1350 virtual void evaluate (ShaderEvalContext& evalCtx); 1351 1352private: 1353 MatrixShaderEvalFunc m_matEvalFunc; 1354 InputType m_inType0; 1355 InputType m_inType1; 1356}; 1357 1358MatrixShaderEvaluator::MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1) 1359 : m_matEvalFunc (evalFunc) 1360 , m_inType0 (inType0) 1361 , m_inType1 (inType1) 1362{ 1363} 1364 1365void MatrixShaderEvaluator::evaluate (ShaderEvalContext& evalCtx) 1366{ 1367 m_matEvalFunc(evalCtx, m_inType0, m_inType1); 1368} 1369 1370class ShaderMatrixCase : public ShaderRenderCase 1371{ 1372public: 1373 ShaderMatrixCase (Context& context, const char* name, const char* desc, const ShaderInput& in0, const ShaderInput& in1, MatrixOp op, bool isVertexCase); 1374 ~ShaderMatrixCase (void); 1375 1376 void init (void); 1377 1378protected: 1379 std::string genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName); 1380 void setupUniforms (int programID, const tcu::Vec4& constCoords); 1381 1382private: 1383 ShaderInput m_in0; 1384 ShaderInput m_in1; 1385 MatrixOp m_op; 1386 MatrixShaderEvaluator m_matEvaluator; 1387}; 1388 1389ShaderMatrixCase::ShaderMatrixCase (Context& context, const char* name, const char* desc, const ShaderInput& in0, const ShaderInput& in1, MatrixOp op, bool isVertexCase) 1390 : ShaderRenderCase (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_matEvaluator) 1391 , m_in0 (in0) 1392 , m_in1 (in1) 1393 , m_op (op) 1394 , m_matEvaluator (getEvalFunc(in0, in1, op), in0.inputType, in1.inputType) 1395{ 1396} 1397 1398ShaderMatrixCase::~ShaderMatrixCase (void) 1399{ 1400} 1401 1402void ShaderMatrixCase::init (void) 1403{ 1404 std::ostringstream vtx; 1405 std::ostringstream frag; 1406 std::ostringstream& op = m_isVertexCase ? vtx : frag; 1407 1408 bool isInDynMat0 = isDataTypeMatrix(m_in0.dataType) && m_in0.inputType == INPUTTYPE_DYNAMIC; 1409 bool isInDynMat1 = isDataTypeMatrix(m_in1.dataType) && m_in1.inputType == INPUTTYPE_DYNAMIC; 1410 string inValue0; 1411 string inValue1; 1412 DataType resultType = TYPE_LAST; 1413 Precision resultPrec = m_in0.precision; 1414 vector<string> passVars; 1415 int numInputs = (isOperationBinary(m_op)) ? (2) : (1); 1416 1417 std::string operationValue0; 1418 std::string operationValue1; 1419 1420 DE_ASSERT(!isInDynMat0 || !isInDynMat1); // Only single dynamic matrix input is allowed. 1421 DE_UNREF(isInDynMat0 && isInDynMat1); 1422 1423 // Compute result type. 1424 if (m_op == OP_MUL && isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType)) 1425 { 1426 resultType = getDataTypeMatrix(getDataTypeMatrixNumColumns(m_in1.dataType), getDataTypeMatrixNumRows(m_in0.dataType)); 1427 } 1428 else if (m_op == OP_OUTER_PRODUCT) 1429 { 1430 resultType = getDataTypeMatrix(getDataTypeScalarSize(m_in1.dataType), getDataTypeScalarSize(m_in0.dataType)); 1431 } 1432 else if (m_op == OP_TRANSPOSE) 1433 { 1434 resultType = getDataTypeMatrix(getDataTypeMatrixNumRows(m_in0.dataType), getDataTypeMatrixNumColumns(m_in0.dataType)); 1435 } 1436 else if (m_op == OP_INVERSE) 1437 { 1438 resultType = m_in0.dataType; 1439 } 1440 else if (m_op == OP_DETERMINANT) 1441 { 1442 resultType = TYPE_FLOAT; 1443 } 1444 else if (getOperationType(m_op) == OPERATIONTYPE_UNARY_PREFIX_OPERATOR || 1445 getOperationType(m_op) == OPERATIONTYPE_UNARY_POSTFIX_OPERATOR) 1446 { 1447 resultType = m_in0.dataType; 1448 } 1449 else if (isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType)) 1450 { 1451 DE_ASSERT(m_in0.dataType == m_in1.dataType); 1452 resultType = m_in0.dataType; 1453 } 1454 else if (isDataTypeMatrix(m_in0.dataType) || isDataTypeMatrix(m_in1.dataType)) 1455 { 1456 int matNdx = isDataTypeMatrix(m_in0.dataType) ? 0 : 1; 1457 DataType matrixType = matNdx == 0 ? m_in0.dataType : m_in1.dataType; 1458 DataType otherType = matNdx == 0 ? m_in1.dataType : m_in0.dataType; 1459 1460 if (otherType == TYPE_FLOAT) 1461 resultType = matrixType; 1462 else 1463 { 1464 DE_ASSERT(isDataTypeVector(otherType)); 1465 resultType = getDataTypeFloatVec(matNdx == 0 ? getDataTypeMatrixNumRows(matrixType) : getDataTypeMatrixNumColumns(matrixType)); 1466 } 1467 } 1468 else 1469 { 1470 DE_ASSERT(DE_FALSE); 1471 } 1472 1473 vtx << "#version 300 es\n"; 1474 frag << "#version 300 es\n"; 1475 1476 vtx << "in highp vec4 a_position;\n"; 1477 frag << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 1478 if (m_isVertexCase) 1479 { 1480 vtx << "out mediump vec4 v_color;\n"; 1481 frag << "in mediump vec4 v_color;\n"; 1482 } 1483 1484 // Input declarations. 1485 for (int inNdx = 0; inNdx < numInputs; inNdx++) 1486 { 1487 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0; 1488 const char* precName = getPrecisionName(in.precision); 1489 const char* typeName = getDataTypeName(in.dataType); 1490 string& inValue = inNdx > 0 ? inValue1 : inValue0; 1491 1492 if (in.inputType == INPUTTYPE_DYNAMIC) 1493 { 1494 vtx << "in " << precName << " " << typeName << " a_"; 1495 1496 if (isDataTypeMatrix(in.dataType)) 1497 { 1498 // a_matN, v_matN 1499 vtx << typeName << ";\n"; 1500 if (!m_isVertexCase) 1501 { 1502 vtx << "out " << precName << " " << typeName << " v_" << typeName << ";\n"; 1503 frag << "in " << precName << " " << typeName << " v_" << typeName << ";\n"; 1504 passVars.push_back(typeName); 1505 } 1506 1507 inValue = string(m_isVertexCase ? "a_" : "v_") + getDataTypeName(in.dataType); 1508 } 1509 else 1510 { 1511 // a_coords, v_coords 1512 vtx << "coords;\n"; 1513 if (!m_isVertexCase) 1514 { 1515 vtx << "out " << precName << " " << typeName << " v_coords;\n"; 1516 frag << "in " << precName << " " << typeName << " v_coords;\n"; 1517 passVars.push_back("coords"); 1518 } 1519 1520 inValue = m_isVertexCase ? "a_coords" : "v_coords"; 1521 } 1522 } 1523 else if (in.inputType == INPUTTYPE_UNIFORM) 1524 { 1525 op << "uniform " << precName << " " << typeName << " u_in" << inNdx << ";\n"; 1526 inValue = string("u_in") + de::toString(inNdx); 1527 } 1528 else if (in.inputType == INPUTTYPE_CONST) 1529 { 1530 op << "const " << precName << " " << typeName << " in" << inNdx << " = "; 1531 1532 // Generate declaration. 1533 switch (in.dataType) 1534 { 1535 case TYPE_FLOAT: op << de::floatToString(s_constInFloat[inNdx], 1); break; 1536 case TYPE_FLOAT_VEC2: writeVectorConstructor<2>(op, s_constInVec2[inNdx]); break; 1537 case TYPE_FLOAT_VEC3: writeVectorConstructor<3>(op, s_constInVec3[inNdx]); break; 1538 case TYPE_FLOAT_VEC4: writeVectorConstructor<4>(op, s_constInVec4[inNdx]); break; 1539 case TYPE_FLOAT_MAT2: writeMatrixConstructor<2, 2>(op, Mat2(s_constInMat2x2[inNdx])); break; 1540 case TYPE_FLOAT_MAT2X3: writeMatrixConstructor<2, 3>(op, Mat2x3(s_constInMat2x3[inNdx])); break; 1541 case TYPE_FLOAT_MAT2X4: writeMatrixConstructor<2, 4>(op, Mat2x4(s_constInMat2x4[inNdx])); break; 1542 case TYPE_FLOAT_MAT3X2: writeMatrixConstructor<3, 2>(op, Mat3x2(s_constInMat3x2[inNdx])); break; 1543 case TYPE_FLOAT_MAT3: writeMatrixConstructor<3, 3>(op, Mat3(s_constInMat3x3[inNdx])); break; 1544 case TYPE_FLOAT_MAT3X4: writeMatrixConstructor<3, 4>(op, Mat3x4(s_constInMat3x4[inNdx])); break; 1545 case TYPE_FLOAT_MAT4X2: writeMatrixConstructor<4, 2>(op, Mat4x2(s_constInMat4x2[inNdx])); break; 1546 case TYPE_FLOAT_MAT4X3: writeMatrixConstructor<4, 3>(op, Mat4x3(s_constInMat4x3[inNdx])); break; 1547 case TYPE_FLOAT_MAT4: writeMatrixConstructor<4, 4>(op, Mat4(s_constInMat4x4[inNdx])); break; 1548 1549 default: 1550 DE_ASSERT(DE_FALSE); 1551 } 1552 1553 op << ";\n"; 1554 1555 inValue = string("in") + de::toString(inNdx); 1556 } 1557 } 1558 1559 vtx << "\n" 1560 << "void main (void)\n" 1561 << "{\n" 1562 << " gl_Position = a_position;\n"; 1563 frag << "\n" 1564 << "void main (void)\n" 1565 << "{\n"; 1566 1567 if (m_isVertexCase) 1568 frag << " dEQP_FragColor = v_color;\n"; 1569 else 1570 { 1571 for (vector<string>::const_iterator copyIter = passVars.begin(); copyIter != passVars.end(); copyIter++) 1572 vtx << " v_" << *copyIter << " = " << "a_" << *copyIter << ";\n"; 1573 } 1574 1575 // Operation. 1576 1577 switch (getOperationNature(m_op)) 1578 { 1579 case OPERATIONNATURE_PURE: 1580 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT); 1581 1582 operationValue0 = inValue0; 1583 operationValue1 = inValue1; 1584 break; 1585 1586 case OPERATIONNATURE_MUTATING: 1587 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT); 1588 1589 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " tmpValue = " << inValue0 << ";\n"; 1590 1591 operationValue0 = "tmpValue"; 1592 operationValue1 = inValue1; 1593 break; 1594 1595 case OPERATIONNATURE_ASSIGNMENT: 1596 DE_ASSERT(getOperationType(m_op) == OPERATIONTYPE_ASSIGNMENT); 1597 1598 operationValue0 = inValue0; 1599 operationValue1 = inValue1; 1600 break; 1601 1602 default: 1603 DE_ASSERT(DE_FALSE); 1604 } 1605 1606 switch (getOperationType(m_op)) 1607 { 1608 case OPERATIONTYPE_BINARY_OPERATOR: 1609 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << " " << getOperationName(m_op) << " " << operationValue1 << ";\n"; 1610 break; 1611 1612 case OPERATIONTYPE_UNARY_PREFIX_OPERATOR: 1613 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << operationValue0 << ";\n"; 1614 break; 1615 1616 case OPERATIONTYPE_UNARY_POSTFIX_OPERATOR: 1617 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << getOperationName(m_op) << ";\n"; 1618 break; 1619 1620 case OPERATIONTYPE_BINARY_FUNCTION: 1621 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ", " << operationValue1 << ");\n"; 1622 break; 1623 1624 case OPERATIONTYPE_UNARY_FUNCTION: 1625 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ");\n"; 1626 break; 1627 1628 case OPERATIONTYPE_ASSIGNMENT: 1629 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << ";\n"; 1630 op << " res " << getOperationName(m_op) << " " << operationValue1 << ";\n"; 1631 break; 1632 1633 default: 1634 DE_ASSERT(DE_FALSE); 1635 } 1636 1637 // Reduction to vec3 (rgb). Check the used value too if it was modified 1638 op << " " << (m_isVertexCase ? "v_color" : "dEQP_FragColor") << " = "; 1639 1640 if (isOperationValueModifying(m_op)) 1641 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0) + vec4(" << genGLSLMatToVec3Reduction(resultType, "tmpValue") << ", 0.0);\n"; 1642 else 1643 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0);\n"; 1644 1645 vtx << "}\n"; 1646 frag << "}\n"; 1647 1648 m_vertShaderSource = vtx.str(); 1649 m_fragShaderSource = frag.str(); 1650 1651 // \todo [2012-02-14 pyry] Compute better values for matrix tests. 1652 m_userAttribTransforms.resize(4); 1653 for (int attribNdx = 0; attribNdx < 4; attribNdx++) 1654 { 1655 m_userAttribTransforms[attribNdx] = Mat4(0.0f); 1656 m_userAttribTransforms[attribNdx]( 0, 3) = 0.1f + 0.1f * float(attribNdx); // !< prevent matrix*vec from going into zero (assuming vec.w != 0) 1657 m_userAttribTransforms[attribNdx]( 1, 3) = 0.2f + 0.1f * float(attribNdx); // !< 1658 m_userAttribTransforms[attribNdx]( 2, 3) = 0.3f + 0.1f * float(attribNdx); // !< 1659 m_userAttribTransforms[attribNdx]( 3, 3) = 0.4f + 0.1f * float(attribNdx); // !< 1660 m_userAttribTransforms[attribNdx]((0 + attribNdx) % 4, 0) = 1.0f; 1661 m_userAttribTransforms[attribNdx]((1 + attribNdx) % 4, 1) = 1.0f; 1662 m_userAttribTransforms[attribNdx]((2 + attribNdx) % 4, 2) = 1.0f; 1663 m_userAttribTransforms[attribNdx]((3 + attribNdx) % 4, 3) = 1.0f; 1664 } 1665 1666 // prevent bad reference cases such as black result images by fine-tuning used matrices 1667 if (getOperationTestMatrixType(m_op) != TESTMATRIXTYPE_DEFAULT) 1668 { 1669 for (int attribNdx = 0; attribNdx < 4; attribNdx++) 1670 { 1671 for (int row = 0; row < 4; row++) 1672 for (int col = 0; col < 4; col++) 1673 { 1674 switch (getOperationTestMatrixType(m_op)) 1675 { 1676 case TESTMATRIXTYPE_NEGATED: 1677 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col); 1678 break; 1679 case TESTMATRIXTYPE_INCREMENTED: 1680 m_userAttribTransforms[attribNdx](row, col) += 0.3f; 1681 break; 1682 case TESTMATRIXTYPE_DECREMENTED: 1683 m_userAttribTransforms[attribNdx](row, col) -= 0.3f; 1684 break; 1685 case TESTMATRIXTYPE_NEGATED_INCREMENTED: 1686 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col) + 0.3f; 1687 break; 1688 case TESTMATRIXTYPE_INCREMENTED_LESS: 1689 m_userAttribTransforms[attribNdx](row, col) -= 0.1f; 1690 break; 1691 1692 default: 1693 DE_ASSERT(DE_FALSE); 1694 break; 1695 } 1696 } 1697 } 1698 } 1699 // The verification code doesn't deal with reduced precision, so we must quantize the data 1700 // here to try to avoid verification errors. No implementation seems to use lowp, so reduce 1701 // to mediump. 1702 if(resultPrec != PRECISION_HIGHP) 1703 { 1704 for (int attribNdx = 0; attribNdx < 4; attribNdx++) 1705 { 1706 for (int row = 0; row < 4; row++) 1707 for (int col = 0; col < 4; col++) 1708 { 1709 m_userAttribTransforms[attribNdx](row, col) = deFloat16To32(deFloat32To16(m_userAttribTransforms[attribNdx](row, col))); 1710 } 1711 } 1712 } 1713 1714 ShaderRenderCase::init(); 1715} 1716 1717std::string ShaderMatrixCase::genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName) 1718{ 1719 std::ostringstream op; 1720 1721 switch (matType) 1722 { 1723 case TYPE_FLOAT: op << varName << ", " << varName << ", " << varName << ""; break; 1724 case TYPE_FLOAT_VEC2: op << varName << ".x, " << varName << ".y, " << varName << ".x"; break; 1725 case TYPE_FLOAT_VEC3: op << varName << ""; break; 1726 case TYPE_FLOAT_VEC4: op << varName << ".x, " << varName << ".y, " << varName << ".z+" << varName << ".w"; break; 1727 case TYPE_FLOAT_MAT2: op << varName << "[0][0], " << varName << "[1][0], " << varName << "[0][1]+" << varName << "[1][1]"; break; 1728 case TYPE_FLOAT_MAT2X3: op << varName << "[0] + " << varName << "[1]"; break; 1729 case TYPE_FLOAT_MAT2X4: op << varName << "[0].xyz + " << varName << "[1].yzw"; break; 1730 case TYPE_FLOAT_MAT3X2: op << varName << "[0][0]+" << varName << "[0][1], " << varName << "[1][0]+" << varName << "[1][1], " << varName << "[2][0]+" << varName << "[2][1]"; break; 1731 case TYPE_FLOAT_MAT3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2]"; break; 1732 case TYPE_FLOAT_MAT3X4: op << varName << "[0].xyz + " << varName << "[1].yzw + " << varName << "[2].zwx"; break; 1733 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; 1734 case TYPE_FLOAT_MAT4X3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2] + " << varName << "[3]"; break; 1735 case TYPE_FLOAT_MAT4: op << varName << "[0].xyz+" << varName << "[1].yzw+" << varName << "[2].zwx+" << varName << "[3].wxy"; break; 1736 1737 default: 1738 DE_ASSERT(DE_FALSE); 1739 } 1740 1741 return op.str(); 1742} 1743 1744void ShaderMatrixCase::setupUniforms (int programID, const tcu::Vec4& constCoords) 1745{ 1746 const glw::Functions& gl = m_renderCtx.getFunctions(); 1747 1748 DE_UNREF(constCoords); 1749 1750 for (int inNdx = 0; inNdx < 2; inNdx++) 1751 { 1752 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0; 1753 1754 if (in.inputType == INPUTTYPE_UNIFORM) 1755 { 1756 int loc = gl.getUniformLocation(programID, (string("u_in") + de::toString(inNdx)).c_str()); 1757 1758 if (loc < 0) 1759 continue; 1760 1761 switch (in.dataType) 1762 { 1763 case TYPE_FLOAT: gl.uniform1f(loc, s_constInFloat[inNdx]); break; 1764 case TYPE_FLOAT_VEC2: gl.uniform2fv(loc, 1, s_constInVec2[inNdx].getPtr()); break; 1765 case TYPE_FLOAT_VEC3: gl.uniform3fv(loc, 1, s_constInVec3[inNdx].getPtr()); break; 1766 case TYPE_FLOAT_VEC4: gl.uniform4fv(loc, 1, s_constInVec4[inNdx].getPtr()); break; 1767 // \note GLES3 supports transpose in matrix upload. 1768 case TYPE_FLOAT_MAT2: gl.uniformMatrix2fv (loc, 1, GL_TRUE, s_constInMat2x2[inNdx]); break; 1769 case TYPE_FLOAT_MAT2X3: gl.uniformMatrix2x3fv(loc, 1, GL_TRUE, s_constInMat2x3[inNdx]); break; 1770 case TYPE_FLOAT_MAT2X4: gl.uniformMatrix2x4fv(loc, 1, GL_TRUE, s_constInMat2x4[inNdx]); break; 1771 case TYPE_FLOAT_MAT3X2: gl.uniformMatrix3x2fv(loc, 1, GL_TRUE, s_constInMat3x2[inNdx]); break; 1772 case TYPE_FLOAT_MAT3: gl.uniformMatrix3fv (loc, 1, GL_TRUE, s_constInMat3x3[inNdx]); break; 1773 case TYPE_FLOAT_MAT3X4: gl.uniformMatrix3x4fv(loc, 1, GL_TRUE, s_constInMat3x4[inNdx]); break; 1774 case TYPE_FLOAT_MAT4X2: gl.uniformMatrix4x2fv(loc, 1, GL_TRUE, s_constInMat4x2[inNdx]); break; 1775 case TYPE_FLOAT_MAT4X3: gl.uniformMatrix4x3fv(loc, 1, GL_TRUE, s_constInMat4x3[inNdx]); break; 1776 case TYPE_FLOAT_MAT4: gl.uniformMatrix4fv (loc, 1, GL_TRUE, s_constInMat4x4[inNdx]); break; 1777 default: 1778 DE_ASSERT(false); 1779 } 1780 } 1781 } 1782} 1783 1784ShaderMatrixTests::ShaderMatrixTests (Context& context) 1785 : TestCaseGroup(context, "matrix", "Matrix Tests") 1786{ 1787} 1788 1789ShaderMatrixTests::~ShaderMatrixTests (void) 1790{ 1791} 1792 1793void ShaderMatrixTests::init (void) 1794{ 1795 static const struct 1796 { 1797 const char* name; 1798 const char* desc; 1799 MatrixOp op; 1800 bool extendedInputTypeCases; // !< test with const and uniform types too 1801 bool createInputTypeGroup; // !< create group for input types 1802 } ops[] = 1803 { 1804 { "add", "Matrix addition tests", OP_ADD, true, true }, 1805 { "sub", "Matrix subtraction tests", OP_SUB, true, true }, 1806 { "mul", "Matrix multiplication tests", OP_MUL, true, true }, 1807 { "div", "Matrix division tests", OP_DIV, true, true }, 1808 { "matrixcompmult", "Matrix component-wise multiplication tests", OP_COMP_MUL, false, true }, 1809 { "outerproduct", "Matrix outerProduct() tests", OP_OUTER_PRODUCT, false, true }, 1810 { "transpose", "Matrix transpose() tests", OP_TRANSPOSE, false, true }, 1811 { "determinant", "Matrix determinant() tests", OP_DETERMINANT, false, true }, 1812 { "inverse", "Matrix inverse() tests", OP_INVERSE, false, true }, 1813 { "unary_addition", "Matrix unary addition tests", OP_UNARY_PLUS, false, false }, 1814 { "negation", "Matrix negation tests", OP_NEGATION, false, false }, 1815 { "pre_increment", "Matrix prefix increment tests", OP_PRE_INCREMENT, false, false }, 1816 { "pre_decrement", "Matrix prefix decrement tests", OP_PRE_DECREMENT, false, false }, 1817 { "post_increment", "Matrix postfix increment tests", OP_POST_INCREMENT, false, false }, 1818 { "post_decrement", "Matrix postfix decrement tests", OP_POST_DECREMENT, false, false }, 1819 { "add_assign", "Matrix add into tests", OP_ADD_INTO, false, false }, 1820 { "sub_assign", "Matrix subtract from tests", OP_SUBTRACT_FROM, false, false }, 1821 { "mul_assign", "Matrix multiply into tests", OP_MULTIPLY_INTO, false, false }, 1822 { "div_assign", "Matrix divide into tests", OP_DIVIDE_INTO, false, false }, 1823 }; 1824 1825 struct InputTypeSpec 1826 { 1827 const char* name; 1828 const char* desc; 1829 InputType type; 1830 }; 1831 static const InputTypeSpec extendedInputTypes[] = 1832 { 1833 { "const", "Constant matrix input", INPUTTYPE_CONST }, 1834 { "uniform", "Uniform matrix input", INPUTTYPE_UNIFORM }, 1835 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC } 1836 }; 1837 static const InputTypeSpec reducedInputTypes[] = 1838 { 1839 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC } 1840 }; 1841 1842 static const DataType matrixTypes[] = 1843 { 1844 TYPE_FLOAT_MAT2, 1845 TYPE_FLOAT_MAT2X3, 1846 TYPE_FLOAT_MAT2X4, 1847 TYPE_FLOAT_MAT3X2, 1848 TYPE_FLOAT_MAT3, 1849 TYPE_FLOAT_MAT3X4, 1850 TYPE_FLOAT_MAT4X2, 1851 TYPE_FLOAT_MAT4X3, 1852 TYPE_FLOAT_MAT4 1853 }; 1854 1855 static const Precision precisions[] = 1856 { 1857 PRECISION_LOWP, 1858 PRECISION_MEDIUMP, 1859 PRECISION_HIGHP 1860 }; 1861 1862 for (int opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++) 1863 { 1864 const InputTypeSpec* inTypeList = (ops[opNdx].extendedInputTypeCases) ? (extendedInputTypes) : (reducedInputTypes); 1865 const int inTypeListSize = (ops[opNdx].extendedInputTypeCases) ? (DE_LENGTH_OF_ARRAY(extendedInputTypes)) : (DE_LENGTH_OF_ARRAY(reducedInputTypes)); 1866 const MatrixOp op = ops[opNdx].op; 1867 tcu::TestCaseGroup* opGroup = new tcu::TestCaseGroup(m_testCtx, ops[opNdx].name, ops[opNdx].desc); 1868 1869 addChild(opGroup); 1870 1871 for (int inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++) 1872 { 1873 const InputType inputType = inTypeList[inTypeNdx].type; 1874 tcu::TestCaseGroup* inGroup; 1875 1876 if (ops[opNdx].createInputTypeGroup) 1877 { 1878 inGroup = new tcu::TestCaseGroup(m_testCtx, inTypeList[inTypeNdx].name, inTypeList[inTypeNdx].desc); 1879 opGroup->addChild(inGroup); 1880 } 1881 else 1882 inGroup = opGroup; 1883 1884 for (int matTypeNdx = 0; matTypeNdx < DE_LENGTH_OF_ARRAY(matrixTypes); matTypeNdx++) 1885 { 1886 DataType matType = matrixTypes[matTypeNdx]; 1887 int numCols = getDataTypeMatrixNumColumns(matType); 1888 int numRows = getDataTypeMatrixNumRows(matType); 1889 const char* matTypeName = getDataTypeName(matType); 1890 1891 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++) 1892 { 1893 Precision precision = precisions[precNdx]; 1894 const char* precName = getPrecisionName(precision); 1895 string baseName = string(precName) + "_" + matTypeName + "_"; 1896 ShaderInput matIn (inputType, matType, precision); 1897 1898 if (isOperationMatrixScalar(op)) 1899 { 1900 // Matrix-scalar \note For div cases we use uniform input. 1901 ShaderInput scalarIn(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, TYPE_FLOAT, precision); 1902 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(), "Matrix-scalar case", matIn, scalarIn, op, true)); 1903 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(), "Matrix-scalar case", matIn, scalarIn, op, false)); 1904 } 1905 1906 if (isOperationMatrixVector(op)) 1907 { 1908 // Matrix-vector. 1909 DataType colVecType = getDataTypeFloatVec(numCols); 1910 ShaderInput colVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, colVecType, precision); 1911 1912 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(colVecType) + "_vertex").c_str(), "Matrix-vector case", matIn, colVecIn, op, true)); 1913 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(colVecType) + "_fragment").c_str(), "Matrix-vector case", matIn, colVecIn, op, false)); 1914 1915 // Vector-matrix. 1916 DataType rowVecType = getDataTypeFloatVec(numRows); 1917 ShaderInput rowVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, rowVecType, precision); 1918 string vecMatName = string(precName) + "_" + getDataTypeName(rowVecType) + "_" + matTypeName; 1919 1920 inGroup->addChild(new ShaderMatrixCase(m_context, (vecMatName + "_vertex").c_str(), "Vector-matrix case", rowVecIn, matIn, op, true)); 1921 inGroup->addChild(new ShaderMatrixCase(m_context, (vecMatName + "_fragment").c_str(), "Vector-matrix case", rowVecIn, matIn, op, false)); 1922 } 1923 1924 if (isOperationArithmeticMatrixMatrix(op)) 1925 { 1926 // Arithmetic matrix-matrix multiplication. 1927 for (int otherCols = 2; otherCols <= 4; otherCols++) 1928 { 1929 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, getDataTypeMatrix(otherCols, numCols /* rows */), precision); 1930 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(otherMatIn.dataType) + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true)); 1931 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(otherMatIn.dataType) + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false)); 1932 } 1933 } 1934 else if (isOperationComponentwiseMatrixMatrix(op)) 1935 { 1936 // Component-wise. 1937 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision); 1938 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + matTypeName + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true)); 1939 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + matTypeName + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false)); 1940 } 1941 1942 if (isOperationVectorVector(op)) 1943 { 1944 ShaderInput vec1In(inputType, getDataTypeFloatVec(numRows), precision); 1945 ShaderInput vec2In((inputType == INPUTTYPE_DYNAMIC) ? (INPUTTYPE_UNIFORM) : (inputType), getDataTypeFloatVec(numCols), precision); 1946 1947 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(), "Vector-vector case", vec1In, vec2In, op, true)); 1948 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(), "Vector-vector case", vec1In, vec2In, op, false)); 1949 } 1950 1951 if ((isOperationUnaryAnyMatrix(op)) || 1952 (isOperationUnarySymmetricMatrix(op) && numCols == numRows)) 1953 { 1954 ShaderInput voidInput(INPUTTYPE_LAST, TYPE_LAST, PRECISION_LAST); 1955 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(), "Matrix case", matIn, voidInput, op, true)); 1956 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(), "Matrix case", matIn, voidInput, op, false)); 1957 } 1958 1959 if ((isOperationAssignmentAnyMatrix(op)) || 1960 (isOperationAssignmentSymmetricMatrix(op) && numCols == numRows)) 1961 { 1962 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision); 1963 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(), "Matrix assignment case", matIn, otherMatIn, op, true)); 1964 inGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(), "Matrix assignment case", matIn, otherMatIn, op, false)); 1965 } 1966 } 1967 } 1968 } 1969 } 1970} 1971 1972} // Functional 1973} // gles3 1974} // deqp 1975 1976#if defined(_MSC_VER) && _MSC_FULL_VER == 191125507 1977// Work around crbug.com/759402 which is a code-gen bug in VC++ 2017, version 1978// 15.3.2. 1979#pragma optimize("", off) 1980#endif 1981