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