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