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