Merge vk-gl-cts/opengl-es-cts-3.2.3 into vk-gl-cts/opengl-es-cts-3.2.4
[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 // outerProduct
631
632 template <typename T, int Rows, int Cols>
633 tcu::Matrix<T, Cols, Rows> outerProduct (const tcu::Vector<T, Cols>& a, const tcu::Vector<T, Rows>& b)
634 {
635         tcu::Matrix<T, Rows, Cols> retVal;
636
637         for (int r = 0; r < Rows; ++r)
638                 for (int c = 0; c < Cols; ++c)
639                         retVal(r,c) = a[c] * b[r];
640
641         return transpose(retVal); // to gl-form (column-major)
642 }
643
644 // Determinant
645
646 template <int Size>
647 float determinant (const tcu::Matrix<float, Size, Size>& mat);
648
649 template <>
650 float determinant<2> (const tcu::Matrix<float, 2, 2>& mat)
651 {
652         return mat(0,0) * mat(1,1) - mat(1,0) * mat(0,1);
653 }
654
655 template <>
656 float determinant<3> (const tcu::Matrix<float, 3, 3>& mat)
657 {
658         return  + mat(0,0) * mat(1,1) * mat(2,2)
659                         + mat(0,1) * mat(1,2) * mat(2,0)
660                         + mat(0,2) * mat(1,0) * mat(2,1)
661                         - mat(0,0) * mat(1,2) * mat(2,1)
662                         - mat(0,1) * mat(1,0) * mat(2,2)
663                         - mat(0,2) * mat(1,1) * mat(2,0);
664 }
665
666 template <>
667 float determinant<4> (const tcu::Matrix<float, 4, 4>& mat)
668 {
669         const float minorMatrices[4][3*3] =
670         {
671                 {
672                         mat(1,1),       mat(2,1),       mat(3,1),
673                         mat(1,2),       mat(2,2),       mat(3,2),
674                         mat(1,3),       mat(2,3),       mat(3,3),
675                 },
676                 {
677                         mat(1,0),       mat(2,0),       mat(3,0),
678                         mat(1,2),       mat(2,2),       mat(3,2),
679                         mat(1,3),       mat(2,3),       mat(3,3),
680                 },
681                 {
682                         mat(1,0),       mat(2,0),       mat(3,0),
683                         mat(1,1),       mat(2,1),       mat(3,1),
684                         mat(1,3),       mat(2,3),       mat(3,3),
685                 },
686                 {
687                         mat(1,0),       mat(2,0),       mat(3,0),
688                         mat(1,1),       mat(2,1),       mat(3,1),
689                         mat(1,2),       mat(2,2),       mat(3,2),
690                 }
691         };
692
693         return  + mat(0,0) * determinant(tcu::Mat3(minorMatrices[0]))
694                         - mat(0,1) * determinant(tcu::Mat3(minorMatrices[1]))
695                         + mat(0,2) * determinant(tcu::Mat3(minorMatrices[2]))
696                         - mat(0,3) * determinant(tcu::Mat3(minorMatrices[3]));
697 }
698
699 // Inverse
700
701 template <int Size>
702 tcu::Matrix<float, Size, Size> inverse (const tcu::Matrix<float, Size, Size>& mat);
703
704 template <>
705 tcu::Matrix<float, 2, 2> inverse<2> (const tcu::Matrix<float, 2, 2>& mat)
706 {
707         const float                                     det             = determinant(mat);
708         tcu::Matrix<float, 2, 2>        retVal;
709
710         DE_ASSERT(det != 0.0f);
711
712         retVal(0, 0) =  mat(1, 1) / det;
713         retVal(0, 1) = -mat(0, 1) / det;
714         retVal(1, 0) = -mat(1, 0) / det;
715         retVal(1, 1) =  mat(0, 0) / det;
716
717         return retVal;
718 }
719
720 template <>
721 tcu::Matrix<float, 3, 3> inverse<3> (const tcu::Matrix<float, 3, 3>& mat)
722 {
723         // Blockwise inversion
724
725         DE_ASSERT(determinant(mat) != 0.0f);
726
727         const float areaA[2*2] =
728         {
729                 mat(0,0),       mat(0,1),
730                 mat(1,0),       mat(1,1)
731         };
732         const float areaB[2] =
733         {
734                 mat(0,2),
735                 mat(1,2),
736         };
737         const float areaC[2] =
738         {
739                 mat(2,0),       mat(2,1),
740         };
741         const float areaD[1] =
742         {
743                 mat(2,2)
744         };
745         const float nullField[4] = { 0.0f };
746
747         const tcu::Matrix<float, 2, 2>  invA = inverse(tcu::Matrix<float, 2, 2>(areaA));
748         const tcu::Matrix<float, 2, 1>  matB =         tcu::Matrix<float, 2, 1>(areaB);
749         const tcu::Matrix<float, 1, 2>  matC =         tcu::Matrix<float, 1, 2>(areaC);
750         const tcu::Matrix<float, 1, 1>  matD =         tcu::Matrix<float, 1, 1>(areaD);
751
752         const float                                             schurComplement = 1.0f / (matD - matC*invA*matB)(0,0);
753         const tcu::Matrix<float, 2, 2>  zeroMat         = Mat2(nullField);
754
755         const tcu::Matrix<float, 2, 2>  blockA = invA + invA*matB*schurComplement*matC*invA;
756         const tcu::Matrix<float, 2, 1>  blockB = (zeroMat-invA)*matB*schurComplement;
757         const tcu::Matrix<float, 1, 2>  blockC = matC*invA*(-schurComplement);
758         const float                                             blockD = schurComplement;
759
760         const float result[3*3] =
761         {
762                 blockA(0,0),    blockA(0,1),    blockB(0,0),
763                 blockA(1,0),    blockA(1,1),    blockB(1,0),
764                 blockC(0,0),    blockC(0,1),    blockD,
765         };
766
767         return Mat3(result);
768 }
769
770 template <>
771 tcu::Matrix<float, 4, 4> inverse<4> (const tcu::Matrix<float, 4, 4>& mat)
772 {
773         // Blockwise inversion
774
775         DE_ASSERT(determinant(mat) != 0.0f);
776
777         const float areaA[2*2] =
778         {
779                 mat(0,0),       mat(0,1),
780                 mat(1,0),       mat(1,1)
781         };
782         const float areaB[2*2] =
783         {
784                 mat(0,2),       mat(0,3),
785                 mat(1,2),       mat(1,3)
786         };
787         const float areaC[2*2] =
788         {
789                 mat(2,0),       mat(2,1),
790                 mat(3,0),       mat(3,1)
791         };
792         const float areaD[2*2] =
793         {
794                 mat(2,2),       mat(2,3),
795                 mat(3,2),       mat(3,3)
796         };
797         const float nullField[4] = { 0.0f };
798
799         const tcu::Matrix<float, 2, 2> invA = inverse(Mat2(areaA));
800         const tcu::Matrix<float, 2, 2> matB =         Mat2(areaB);
801         const tcu::Matrix<float, 2, 2> matC =         Mat2(areaC);
802         const tcu::Matrix<float, 2, 2> matD =         Mat2(areaD);
803
804         const tcu::Matrix<float, 2, 2> schurComplement = inverse(matD - matC*invA*matB);
805         const tcu::Matrix<float, 2, 2> zeroMat         = Mat2(nullField);
806
807         const tcu::Matrix<float, 2, 2> blockA = invA + invA*matB*schurComplement*matC*invA;
808         const tcu::Matrix<float, 2, 2> blockB = (zeroMat-invA)*matB*schurComplement;
809         const tcu::Matrix<float, 2, 2> blockC = (zeroMat-schurComplement)*matC*invA;
810         const tcu::Matrix<float, 2, 2> blockD = schurComplement;
811
812         const float result[4*4] =
813         {
814                 blockA(0,0),    blockA(0,1),    blockB(0,0),    blockB(0,1),
815                 blockA(1,0),    blockA(1,1),    blockB(1,0),    blockB(1,1),
816                 blockC(0,0),    blockC(0,1),    blockD(0,0),    blockD(0,1),
817                 blockC(1,0),    blockC(1,1),    blockD(1,0),    blockD(1,1),
818         };
819
820         return Mat4(result);
821 }
822
823 // negate
824
825 template <typename T, int Rows, int Cols>
826 tcu::Matrix<T, Rows, Cols> negate (const tcu::Matrix<T, Rows, Cols>& mat)
827 {
828         tcu::Matrix<T, Rows, Cols> retVal;
829
830         for (int r = 0; r < Rows; ++r)
831                 for (int c = 0; c < Cols; ++c)
832                         retVal(r,c) = -mat(r, c);
833
834         return retVal;
835 }
836
837 // increment/decrement
838
839 template <typename T, int Rows, int Cols>
840 tcu::Matrix<T, Rows, Cols> increment (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) + 1.0f;
847
848         return retVal;
849 }
850
851 template <typename T, int Rows, int Cols>
852 tcu::Matrix<T, Rows, Cols> decrement (const tcu::Matrix<T, Rows, Cols>& mat)
853 {
854         tcu::Matrix<T, Rows, Cols> retVal;
855
856         for (int r = 0; r < Rows; ++r)
857                 for (int c = 0; c < Cols; ++c)
858                         retVal(r,c) = mat(r, c) - 1.0f;
859
860         return retVal;
861 }
862
863 // Evaluator template.
864
865 typedef void (*MatrixShaderEvalFunc) (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type);
866
867 template <int Op, int In0DataType, int In1DataType>
868 struct Evaluator;
869
870 template <int In0DataType, int In1DataType>
871 struct Evaluator<OP_ADD, In0DataType, In1DataType>
872 {
873         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
874         {
875                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
876                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
877                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
878                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
879                 evalCtx.color.xyz() = reduceToVec3(in0 + in1);
880         }
881 };
882
883 template <int In0DataType, int In1DataType>
884 struct Evaluator<OP_SUB, In0DataType, In1DataType>
885 {
886         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
887         {
888                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
889                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
890                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
891                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
892                 evalCtx.color.xyz() = reduceToVec3(in0 - in1);
893         }
894 };
895
896 template <int In0DataType, int In1DataType>
897 struct Evaluator<OP_MUL, In0DataType, In1DataType>
898 {
899         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
900         {
901                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
902                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
903                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
904                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
905                 evalCtx.color.xyz() = reduceToVec3(in0 * in1);
906         }
907 };
908
909 template <int In0DataType, int In1DataType>
910 struct Evaluator<OP_DIV, In0DataType, In1DataType>
911 {
912         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
913         {
914                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
915                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
916                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
917                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
918                 evalCtx.color.xyz() = reduceToVec3(in0 / in1);
919         }
920 };
921
922 template <int In0DataType, int In1DataType>
923 struct Evaluator<OP_COMP_MUL, In0DataType, In1DataType>
924 {
925         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
926         {
927                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
928                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
929                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
930                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
931                 evalCtx.color.xyz() = reduceToVec3(matrixCompMult(in0, in1));
932         }
933 };
934
935 template <int In0DataType, int In1DataType>
936 struct Evaluator<OP_OUTER_PRODUCT, In0DataType, In1DataType>
937 {
938         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
939         {
940                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
941                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
942                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
943                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
944                 evalCtx.color.xyz() = reduceToVec3(outerProduct(in0, in1));
945         }
946 };
947
948 template <int In0DataType, int In1DataType>
949 struct Evaluator<OP_TRANSPOSE, In0DataType, In1DataType>
950 {
951         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
952         {
953                 DE_UNREF(in1Type);
954                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
955                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
956                 evalCtx.color.xyz() = reduceToVec3(transpose(in0));
957         }
958 };
959
960 template <int In0DataType, int In1DataType>
961 struct Evaluator<OP_INVERSE, In0DataType, In1DataType>
962 {
963         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
964         {
965                 DE_UNREF(in1Type);
966                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
967                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
968                 evalCtx.color.xyz() = reduceToVec3(inverse(in0));
969         }
970 };
971
972 template <int In0DataType, int In1DataType>
973 struct Evaluator<OP_DETERMINANT, In0DataType, In1DataType>
974 {
975         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
976         {
977                 DE_UNREF(in1Type);
978                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
979                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
980                 evalCtx.color.xyz() = Vec3(determinant(in0));
981         }
982 };
983
984 template <int In0DataType, int In1DataType>
985 struct Evaluator<OP_UNARY_PLUS, In0DataType, In1DataType>
986 {
987         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
988         {
989                 DE_UNREF(in1Type);
990                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
991                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
992                 evalCtx.color.xyz() = reduceToVec3(in0);
993         }
994 };
995
996 template <int In0DataType, int In1DataType>
997 struct Evaluator<OP_NEGATION, In0DataType, In1DataType>
998 {
999         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1000         {
1001                 DE_UNREF(in1Type);
1002                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1003                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
1004                 evalCtx.color.xyz() = reduceToVec3(negate(in0));
1005         }
1006 };
1007
1008 template <int In0DataType, int In1DataType>
1009 struct Evaluator<OP_PRE_INCREMENT, In0DataType, In1DataType>
1010 {
1011         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1012         {
1013                 DE_UNREF(in1Type);
1014                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1015                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
1016
1017                 // modifying reduction: sum modified value too
1018                 evalCtx.color.xyz() = reduceToVec3(increment(in0)) + reduceToVec3(increment(in0));
1019         }
1020 };
1021
1022 template <int In0DataType, int In1DataType>
1023 struct Evaluator<OP_PRE_DECREMENT, 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(decrement(in0)) + reduceToVec3(decrement(in0));
1033         }
1034 };
1035
1036 template <int In0DataType, int In1DataType>
1037 struct Evaluator<OP_POST_INCREMENT, 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(in0) + reduceToVec3(increment(in0));
1047         }
1048 };
1049
1050 template <int In0DataType, int In1DataType>
1051 struct Evaluator<OP_POST_DECREMENT, 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(decrement(in0));
1061         }
1062 };
1063
1064 template <int In0DataType, int In1DataType>
1065 struct Evaluator<OP_ADD_INTO, In0DataType, In1DataType>
1066 {
1067         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1068         {
1069                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1070                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
1071                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1072                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
1073                 evalCtx.color.xyz() = reduceToVec3(in0 + in1);
1074         }
1075 };
1076
1077 template <int In0DataType, int In1DataType>
1078 struct Evaluator<OP_SUBTRACT_FROM, In0DataType, In1DataType>
1079 {
1080         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1081         {
1082                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1083                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
1084                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1085                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
1086                 evalCtx.color.xyz() = reduceToVec3(in0 - in1);
1087         }
1088 };
1089
1090 template <int In0DataType, int In1DataType>
1091 struct Evaluator<OP_MULTIPLY_INTO, In0DataType, In1DataType>
1092 {
1093         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1094         {
1095                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1096                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
1097                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1098                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
1099                 evalCtx.color.xyz() = reduceToVec3(in0 * in1);
1100         }
1101 };
1102
1103 template <int In0DataType, int In1DataType>
1104 struct Evaluator<OP_DIVIDE_INTO, In0DataType, In1DataType>
1105 {
1106         static void evaluate (ShaderEvalContext& evalCtx, InputType in0Type, InputType in1Type)
1107         {
1108                 typename TypeTraits<In0DataType>::Type  in0     = (in0Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In0DataType>(evalCtx, 0)
1109                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In0DataType>(evalCtx, 0);
1110                 typename TypeTraits<In1DataType>::Type  in1     = (in1Type == INPUTTYPE_DYNAMIC) ? getInputValue<INPUTTYPE_DYNAMIC, In1DataType>(evalCtx, 1)
1111                                                                                                                                                                      : getInputValue<INPUTTYPE_CONST,   In1DataType>(evalCtx, 1);
1112                 evalCtx.color.xyz() = reduceToVec3(in0 / in1);
1113         }
1114 };
1115
1116 MatrixShaderEvalFunc getEvalFunc (const ShaderInput& in0, const ShaderInput& in1, MatrixOp op)
1117 {
1118         // Evaluator is selected based on op and input data types.
1119         // For efficient lookup the types and op enums are packed together to form a 19-bit key:
1120         // [18..14 OP] [13..7 TYPE0] [6..0 TYPE1]
1121
1122         DE_STATIC_ASSERT(TYPE_LAST      <= (1<<7));
1123         DE_STATIC_ASSERT(OP_LAST        <= (1<<5));
1124
1125 #define PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE)    (((OP) << 14) | ((IN0DATATYPE) << 7) | (IN1DATATYPE))
1126
1127 #define MAKE_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE)    \
1128         case PACK_EVAL_CASE(OP, IN0DATATYPE, IN1DATATYPE):      \
1129                 return Evaluator<OP, IN0DATATYPE, IN1DATATYPE>::evaluate
1130
1131 #define MAKE_SCALAR_OPS(IN0DATATYPE, IN1DATATYPE)               \
1132         MAKE_EVAL_CASE(OP_ADD, IN0DATATYPE, IN1DATATYPE);       \
1133         MAKE_EVAL_CASE(OP_SUB, IN0DATATYPE, IN1DATATYPE);       \
1134         MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE);       \
1135         MAKE_EVAL_CASE(OP_DIV, IN0DATATYPE, IN1DATATYPE)
1136
1137 #define MAKE_CWISE_OPS(IN0DATATYPE, IN1DATATYPE)                        \
1138         MAKE_EVAL_CASE(OP_ADD,          IN0DATATYPE, IN1DATATYPE);      \
1139         MAKE_EVAL_CASE(OP_SUB,          IN0DATATYPE, IN1DATATYPE);      \
1140         MAKE_EVAL_CASE(OP_DIV,          IN0DATATYPE, IN1DATATYPE);      \
1141         MAKE_EVAL_CASE(OP_COMP_MUL,     IN0DATATYPE, IN1DATATYPE)
1142
1143 #define MAKE_MUL_OP(IN0DATATYPE, IN1DATATYPE)                   \
1144         MAKE_EVAL_CASE(OP_MUL, IN0DATATYPE, IN1DATATYPE)
1145
1146 #define MAKE_VECVEC_OP(IN0DATATYPE, IN1DATATYPE)                        \
1147         MAKE_EVAL_CASE(OP_OUTER_PRODUCT, IN0DATATYPE, IN1DATATYPE)
1148
1149 #define MAKE_UNARY_OP(IN0DATATYPE)                                                              \
1150         MAKE_EVAL_CASE(OP_TRANSPOSE,            IN0DATATYPE, TYPE_LAST);        \
1151         MAKE_EVAL_CASE(OP_UNARY_PLUS,           IN0DATATYPE, TYPE_LAST);        \
1152         MAKE_EVAL_CASE(OP_NEGATION,                     IN0DATATYPE, TYPE_LAST);        \
1153         MAKE_EVAL_CASE(OP_PRE_INCREMENT,        IN0DATATYPE, TYPE_LAST);        \
1154         MAKE_EVAL_CASE(OP_PRE_DECREMENT,        IN0DATATYPE, TYPE_LAST);        \
1155         MAKE_EVAL_CASE(OP_POST_INCREMENT,       IN0DATATYPE, TYPE_LAST);        \
1156         MAKE_EVAL_CASE(OP_POST_DECREMENT,       IN0DATATYPE, TYPE_LAST)
1157
1158 #define MAKE_UNARY_SYMMETRIC_OP(IN0DATATYPE)                                    \
1159         MAKE_UNARY_OP(IN0DATATYPE);                                                                     \
1160         MAKE_EVAL_CASE(OP_DETERMINANT,  IN0DATATYPE, TYPE_LAST);        \
1161         MAKE_EVAL_CASE(OP_INVERSE,              IN0DATATYPE, TYPE_LAST)
1162
1163 #define MAKE_ASSIGNMENT_OP(IN0DATATYPE)                                                         \
1164         MAKE_EVAL_CASE(OP_ADD_INTO,                     IN0DATATYPE, IN0DATATYPE);      \
1165         MAKE_EVAL_CASE(OP_SUBTRACT_FROM,        IN0DATATYPE, IN0DATATYPE);      \
1166         MAKE_EVAL_CASE(OP_DIVIDE_INTO,          IN0DATATYPE, IN0DATATYPE)
1167
1168 #define MAKE_ASSIGNMENT_SYMMETRIC_OP(IN0DATATYPE)                                       \
1169         MAKE_ASSIGNMENT_OP(IN0DATATYPE);                                                                \
1170         MAKE_EVAL_CASE(OP_MULTIPLY_INTO,        IN0DATATYPE, IN0DATATYPE)
1171
1172         switch (PACK_EVAL_CASE(op, in0.dataType, in1.dataType))
1173         {
1174                 // Matrix-scalar.
1175                 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2,        TYPE_FLOAT);
1176                 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X3,      TYPE_FLOAT);
1177                 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT2X4,      TYPE_FLOAT);
1178                 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X2,      TYPE_FLOAT);
1179                 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3,        TYPE_FLOAT);
1180                 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT3X4,      TYPE_FLOAT);
1181                 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X2,      TYPE_FLOAT);
1182                 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4X3,      TYPE_FLOAT);
1183                 MAKE_SCALAR_OPS(TYPE_FLOAT_MAT4,        TYPE_FLOAT);
1184
1185                 // Matrix-vector.
1186                 MAKE_MUL_OP(TYPE_FLOAT_MAT2,    TYPE_FLOAT_VEC2);
1187                 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3,  TYPE_FLOAT_VEC2);
1188                 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4,  TYPE_FLOAT_VEC2);
1189                 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2,  TYPE_FLOAT_VEC3);
1190                 MAKE_MUL_OP(TYPE_FLOAT_MAT3,    TYPE_FLOAT_VEC3);
1191                 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4,  TYPE_FLOAT_VEC3);
1192                 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2,  TYPE_FLOAT_VEC4);
1193                 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3,  TYPE_FLOAT_VEC4);
1194                 MAKE_MUL_OP(TYPE_FLOAT_MAT4,    TYPE_FLOAT_VEC4);
1195
1196                 // Vector-matrix.
1197                 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT2);
1198                 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT2X3);
1199                 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT2X4);
1200                 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT3X2);
1201                 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT3);
1202                 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT3X4);
1203                 MAKE_MUL_OP(TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT4X2);
1204                 MAKE_MUL_OP(TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT4X3);
1205                 MAKE_MUL_OP(TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT4);
1206
1207                 // Matrix-matrix.
1208                 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2,         TYPE_FLOAT_MAT2);
1209                 MAKE_MUL_OP(TYPE_FLOAT_MAT2,            TYPE_FLOAT_MAT2);
1210                 MAKE_MUL_OP(TYPE_FLOAT_MAT2,            TYPE_FLOAT_MAT3X2);
1211                 MAKE_MUL_OP(TYPE_FLOAT_MAT2,            TYPE_FLOAT_MAT4X2);
1212
1213                 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X3,       TYPE_FLOAT_MAT2X3);
1214                 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3,          TYPE_FLOAT_MAT2);
1215                 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3,          TYPE_FLOAT_MAT3X2);
1216                 MAKE_MUL_OP(TYPE_FLOAT_MAT2X3,          TYPE_FLOAT_MAT4X2);
1217
1218                 MAKE_CWISE_OPS(TYPE_FLOAT_MAT2X4,       TYPE_FLOAT_MAT2X4);
1219                 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4,          TYPE_FLOAT_MAT2);
1220                 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4,          TYPE_FLOAT_MAT3X2);
1221                 MAKE_MUL_OP(TYPE_FLOAT_MAT2X4,          TYPE_FLOAT_MAT4X2);
1222
1223                 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X2,       TYPE_FLOAT_MAT3X2);
1224                 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2,          TYPE_FLOAT_MAT2X3);
1225                 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2,          TYPE_FLOAT_MAT3);
1226                 MAKE_MUL_OP(TYPE_FLOAT_MAT3X2,          TYPE_FLOAT_MAT4X3);
1227
1228                 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3,         TYPE_FLOAT_MAT3);
1229                 MAKE_MUL_OP(TYPE_FLOAT_MAT3,            TYPE_FLOAT_MAT2X3);
1230                 MAKE_MUL_OP(TYPE_FLOAT_MAT3,            TYPE_FLOAT_MAT3);
1231                 MAKE_MUL_OP(TYPE_FLOAT_MAT3,            TYPE_FLOAT_MAT4X3);
1232
1233                 MAKE_CWISE_OPS(TYPE_FLOAT_MAT3X4,       TYPE_FLOAT_MAT3X4);
1234                 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4,          TYPE_FLOAT_MAT2X3);
1235                 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4,          TYPE_FLOAT_MAT3);
1236                 MAKE_MUL_OP(TYPE_FLOAT_MAT3X4,          TYPE_FLOAT_MAT4X3);
1237
1238                 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X2,       TYPE_FLOAT_MAT4X2);
1239                 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2,          TYPE_FLOAT_MAT2X4);
1240                 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2,          TYPE_FLOAT_MAT3X4);
1241                 MAKE_MUL_OP(TYPE_FLOAT_MAT4X2,          TYPE_FLOAT_MAT4);
1242
1243                 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4X3,       TYPE_FLOAT_MAT4X3);
1244                 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3,          TYPE_FLOAT_MAT2X4);
1245                 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3,          TYPE_FLOAT_MAT3X4);
1246                 MAKE_MUL_OP(TYPE_FLOAT_MAT4X3,          TYPE_FLOAT_MAT4);
1247
1248                 MAKE_CWISE_OPS(TYPE_FLOAT_MAT4,         TYPE_FLOAT_MAT4);
1249                 MAKE_MUL_OP(TYPE_FLOAT_MAT4,            TYPE_FLOAT_MAT2X4);
1250                 MAKE_MUL_OP(TYPE_FLOAT_MAT4,            TYPE_FLOAT_MAT3X4);
1251                 MAKE_MUL_OP(TYPE_FLOAT_MAT4,            TYPE_FLOAT_MAT4);
1252
1253                 // Vector-vector.
1254                 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2,         TYPE_FLOAT_VEC2);
1255                 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2,         TYPE_FLOAT_VEC3);
1256                 MAKE_VECVEC_OP(TYPE_FLOAT_VEC2,         TYPE_FLOAT_VEC4);
1257                 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3,         TYPE_FLOAT_VEC2);
1258                 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3,         TYPE_FLOAT_VEC3);
1259                 MAKE_VECVEC_OP(TYPE_FLOAT_VEC3,         TYPE_FLOAT_VEC4);
1260                 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4,         TYPE_FLOAT_VEC2);
1261                 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4,         TYPE_FLOAT_VEC3);
1262                 MAKE_VECVEC_OP(TYPE_FLOAT_VEC4,         TYPE_FLOAT_VEC4);
1263
1264                 // Unary Matrix.
1265                 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT2);
1266                 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X3);
1267                 MAKE_UNARY_OP(TYPE_FLOAT_MAT2X4);
1268                 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X2);
1269                 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT3);
1270                 MAKE_UNARY_OP(TYPE_FLOAT_MAT3X4);
1271                 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X2);
1272                 MAKE_UNARY_OP(TYPE_FLOAT_MAT4X3);
1273                 MAKE_UNARY_SYMMETRIC_OP(TYPE_FLOAT_MAT4);
1274
1275                 // Assignments
1276                 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT2);
1277                 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X3);
1278                 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT2X4);
1279                 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X2);
1280                 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT3);
1281                 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT3X4);
1282                 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X2);
1283                 MAKE_ASSIGNMENT_OP(TYPE_FLOAT_MAT4X3);
1284                 MAKE_ASSIGNMENT_SYMMETRIC_OP(TYPE_FLOAT_MAT4);
1285
1286                 default:
1287                         DE_ASSERT(DE_FALSE);
1288                         return DE_NULL;
1289         }
1290
1291 #undef PACK_EVAL_CASE
1292 #undef MAKE_EVAL_CASE
1293 #undef MUL_OP
1294 #undef ALL_OPS
1295 #undef MAKE_MAT_SCALAR_VEC_CASES
1296 #undef MAKE_MAT_MAT_CASES
1297 }
1298
1299 // Shader source format utilities.
1300
1301 template <int Size>
1302 void writeVectorConstructor (std::ostream& str, const tcu::Vector<float, Size>& v)
1303 {
1304         str << "vec" << Size << "(";
1305         for (int ndx = 0; ndx < Size; ndx++)
1306         {
1307                 if (ndx != 0)
1308                         str << ", ";
1309                 str << de::floatToString(v[ndx], 1);
1310         }
1311         str << ")";
1312 }
1313
1314 template <int Cols, int Rows>
1315 void writeMatrixConstructor (std::ostream& str, const tcu::Matrix<float, Rows, Cols>& m)
1316 {
1317         if (Rows == Cols)
1318                 str << "mat" << Cols;
1319         else
1320                 str << "mat" << Cols << "x" << Rows;
1321
1322         str << "(";
1323         for (int colNdx = 0; colNdx < Cols; colNdx++)
1324         {
1325                 for (int rowNdx = 0; rowNdx < Rows; rowNdx++)
1326                 {
1327                         if (rowNdx > 0 || colNdx > 0)
1328                                 str << ", ";
1329                         str << de::floatToString(m(rowNdx, colNdx), 1);
1330                 }
1331         }
1332         str << ")";
1333 }
1334
1335 } // MatrixCaseUtils
1336
1337 using namespace MatrixCaseUtils;
1338
1339 class MatrixShaderEvaluator : public ShaderEvaluator
1340 {
1341 public:
1342                                                         MatrixShaderEvaluator   (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1);
1343
1344         virtual void                    evaluate                                (ShaderEvalContext& evalCtx) const;
1345
1346 private:
1347         MatrixShaderEvalFunc    m_matEvalFunc;
1348         InputType                               m_inType0;
1349         InputType                               m_inType1;
1350 };
1351
1352 MatrixShaderEvaluator::MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1)
1353         : m_matEvalFunc (evalFunc)
1354         , m_inType0             (inType0)
1355         , m_inType1             (inType1)
1356 {
1357 }
1358
1359 void MatrixShaderEvaluator::evaluate (ShaderEvalContext& evalCtx) const
1360 {
1361         m_matEvalFunc(evalCtx, m_inType0, m_inType1);
1362 }
1363
1364
1365 BaseAttributeType getAttributeType(const glu::DataType dataType)
1366 {
1367         switch(dataType)
1368         {
1369         case TYPE_FLOAT_MAT2:           return MAT2;
1370         case TYPE_FLOAT_MAT2X3:         return MAT2x3;
1371         case TYPE_FLOAT_MAT2X4:         return MAT2x4;
1372         case TYPE_FLOAT_MAT3X2:         return MAT3x2;
1373         case TYPE_FLOAT_MAT3:           return MAT3;
1374         case TYPE_FLOAT_MAT3X4:         return MAT3x4;
1375         case TYPE_FLOAT_MAT4X2:         return MAT4x2;
1376         case TYPE_FLOAT_MAT4X3:         return MAT4x3;
1377         case TYPE_FLOAT_MAT4:           return MAT4;
1378         default:
1379                 TCU_THROW(InternalError, "Not supported");
1380                 break;
1381         }
1382 }
1383
1384 // ShaderMatrixInstance
1385
1386 class ShaderMatrixInstance : public ShaderRenderCaseInstance
1387 {
1388 public:
1389                                                         ShaderMatrixInstance            (Context&                               context,
1390                                                                                                                  bool                                   isVertex,
1391                                                                                                                  const ShaderEvaluator& evaluator,
1392                                                                                                                  const ShaderInput              in0,
1393                                                                                                                  const ShaderInput              in1,
1394                                                                                                                  const MatrixOp                 m_op);
1395         virtual                                 ~ShaderMatrixInstance           (void);
1396
1397 protected:
1398         virtual void                    setupUniforms                           (const tcu::Vec4&);
1399
1400 private:
1401         void                                    addMatrixUniform                        (deUint32 bindingLocation, DataType dataType, const float* dataPtr);
1402
1403         const ShaderInput               m_in0;
1404         const ShaderInput               m_in1;
1405         const MatrixOp                  m_op;
1406 };
1407
1408 ShaderMatrixInstance::ShaderMatrixInstance (Context&                            context,
1409                                                                                         bool                                    isVertex,
1410                                                                                         const ShaderEvaluator&  evaluator,
1411                                                                                         const ShaderInput               in0,
1412                                                                                         const ShaderInput               in1,
1413                                                                                         const MatrixOp                  op)
1414         : ShaderRenderCaseInstance      (context, isVertex, evaluator, DE_NULL, DE_NULL, IMAGE_BACKING_MODE_REGULAR, isVertex && op == OP_INVERSE ? 64 : GRID_SIZE_DEFAULTS)
1415         , m_in0                                         (in0)
1416         , m_in1                                         (in1)
1417         , m_op                                          (op)
1418 {
1419         m_userAttribTransforms.resize(4);
1420         for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1421         {
1422                 m_userAttribTransforms[attribNdx] = Mat4(0.0f);
1423                 m_userAttribTransforms[attribNdx](                  0, 3) = 0.2f;                                                               // !< prevent matrix*vec from going into zero (assuming vec.w != 0)
1424                 m_userAttribTransforms[attribNdx](                  1, 3) = 0.1f;                                                               // !<
1425                 m_userAttribTransforms[attribNdx](                  2, 3) = 0.4f + 0.15f * float(attribNdx);    // !<
1426                 m_userAttribTransforms[attribNdx](                  3, 3) = 0.7f;                                                               // !<
1427                 m_userAttribTransforms[attribNdx]((0 + attribNdx) % 4, 0) = 1.0f;
1428                 m_userAttribTransforms[attribNdx]((1 + attribNdx) % 4, 1) = 1.0f;
1429                 m_userAttribTransforms[attribNdx]((2 + attribNdx) % 4, 2) = 1.0f;
1430                 m_userAttribTransforms[attribNdx]((3 + attribNdx) % 4, 3) = 1.0f;
1431         }
1432
1433         // prevent bad reference cases such as black result images by fine-tuning used matrices
1434         if (getOperationTestMatrixType(m_op) != TESTMATRIXTYPE_DEFAULT)
1435         {
1436                 for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1437                 {
1438                         for (int row = 0; row < 4; row++)
1439                         for (int col = 0; col < 4; col++)
1440                         {
1441                                 switch (getOperationTestMatrixType(m_op))
1442                                 {
1443                                         case TESTMATRIXTYPE_NEGATED:
1444                                                 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col);
1445                                                 break;
1446                                         case TESTMATRIXTYPE_INCREMENTED:
1447                                                 m_userAttribTransforms[attribNdx](row, col) += 0.3f;
1448                                                 break;
1449                                         case TESTMATRIXTYPE_DECREMENTED:
1450                                                 m_userAttribTransforms[attribNdx](row, col) -= 0.3f;
1451                                                 break;
1452                                         case TESTMATRIXTYPE_NEGATED_INCREMENTED:
1453                                                 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col) + 0.3f;
1454                                                 break;
1455                                         case TESTMATRIXTYPE_INCREMENTED_LESS:
1456                                                 m_userAttribTransforms[attribNdx](row, col) -= 0.1f;
1457                                                 break;
1458
1459                                         default:
1460                                                 DE_ASSERT(DE_FALSE);
1461                                                 break;
1462                                 }
1463                         }
1464                 }
1465         }
1466
1467         int     numInputs = isOperationBinary(m_op) ? 2 : 1;
1468
1469         for (int inNdx = 0; inNdx < numInputs; inNdx++)
1470         {
1471                 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1472
1473                 if (in.inputType == INPUTTYPE_DYNAMIC && isDataTypeMatrix(in.dataType))
1474                 {
1475                         useAttribute(4u + inNdx, getAttributeType(in.dataType));
1476                 }
1477         }
1478
1479 }
1480
1481 ShaderMatrixInstance::~ShaderMatrixInstance (void)
1482 {
1483 }
1484
1485 void ShaderMatrixInstance::addMatrixUniform(deUint32 bindingLocation, DataType dataType, const float *dataPtr)
1486 {
1487         Mat4                    result;
1488         const size_t    matrixSize = sizeof(float) * 4 * 4;
1489
1490         switch(dataType)
1491         {
1492                 case TYPE_FLOAT_MAT2:
1493                 {
1494                         Mat2 matrix = Mat2(dataPtr);
1495                         result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1496                         result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1497                         break;
1498                 }
1499                 case TYPE_FLOAT_MAT2X3:
1500                 {
1501                         Mat2x3 matrix = Mat2x3(dataPtr);
1502                         result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1503                         result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1504                         break;
1505                 }
1506                 case TYPE_FLOAT_MAT2X4:
1507                 {
1508                         Mat2x4 matrix = Mat2x4(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_MAT3X2:
1514                 {
1515                         Mat3x2 matrix = Mat3x2(dataPtr);
1516                         result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1517                         result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1518                         result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1519                         break;
1520                 }
1521                 case TYPE_FLOAT_MAT3:
1522                 {
1523                         Mat3 matrix = Mat3(dataPtr);
1524                         result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1525                         result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1526                         result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1527                         break;
1528                 }
1529                 case TYPE_FLOAT_MAT3X4:
1530                 {
1531                         Mat3x4 matrix = Mat3x4(dataPtr);
1532                         result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1533                         result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1534                         result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1535                         break;
1536                 }
1537                 case TYPE_FLOAT_MAT4X2:
1538                 {
1539                         Mat4x2 matrix = Mat4x2(dataPtr);
1540                         result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1541                         result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1542                         result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1543                         result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1544                         break;
1545                 }
1546                 case TYPE_FLOAT_MAT4X3:
1547                 {
1548                         Mat4x3 matrix = Mat4x3(dataPtr);
1549                         result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1550                         result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1551                         result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1552                         result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1553                         break;
1554                 }
1555                 case TYPE_FLOAT_MAT4:
1556                 {
1557                         Mat4 matrix = Mat4(dataPtr);
1558                         result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1559                         result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1560                         result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1561                         result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1562                         break;
1563                 }
1564                 default:
1565                         DE_ASSERT(false);
1566                         break;
1567         }
1568
1569         addUniform(bindingLocation, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, matrixSize, result.getColumnMajorData().getPtr());
1570 }
1571
1572 void ShaderMatrixInstance::setupUniforms (const tcu::Vec4&)
1573 {
1574         const int       numInputs               = isOperationBinary(m_op) ? 2 : 1;
1575         deUint32        uniformBinding  = 0;
1576
1577         for (int inNdx = 0; inNdx < numInputs; inNdx++)
1578         {
1579                 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1580
1581                 if (in.inputType == INPUTTYPE_UNIFORM)
1582                 {
1583                         switch (in.dataType)
1584                         {
1585                                 case TYPE_FLOAT:                addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(float), &s_constInFloat[inNdx]);                                       break;
1586                                 case TYPE_FLOAT_VEC2:   addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec2[inNdx]);                        break;
1587                                 case TYPE_FLOAT_VEC3:   addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec3[inNdx]);                        break;
1588                                 case TYPE_FLOAT_VEC4:   addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec4[inNdx]);                        break;
1589                                 // \note GLES3 supports transpose in matrix upload.
1590                                 case TYPE_FLOAT_MAT2:   addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x2[inNdx]);  break;
1591                                 case TYPE_FLOAT_MAT2X3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x3[inNdx]);  break;
1592                                 case TYPE_FLOAT_MAT2X4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x4[inNdx]);  break;
1593                                 case TYPE_FLOAT_MAT3X2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x2[inNdx]);  break;
1594                                 case TYPE_FLOAT_MAT3:   addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x3[inNdx]);  break;
1595                                 case TYPE_FLOAT_MAT3X4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x4[inNdx]);  break;
1596                                 case TYPE_FLOAT_MAT4X2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x2[inNdx]);  break;
1597                                 case TYPE_FLOAT_MAT4X3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x3[inNdx]);  break;
1598                                 case TYPE_FLOAT_MAT4:   addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x4[inNdx]);  break;
1599                                 default:
1600                                         DE_ASSERT(false);
1601                         }
1602                         uniformBinding++;
1603                 }
1604         }
1605 }
1606
1607 // ShaderMatrixCase
1608
1609 class ShaderMatrixCase : public ShaderRenderCase
1610 {
1611 public:
1612                                                         ShaderMatrixCase                        (tcu::TestContext&      testCtx,
1613                                                                                                                  const std::string&     name,
1614                                                                                                                  const std::string&     desc,
1615                                                                                                                  const ShaderInput&     in0,
1616                                                                                                                  const ShaderInput&     in1,
1617                                                                                                                  const MatrixOp         op,
1618                                                                                                                  bool                           isVertexCase);
1619                                                         ~ShaderMatrixCase                       (void);
1620
1621         virtual TestInstance*   createInstance                          (Context& context) const;
1622
1623 protected:
1624         void                                    setupShader                                     (void);
1625         std::string                             genGLSLMatToVec3Reduction       (const glu::DataType& matType, const char* varName);
1626
1627 private:
1628         const ShaderInput               m_in0;
1629         const ShaderInput               m_in1;
1630         const MatrixOp                  m_op;
1631 };
1632
1633 ShaderMatrixCase::ShaderMatrixCase (tcu::TestContext&   testCtx,
1634                                                                         const std::string&      name,
1635                                                                         const std::string&      desc,
1636                                                                         const ShaderInput&      in0,
1637                                                                         const ShaderInput&      in1,
1638                                                                         MatrixOp                        op,
1639                                                                         bool                            isVertexCase)
1640         : ShaderRenderCase      (testCtx,
1641                                                  name,
1642                                                  desc,
1643                                                  isVertexCase,
1644                                                  new MatrixShaderEvaluator(getEvalFunc(in0, in1, op), in0.inputType, in1.inputType),
1645                                                  DE_NULL /* uniform setup */,
1646                                                  DE_NULL /* attribute setup */)
1647         , m_in0                         (in0)
1648         , m_in1                         (in1)
1649         , m_op                          (op)
1650 {
1651         setupShader();
1652 }
1653
1654 ShaderMatrixCase::~ShaderMatrixCase (void)
1655 {
1656 }
1657
1658 TestInstance* ShaderMatrixCase::createInstance (Context& context) const
1659 {
1660         return new ShaderMatrixInstance(context, m_isVertexCase, *m_evaluator, m_in0, m_in1, m_op);
1661 }
1662
1663 void ShaderMatrixCase::setupShader (void)
1664 {
1665         std::ostringstream      vtx;
1666         std::ostringstream      frag;
1667         std::ostringstream&     op                              = m_isVertexCase ? vtx : frag;
1668
1669         bool                            isInDynMat0             = isDataTypeMatrix(m_in0.dataType) && m_in0.inputType == INPUTTYPE_DYNAMIC;
1670         bool                            isInDynMat1             = isDataTypeMatrix(m_in1.dataType) && m_in1.inputType == INPUTTYPE_DYNAMIC;
1671         string                          inValue0;
1672         string                          inValue1;
1673         DataType                        resultType              = TYPE_LAST;
1674         Precision                       resultPrec              = m_in0.precision;
1675         vector<string>          passVars;
1676         int                                     numInputs               = (isOperationBinary(m_op)) ? (2) : (1);
1677
1678         std::string                     operationValue0;
1679         std::string                     operationValue1;
1680
1681         DE_ASSERT(!isInDynMat0 || !isInDynMat1); // Only single dynamic matrix input is allowed.
1682         DE_UNREF(isInDynMat0 && isInDynMat1);
1683
1684         // Compute result type.
1685         if (m_op == OP_MUL && isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1686         {
1687                 resultType = getDataTypeMatrix(getDataTypeMatrixNumColumns(m_in1.dataType), getDataTypeMatrixNumRows(m_in0.dataType));
1688         }
1689         else if (m_op == OP_OUTER_PRODUCT)
1690         {
1691                 resultType = getDataTypeMatrix(getDataTypeScalarSize(m_in1.dataType), getDataTypeScalarSize(m_in0.dataType));
1692         }
1693         else if (m_op == OP_TRANSPOSE)
1694         {
1695                 resultType = getDataTypeMatrix(getDataTypeMatrixNumRows(m_in0.dataType), getDataTypeMatrixNumColumns(m_in0.dataType));
1696         }
1697         else if (m_op == OP_INVERSE)
1698         {
1699                 resultType = m_in0.dataType;
1700         }
1701         else if (m_op == OP_DETERMINANT)
1702         {
1703                 resultType = TYPE_FLOAT;
1704         }
1705         else if (getOperationType(m_op) == OPERATIONTYPE_UNARY_PREFIX_OPERATOR ||
1706                          getOperationType(m_op) == OPERATIONTYPE_UNARY_POSTFIX_OPERATOR)
1707         {
1708                 resultType = m_in0.dataType;
1709         }
1710         else if (isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1711         {
1712                 DE_ASSERT(m_in0.dataType == m_in1.dataType);
1713                 resultType = m_in0.dataType;
1714         }
1715         else if (isDataTypeMatrix(m_in0.dataType) || isDataTypeMatrix(m_in1.dataType))
1716         {
1717                 int                     matNdx          = isDataTypeMatrix(m_in0.dataType) ? 0 : 1;
1718                 DataType        matrixType      = matNdx == 0 ? m_in0.dataType : m_in1.dataType;
1719                 DataType        otherType       = matNdx == 0 ? m_in1.dataType : m_in0.dataType;
1720
1721                 if (otherType == TYPE_FLOAT)
1722                         resultType = matrixType;
1723                 else
1724                 {
1725                         DE_ASSERT(isDataTypeVector(otherType));
1726                         resultType = getDataTypeFloatVec(matNdx == 0 ? getDataTypeMatrixNumRows(matrixType) : getDataTypeMatrixNumColumns(matrixType));
1727                 }
1728         }
1729         else
1730         {
1731                 DE_ASSERT(DE_FALSE);
1732         }
1733
1734         static const std::string header =
1735                 "#version 310 es\n";
1736
1737         vtx << header;
1738         frag << header;
1739
1740         vtx << "layout(location = 0) in highp vec4 a_position;\n";
1741         frag << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1742         if (m_isVertexCase)
1743         {
1744                 vtx << "layout(location = 0) out mediump vec4 v_color;\n";
1745                 frag << "layout(location = 0) in mediump vec4 v_color;\n";
1746         }
1747
1748         // Input declarations.
1749         deUint32 uniformBinding = 0;
1750         deUint32 padding = 0;
1751         for (int inNdx = 0; inNdx < numInputs; inNdx++)
1752         {
1753                 const ShaderInput&      in                      = inNdx > 0 ? m_in1 : m_in0;
1754                 const char*                     precName        = getPrecisionName(in.precision);
1755                 const char*                     typeName        = getDataTypeName(in.dataType);
1756                 string&                         inValue         = inNdx > 0 ? inValue1 : inValue0;
1757
1758                 if (in.inputType == INPUTTYPE_DYNAMIC)
1759                 {
1760                         if (isDataTypeMatrix(in.dataType))
1761                         {
1762                                 vtx << "layout(location = " << 4 + inNdx + padding << ") in " << precName << " " << typeName << " a_";
1763                                 // a_matN, v_matN
1764                                 vtx << typeName << ";\n";
1765                                 if (!m_isVertexCase)
1766                                 {
1767                                         vtx << "layout(location = " << 1 + inNdx + padding << ") out " << precName << " " << typeName << " v_" << typeName << ";\n";
1768                                         frag << "layout(location = " << 1 + inNdx + padding << ") in " << precName << " " << typeName << " v_" << typeName << ";\n";
1769                                         passVars.push_back(typeName);
1770                                 }
1771
1772                                 inValue = string(m_isVertexCase ? "a_" : "v_") + getDataTypeName(in.dataType);
1773                                 padding += getDataTypeMatrixNumColumns(in.dataType);
1774                         }
1775                         else
1776                         {
1777                                 // a_coords, v_coords
1778                                 vtx << "layout(location = 1) in " << precName << " " << typeName << " a_coords;\n";
1779                                 if (!m_isVertexCase)
1780                                 {
1781                                         vtx << "layout(location = " << 1 + padding << ") out " << precName << " " << typeName << " v_coords;\n";
1782                                         frag << "layout(location = " << 1 + padding << ") in " << precName << " " << typeName << " v_coords;\n";
1783                                         passVars.push_back("coords");
1784                                 }
1785
1786                                 inValue = m_isVertexCase ? "a_coords" : "v_coords";
1787                         }
1788                 }
1789                 else if (in.inputType == INPUTTYPE_UNIFORM)
1790                 {
1791                         op << "layout(std140, set = 0, binding = " << uniformBinding++ <<  ") uniform buffer"<< inNdx <<" { " << precName << " " << typeName << " u_in" << inNdx << "; };\n";
1792                         inValue = string("u_in") + de::toString(inNdx);
1793                 }
1794                 else if (in.inputType == INPUTTYPE_CONST)
1795                 {
1796                         op << "const " << precName << " " << typeName << " in" << inNdx << " = ";
1797
1798                         // Generate declaration.
1799                         switch (in.dataType)
1800                         {
1801                                 case TYPE_FLOAT:                op << de::floatToString(s_constInFloat[inNdx], 1);                                      break;
1802                                 case TYPE_FLOAT_VEC2:   writeVectorConstructor<2>(op, s_constInVec2[inNdx]);                            break;
1803                                 case TYPE_FLOAT_VEC3:   writeVectorConstructor<3>(op, s_constInVec3[inNdx]);                            break;
1804                                 case TYPE_FLOAT_VEC4:   writeVectorConstructor<4>(op, s_constInVec4[inNdx]);                            break;
1805                                 case TYPE_FLOAT_MAT2:   writeMatrixConstructor<2, 2>(op, Mat2(s_constInMat2x2[inNdx]));         break;
1806                                 case TYPE_FLOAT_MAT2X3: writeMatrixConstructor<2, 3>(op, Mat2x3(s_constInMat2x3[inNdx]));       break;
1807                                 case TYPE_FLOAT_MAT2X4: writeMatrixConstructor<2, 4>(op, Mat2x4(s_constInMat2x4[inNdx]));       break;
1808                                 case TYPE_FLOAT_MAT3X2: writeMatrixConstructor<3, 2>(op, Mat3x2(s_constInMat3x2[inNdx]));       break;
1809                                 case TYPE_FLOAT_MAT3:   writeMatrixConstructor<3, 3>(op, Mat3(s_constInMat3x3[inNdx]));         break;
1810                                 case TYPE_FLOAT_MAT3X4: writeMatrixConstructor<3, 4>(op, Mat3x4(s_constInMat3x4[inNdx]));       break;
1811                                 case TYPE_FLOAT_MAT4X2: writeMatrixConstructor<4, 2>(op, Mat4x2(s_constInMat4x2[inNdx]));       break;
1812                                 case TYPE_FLOAT_MAT4X3: writeMatrixConstructor<4, 3>(op, Mat4x3(s_constInMat4x3[inNdx]));       break;
1813                                 case TYPE_FLOAT_MAT4:   writeMatrixConstructor<4, 4>(op, Mat4(s_constInMat4x4[inNdx]));         break;
1814
1815                                 default:
1816                                         DE_ASSERT(DE_FALSE);
1817                         }
1818
1819                         op << ";\n";
1820
1821                         inValue = string("in") + de::toString(inNdx);
1822                 }
1823         }
1824
1825         vtx << "\n"
1826                 << "void main (void)\n"
1827                 << "{\n"
1828                 << "    gl_Position = a_position;\n";
1829         frag << "\n"
1830                  << "void main (void)\n"
1831                  << "{\n";
1832
1833         if (m_isVertexCase)
1834                 frag << "       dEQP_FragColor = v_color;\n";
1835         else
1836         {
1837                 for (vector<string>::const_iterator copyIter = passVars.begin(); copyIter != passVars.end(); copyIter++)
1838                         vtx << "        v_" << *copyIter << " = " << "a_" << *copyIter << ";\n";
1839         }
1840
1841         // Operation.
1842
1843         switch (getOperationNature(m_op))
1844         {
1845                 case OPERATIONNATURE_PURE:
1846                         DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1847
1848                         operationValue0 = inValue0;
1849                         operationValue1 = inValue1;
1850                         break;
1851
1852                 case OPERATIONNATURE_MUTATING:
1853                         DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1854
1855                         op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " tmpValue = " << inValue0 << ";\n";
1856
1857                         operationValue0 = "tmpValue";
1858                         operationValue1 = inValue1;
1859                         break;
1860
1861                 case OPERATIONNATURE_ASSIGNMENT:
1862                         DE_ASSERT(getOperationType(m_op) == OPERATIONTYPE_ASSIGNMENT);
1863
1864                         operationValue0 = inValue0;
1865                         operationValue1 = inValue1;
1866                         break;
1867
1868                 default:
1869                         DE_ASSERT(DE_FALSE);
1870         }
1871
1872         switch (getOperationType(m_op))
1873         {
1874                 case OPERATIONTYPE_BINARY_OPERATOR:
1875                         op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << " " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1876                         break;
1877
1878                 case OPERATIONTYPE_UNARY_PREFIX_OPERATOR:
1879                         op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << operationValue0 << ";\n";
1880                         break;
1881
1882                 case OPERATIONTYPE_UNARY_POSTFIX_OPERATOR:
1883                         op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << getOperationName(m_op) << ";\n";
1884                         break;
1885
1886                 case OPERATIONTYPE_BINARY_FUNCTION:
1887                         op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ", " << operationValue1 << ");\n";
1888                         break;
1889
1890                 case OPERATIONTYPE_UNARY_FUNCTION:
1891                         op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ");\n";
1892                         break;
1893
1894                 case OPERATIONTYPE_ASSIGNMENT:
1895                         op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << ";\n";
1896                         op << " res " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1897                         break;
1898
1899                 default:
1900                         DE_ASSERT(DE_FALSE);
1901         }
1902
1903         // Reduction to vec3 (rgb). Check the used value too if it was modified
1904         op << " " << (m_isVertexCase ? "v_color" : "dEQP_FragColor") << " = ";
1905
1906         if (isOperationValueModifying(m_op))
1907                 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0) + vec4(" << genGLSLMatToVec3Reduction(resultType, "tmpValue") << ", 0.0);\n";
1908         else
1909                 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0);\n";
1910
1911         vtx << "}\n";
1912         frag << "}\n";
1913
1914         m_vertShaderSource      = vtx.str();
1915         m_fragShaderSource      = frag.str();
1916 }
1917
1918 std::string ShaderMatrixCase::genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName)
1919 {
1920         std::ostringstream op;
1921
1922         switch (matType)
1923         {
1924                 case TYPE_FLOAT:                op << varName << ", "                   << varName << ", "                      << varName << "";                                                                                                                                                                                                                                                                                       break;
1925                 case TYPE_FLOAT_VEC2:   op << varName << ".x, "                 << varName << ".y, "            << varName << ".x";                                                                                                                                                                                                                                                                                     break;
1926                 case TYPE_FLOAT_VEC3:   op << varName << "";                                                                                                                                                                                                                                                                                                                                                                                                    break;
1927                 case TYPE_FLOAT_VEC4:   op << varName << ".x, "                 << varName << ".y, "            << varName << ".z+"                     << varName << ".w";                                                                                                                                                                                                                             break;
1928                 case TYPE_FLOAT_MAT2:   op << varName << "[0][0], "             << varName << "[1][0], "        << varName << "[0][1]+"         << varName << "[1][1]";                                                                                                                                                                                                                 break;
1929                 case TYPE_FLOAT_MAT2X3: op << varName << "[0] + "               << varName << "[1]";                                                                                                                                                                                                                                                                                                                                    break;
1930                 case TYPE_FLOAT_MAT2X4: op << varName << "[0].xyz + "   << varName << "[1].yzw";                                                                                                                                                                                                                                                                                                                                break;
1931                 case TYPE_FLOAT_MAT3X2: op << varName << "[0][0]+"              << varName << "[0][1], "        << varName << "[1][0]+"         << varName << "[1][1], "        << varName << "[2][0]+" << varName << "[2][1]";                                                                                                         break;
1932                 case TYPE_FLOAT_MAT3:   op << varName << "[0] + "               << varName << "[1] + "          << varName << "[2]";                                                                                                                                                                                                                                                                            break;
1933                 case TYPE_FLOAT_MAT3X4: op << varName << "[0].xyz + "   << varName << "[1].yzw + "      << varName << "[2].zwx";                                                                                                                                                                                                                                                                        break;
1934                 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;
1935                 case TYPE_FLOAT_MAT4X3: op << varName << "[0] + "               << varName << "[1] + "          << varName << "[2] + "          << varName << "[3]";                                                                                                                                                                                                                    break;
1936                 case TYPE_FLOAT_MAT4:   op << varName << "[0].xyz+"             << varName << "[1].yzw+"        << varName << "[2].zwx+"        << varName << "[3].wxy";                                                                                                                                                                                                                break;
1937
1938                 default:
1939                         DE_ASSERT(DE_FALSE);
1940         }
1941
1942         return op.str();
1943 }
1944
1945 class ShaderMatrixTests : public tcu::TestCaseGroup
1946 {
1947 public:
1948                                                         ShaderMatrixTests               (tcu::TestContext& testCtx);
1949         virtual                                 ~ShaderMatrixTests              (void);
1950
1951         virtual void                    init                                    (void);
1952
1953 private:
1954                                                         ShaderMatrixTests               (const ShaderMatrixTests&);             // not allowed!
1955         ShaderMatrixTests&              operator=                               (const ShaderMatrixTests&);             // not allowed!
1956 };
1957
1958 ShaderMatrixTests::ShaderMatrixTests (tcu::TestContext& testCtx)
1959         : TestCaseGroup(testCtx, "matrix", "Matrix Tests")
1960 {
1961 }
1962
1963 ShaderMatrixTests::~ShaderMatrixTests (void)
1964 {
1965 }
1966
1967 void ShaderMatrixTests::init (void)
1968 {
1969         static const struct
1970         {
1971                 const char*             name;
1972                 const char*             desc;
1973                 const MatrixOp  op;
1974                 const bool              extendedInputTypeCases; // !< test with const and uniform types too
1975                 const bool              createInputTypeGroup;   // !< create group for input types
1976         } ops[] =
1977         {
1978                 { "add",                        "Matrix addition tests",                                                OP_ADD,                         true,   true    },
1979                 { "sub",                        "Matrix subtraction tests",                                             OP_SUB,                         true,   true    },
1980                 { "mul",                        "Matrix multiplication tests",                                  OP_MUL,                         true,   true    },
1981                 { "div",                        "Matrix division tests",                                                OP_DIV,                         true,   true    },
1982                 { "matrixcompmult",     "Matrix component-wise multiplication tests",   OP_COMP_MUL,            false,  true    },
1983                 { "outerproduct",       "Matrix outerProduct() tests",                                  OP_OUTER_PRODUCT,       false,  true    },
1984                 { "transpose",          "Matrix transpose() tests",                                             OP_TRANSPOSE,           false,  true    },
1985                 { "determinant",        "Matrix determinant() tests",                                   OP_DETERMINANT,         false,  true    },
1986                 { "inverse",            "Matrix inverse() tests",                                               OP_INVERSE,                     false,  true    },
1987                 { "unary_addition",     "Matrix unary addition tests",                                  OP_UNARY_PLUS,          false,  false   },
1988                 { "negation",           "Matrix negation tests",                                                OP_NEGATION,            false,  false   },
1989                 { "pre_increment",      "Matrix prefix increment tests",                                OP_PRE_INCREMENT,       false,  false   },
1990                 { "pre_decrement",      "Matrix prefix decrement tests",                                OP_PRE_DECREMENT,       false,  false   },
1991                 { "post_increment",     "Matrix postfix increment tests",                               OP_POST_INCREMENT,      false,  false   },
1992                 { "post_decrement",     "Matrix postfix decrement tests",                               OP_POST_DECREMENT,      false,  false   },
1993                 { "add_assign",         "Matrix add into tests",                                                OP_ADD_INTO,            false,  false   },
1994                 { "sub_assign",         "Matrix subtract from tests",                                   OP_SUBTRACT_FROM,       false,  false   },
1995                 { "mul_assign",         "Matrix multiply into tests",                                   OP_MULTIPLY_INTO,       false,  false   },
1996                 { "div_assign",         "Matrix divide into tests",                                             OP_DIVIDE_INTO,         false,  false   },
1997         };
1998
1999         struct InputTypeSpec
2000         {
2001                 const char*             name;
2002                 const char*             desc;
2003                 const InputType type;
2004         };
2005         static const InputTypeSpec extendedInputTypes[] =
2006         {
2007                 { "const",              "Constant matrix input",        INPUTTYPE_CONST         },
2008                 { "uniform",    "Uniform matrix input",         INPUTTYPE_UNIFORM       },
2009                 { "dynamic",    "Dynamic matrix input",         INPUTTYPE_DYNAMIC       }
2010         };
2011         static const InputTypeSpec reducedInputTypes[] =
2012         {
2013                 { "dynamic",    "Dynamic matrix input",         INPUTTYPE_DYNAMIC       }
2014         };
2015
2016         static const DataType matrixTypes[] =
2017         {
2018                 TYPE_FLOAT_MAT2,
2019                 TYPE_FLOAT_MAT2X3,
2020                 TYPE_FLOAT_MAT2X4,
2021                 TYPE_FLOAT_MAT3X2,
2022                 TYPE_FLOAT_MAT3,
2023                 TYPE_FLOAT_MAT3X4,
2024                 TYPE_FLOAT_MAT4X2,
2025                 TYPE_FLOAT_MAT4X3,
2026                 TYPE_FLOAT_MAT4
2027         };
2028
2029         static const Precision precisions[] =
2030         {
2031                 PRECISION_MEDIUMP,
2032                 PRECISION_HIGHP
2033         };
2034
2035         for (int opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
2036         {
2037                 const InputTypeSpec*    inTypeList              = (ops[opNdx].extendedInputTypeCases) ? (extendedInputTypes) : (reducedInputTypes);
2038                 const int                               inTypeListSize  = (ops[opNdx].extendedInputTypeCases) ? (DE_LENGTH_OF_ARRAY(extendedInputTypes)) : (DE_LENGTH_OF_ARRAY(reducedInputTypes));
2039                 const MatrixOp                  op                              = ops[opNdx].op;
2040                 tcu::TestCaseGroup*             opGroup                 = new tcu::TestCaseGroup(m_testCtx, ops[opNdx].name, ops[opNdx].desc);
2041
2042                 addChild(opGroup);
2043
2044                 for (int inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++)
2045                 {
2046                         const InputType         inputType       = inTypeList[inTypeNdx].type;
2047                         tcu::TestCaseGroup* inGroup;
2048
2049                         if (ops[opNdx].createInputTypeGroup)
2050                         {
2051                                 inGroup = new tcu::TestCaseGroup(m_testCtx, inTypeList[inTypeNdx].name, inTypeList[inTypeNdx].desc);
2052                                 opGroup->addChild(inGroup);
2053                         }
2054                         else
2055                                 inGroup = opGroup;
2056
2057                         for (int matTypeNdx = 0; matTypeNdx < DE_LENGTH_OF_ARRAY(matrixTypes); matTypeNdx++)
2058                         {
2059                                 DataType        matType         = matrixTypes[matTypeNdx];
2060                                 int                     numCols         = getDataTypeMatrixNumColumns(matType);
2061                                 int                     numRows         = getDataTypeMatrixNumRows(matType);
2062                                 const char*     matTypeName     = getDataTypeName(matType);
2063
2064                                 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
2065                                 {
2066                                         Precision       precision       = precisions[precNdx];
2067                                         const char*     precName        = getPrecisionName(precision);
2068                                         string          baseName        = string(precName) + "_" + matTypeName + "_";
2069                                         ShaderInput     matIn           (inputType, matType, precision);
2070
2071                                         if (isOperationMatrixScalar(op))
2072                                         {
2073                                                 // Matrix-scalar \note For div cases we use uniform input.
2074                                                 ShaderInput scalarIn(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, TYPE_FLOAT, precision);
2075                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(),          "Matrix-scalar case", matIn, scalarIn, op, true));
2076                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(),        "Matrix-scalar case", matIn, scalarIn, op, false));
2077                                         }
2078
2079                                         if (isOperationMatrixVector(op))
2080                                         {
2081                                                 // Matrix-vector.
2082                                                 DataType        colVecType      = getDataTypeFloatVec(numCols);
2083                                                 ShaderInput colVecIn    (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, colVecType, precision);
2084
2085                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_vertex").c_str(),         "Matrix-vector case", matIn, colVecIn, op, true));
2086                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_fragment").c_str(),       "Matrix-vector case", matIn, colVecIn, op, false));
2087
2088                                                 // Vector-matrix.
2089                                                 DataType        rowVecType      = getDataTypeFloatVec(numRows);
2090                                                 ShaderInput     rowVecIn        (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, rowVecType, precision);
2091                                                 string          vecMatName      = string(precName) + "_" + getDataTypeName(rowVecType) + "_" + matTypeName;
2092
2093                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_vertex").c_str(),             "Vector-matrix case", rowVecIn, matIn, op, true));
2094                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_fragment").c_str(),   "Vector-matrix case", rowVecIn, matIn, op, false));
2095                                         }
2096
2097                                         if (isOperationArithmeticMatrixMatrix(op))
2098                                         {
2099                                                 // Arithmetic matrix-matrix multiplication.
2100                                                 for (int otherCols = 2; otherCols <= 4; otherCols++)
2101                                                 {
2102                                                         ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, getDataTypeMatrix(otherCols, numCols /* rows */), precision);
2103                                                         inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_vertex").c_str(),        "Matrix-matrix case", matIn, otherMatIn, op, true));
2104                                                         inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_fragment").c_str(),      "Matrix-matrix case", matIn, otherMatIn, op, false));
2105                                                 }
2106                                         }
2107                                         else if (isOperationComponentwiseMatrixMatrix(op))
2108                                         {
2109                                                 // Component-wise.
2110                                                 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2111                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_vertex").c_str(),         "Matrix-matrix case", matIn, otherMatIn, op, true));
2112                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_fragment").c_str(),       "Matrix-matrix case", matIn, otherMatIn, op, false));
2113                                         }
2114
2115                                         if (isOperationVectorVector(op))
2116                                         {
2117                                                 ShaderInput vec1In(inputType,                                                                                                                           getDataTypeFloatVec(numRows), precision);
2118                                                 ShaderInput vec2In((inputType == INPUTTYPE_DYNAMIC) ? (INPUTTYPE_UNIFORM) : (inputType),        getDataTypeFloatVec(numCols), precision);
2119
2120                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(),          "Vector-vector case", vec1In, vec2In, op, true));
2121                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(),        "Vector-vector case", vec1In, vec2In, op, false));
2122                                         }
2123
2124                                         if ((isOperationUnaryAnyMatrix(op)) ||
2125                                                 (isOperationUnarySymmetricMatrix(op) && numCols == numRows))
2126                                         {
2127                                                 ShaderInput voidInput(INPUTTYPE_LAST, TYPE_LAST, PRECISION_LAST);
2128                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(),          "Matrix case", matIn, voidInput, op, true));
2129                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(),        "Matrix case", matIn, voidInput, op, false));
2130                                         }
2131
2132                                         if ((isOperationAssignmentAnyMatrix(op)) ||
2133                                                 (isOperationAssignmentSymmetricMatrix(op) && numCols == numRows))
2134                                         {
2135                                                 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2136                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(),          "Matrix assignment case", matIn, otherMatIn, op, true));
2137                                                 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(),        "Matrix assignment case", matIn, otherMatIn, op, false));
2138                                         }
2139                                 }
2140                         }
2141                 }
2142         }
2143 }
2144
2145 } // anonymous
2146
2147 tcu::TestCaseGroup* createMatrixTests (tcu::TestContext& testCtx)
2148 {
2149         return new ShaderMatrixTests(testCtx);
2150 }
2151
2152 } // sr
2153 } // vkt