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