• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
ShaderInputvkt::sr::__anon6963bb650111::MatrixCaseUtils::ShaderInput212 	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 
getOperationName(MatrixOp op)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 
getOperationType(MatrixOp op)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 
getOperationTestMatrixType(MatrixOp op)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 
isOperationBinary(MatrixOp op)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 
isOperationMatrixScalar(MatrixOp op)395 static bool isOperationMatrixScalar (MatrixOp op)
396 {
397 	return op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV;
398 }
399 
isOperationMatrixVector(MatrixOp op)400 static bool isOperationMatrixVector (MatrixOp op)
401 {
402 	return op == OP_MUL;
403 }
404 
isOperationArithmeticMatrixMatrix(MatrixOp op)405 static bool isOperationArithmeticMatrixMatrix (MatrixOp op)
406 {
407 	return op == OP_MUL;
408 }
409 
isOperationComponentwiseMatrixMatrix(MatrixOp op)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 
isOperationVectorVector(MatrixOp op)415 static bool isOperationVectorVector (MatrixOp op)
416 {
417 	return op == OP_OUTER_PRODUCT;
418 }
419 
isOperationUnaryAnyMatrix(MatrixOp op)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 
isOperationUnarySymmetricMatrix(MatrixOp op)431 static bool isOperationUnarySymmetricMatrix (MatrixOp op)
432 {
433 	return op == OP_INVERSE || op == OP_DETERMINANT;
434 }
435 
isOperationValueModifying(MatrixOp op)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 
isOperationAssignment(MatrixOp op)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 
isOperationAssignmentAnyMatrix(MatrixOp op)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 
isOperationAssignmentSymmetricMatrix(MatrixOp op)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 
getOperationNature(MatrixOp op)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)491 template <> inline float		getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT>			(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInFloat[inputNdx];	}
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)492 template <> inline tcu::Vec2	getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT_VEC2>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec2[inputNdx];	}
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)493 template <> inline tcu::Vec3	getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT_VEC3>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec3[inputNdx];	}
getInputValue(const ShaderEvalContext & evalCtx,int 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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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]);		}
getInputValue(const ShaderEvalContext & evalCtx,int 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]);	}
getInputValue(const ShaderEvalContext & evalCtx,int 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]);	}
getInputValue(const ShaderEvalContext & evalCtx,int 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]);	}
getInputValue(const ShaderEvalContext & evalCtx,int 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]);		}
getInputValue(const ShaderEvalContext & evalCtx,int 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]);	}
getInputValue(const ShaderEvalContext & evalCtx,int 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]);	}
getInputValue(const ShaderEvalContext & evalCtx,int 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]);	}
getInputValue(const ShaderEvalContext & evalCtx,int 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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)506 template <> inline float		getInputValue<INPUTTYPE_DYNAMIC,	TYPE_FLOAT>			(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.x();					}
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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);			}
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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);		}
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
getInputValue(const ShaderEvalContext & evalCtx,int inputNdx)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 
reduceToVec3(const tcu::Vec2 & value)603 inline tcu::Vec3 reduceToVec3 (const tcu::Vec2& value)		{ return value.swizzle(0,1,0); }
reduceToVec3(const tcu::Vec3 & value)604 inline tcu::Vec3 reduceToVec3 (const tcu::Vec3& value)		{ return value; }
reduceToVec3(const tcu::Vec4 & value)605 inline tcu::Vec3 reduceToVec3 (const tcu::Vec4& value)		{ return tcu::Vec3(value.x(), value.y(), value.z()+value.w()); }
reduceToVec3(const tcu::Mat2 & value)606 inline tcu::Vec3 reduceToVec3 (const tcu::Mat2& value)		{ return tcu::Vec3(value(0, 0), value(0, 1), value(1, 0)+value(1, 1)); }
reduceToVec3(const tcu::Mat2x3 & value)607 inline tcu::Vec3 reduceToVec3 (const tcu::Mat2x3& value)	{ return value.getColumn(0) + value.getColumn(1); }
reduceToVec3(const tcu::Mat2x4 & value)608 inline tcu::Vec3 reduceToVec3 (const tcu::Mat2x4& value)	{ return value.getColumn(0).swizzle(0,1,2) + value.getColumn(1).swizzle(1,2,3); }
reduceToVec3(const tcu::Mat3x2 & value)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)); }
reduceToVec3(const tcu::Mat3 & value)610 inline tcu::Vec3 reduceToVec3 (const tcu::Mat3& value)		{ return value.getColumn(0) + value.getColumn(1) + value.getColumn(2); }
reduceToVec3(const tcu::Mat3x4 & value)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); }
reduceToVec3(const tcu::Mat4x2 & value)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)); }
reduceToVec3(const tcu::Mat4x3 & value)613 inline tcu::Vec3 reduceToVec3 (const tcu::Mat4x3& value)	{ return value.getColumn(0) + value.getColumn(1) + value.getColumn(2) + value.getColumn(3); }
reduceToVec3(const tcu::Mat4 & value)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>
matrixCompMult(const tcu::Matrix<T,Rows,Cols> & a,const tcu::Matrix<T,Rows,Cols> & b)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>
outerProduct(const tcu::Vector<T,Cols> & a,const tcu::Vector<T,Rows> & b)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 <>
determinant(const tcu::Matrix<float,2,2> & mat)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 <>
determinant(const tcu::Matrix<float,3,3> & mat)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 <>
determinant(const tcu::Matrix<float,4,4> & mat)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 <>
inverse(const tcu::Matrix<float,2,2> & mat)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 <>
inverse(const tcu::Matrix<float,3,3> & mat)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 <>
inverse(const tcu::Matrix<float,4,4> & mat)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>
negate(const tcu::Matrix<T,Rows,Cols> & mat)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>
increment(const tcu::Matrix<T,Rows,Cols> & mat)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>
decrement(const tcu::Matrix<T,Rows,Cols> & mat)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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator873 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator886 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator899 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator912 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator925 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator938 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator951 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator963 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator975 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator987 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator999 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator1011 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator1025 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator1039 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator1053 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator1067 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator1080 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator1093 	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 {
evaluatevkt::sr::__anon6963bb650111::MatrixCaseUtils::Evaluator1106 	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 
getEvalFunc(const ShaderInput & in0,const ShaderInput & in1,MatrixOp op)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>
writeVectorConstructor(std::ostream & str,const tcu::Vector<float,Size> & v)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>
writeMatrixConstructor(std::ostream & str,const tcu::Matrix<float,Rows,Cols> & m)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 
MatrixShaderEvaluator(MatrixShaderEvalFunc evalFunc,InputType inType0,InputType inType1)1352 MatrixShaderEvaluator::MatrixShaderEvaluator (MatrixShaderEvalFunc evalFunc, InputType inType0, InputType inType1)
1353 	: m_matEvalFunc	(evalFunc)
1354 	, m_inType0		(inType0)
1355 	, m_inType1		(inType1)
1356 {
1357 }
1358 
evaluate(ShaderEvalContext & evalCtx) const1359 void MatrixShaderEvaluator::evaluate (ShaderEvalContext& evalCtx) const
1360 {
1361 	m_matEvalFunc(evalCtx, m_inType0, m_inType1);
1362 }
1363 
1364 
getAttributeType(const glu::DataType dataType)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 	}
1381 }
1382 
1383 // ShaderMatrixInstance
1384 
1385 class ShaderMatrixInstance : public ShaderRenderCaseInstance
1386 {
1387 public:
1388 							ShaderMatrixInstance		(Context&				context,
1389 														 bool					isVertex,
1390 														 const ShaderEvaluator&	evaluator,
1391 														 const ShaderInput		in0,
1392 														 const ShaderInput		in1,
1393 														 const MatrixOp			m_op);
1394 	virtual					~ShaderMatrixInstance		(void);
1395 
1396 protected:
1397 	virtual void			setupUniforms				(const tcu::Vec4&);
1398 
1399 private:
1400 	void					addMatrixUniform			(deUint32 bindingLocation, DataType dataType, const float* dataPtr);
1401 
1402 	const ShaderInput		m_in0;
1403 	const ShaderInput		m_in1;
1404 	const MatrixOp			m_op;
1405 };
1406 
ShaderMatrixInstance(Context & context,bool isVertex,const ShaderEvaluator & evaluator,const ShaderInput in0,const ShaderInput in1,const MatrixOp op)1407 ShaderMatrixInstance::ShaderMatrixInstance (Context&				context,
1408 											bool					isVertex,
1409 											const ShaderEvaluator&	evaluator,
1410 											const ShaderInput		in0,
1411 											const ShaderInput		in1,
1412 											const MatrixOp			op)
1413 	: ShaderRenderCaseInstance	(context, isVertex, evaluator, DE_NULL, DE_NULL, IMAGE_BACKING_MODE_REGULAR, isVertex && op == OP_INVERSE ? 64 : GRID_SIZE_DEFAULTS)
1414 	, m_in0						(in0)
1415 	, m_in1						(in1)
1416 	, m_op						(op)
1417 {
1418 	m_userAttribTransforms.resize(4);
1419 	for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1420 	{
1421 		m_userAttribTransforms[attribNdx] = Mat4(0.0f);
1422 		m_userAttribTransforms[attribNdx](                  0, 3) = (op == OP_INVERSE ? -0.5f : 0.2f);	// prevent matrix*vec from going into zero (assuming vec.w != 0).
1423 		m_userAttribTransforms[attribNdx](                  1, 3) = (op == OP_INVERSE ? -1.3f : 0.1f);	// Modified input for OP_INVERSE case, as determinant of final input
1424 		m_userAttribTransforms[attribNdx](                  2, 3) = 0.4f + 0.15f * float(attribNdx);	// matrix is spanning both sides of 0, so 0 (and division by 0) may happen on mediump.
1425 		m_userAttribTransforms[attribNdx](                  3, 3) = (op == OP_INVERSE ? -3.0f : 0.7f);	// Modified OP_INVERSE final input matrix is same signed in whole input range.
1426 		m_userAttribTransforms[attribNdx]((0 + attribNdx) % 4, 0) = 1.0f;
1427 		m_userAttribTransforms[attribNdx]((1 + attribNdx) % 4, 1) = 1.0f;
1428 		m_userAttribTransforms[attribNdx]((2 + attribNdx) % 4, 2) = 1.0f;
1429 		m_userAttribTransforms[attribNdx]((3 + attribNdx) % 4, 3) = 1.0f;
1430 	}
1431 
1432 	// prevent bad reference cases such as black result images by fine-tuning used matrices
1433 	if (getOperationTestMatrixType(m_op) != TESTMATRIXTYPE_DEFAULT)
1434 	{
1435 		for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1436 		{
1437 			for (int row = 0; row < 4; row++)
1438 			for (int col = 0; col < 4; col++)
1439 			{
1440 				switch (getOperationTestMatrixType(m_op))
1441 				{
1442 					case TESTMATRIXTYPE_NEGATED:
1443 						m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col);
1444 						break;
1445 					case TESTMATRIXTYPE_INCREMENTED:
1446 						m_userAttribTransforms[attribNdx](row, col) += 0.3f;
1447 						break;
1448 					case TESTMATRIXTYPE_DECREMENTED:
1449 						m_userAttribTransforms[attribNdx](row, col) -= 0.3f;
1450 						break;
1451 					case TESTMATRIXTYPE_NEGATED_INCREMENTED:
1452 						m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col) + 0.3f;
1453 						break;
1454 					case TESTMATRIXTYPE_INCREMENTED_LESS:
1455 						m_userAttribTransforms[attribNdx](row, col) -= 0.1f;
1456 						break;
1457 
1458 					default:
1459 						DE_ASSERT(DE_FALSE);
1460 						break;
1461 				}
1462 			}
1463 		}
1464 	}
1465 
1466 	int	numInputs = isOperationBinary(m_op) ? 2 : 1;
1467 
1468 	for (int inNdx = 0; inNdx < numInputs; inNdx++)
1469 	{
1470 		const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1471 
1472 		if (in.inputType == INPUTTYPE_DYNAMIC && isDataTypeMatrix(in.dataType))
1473 		{
1474 			useAttribute(4u + inNdx, getAttributeType(in.dataType));
1475 		}
1476 	}
1477 
1478 }
1479 
~ShaderMatrixInstance(void)1480 ShaderMatrixInstance::~ShaderMatrixInstance (void)
1481 {
1482 }
1483 
addMatrixUniform(deUint32 bindingLocation,DataType dataType,const float * dataPtr)1484 void ShaderMatrixInstance::addMatrixUniform(deUint32 bindingLocation, DataType dataType, const float *dataPtr)
1485 {
1486 	Mat4			result;
1487 	const size_t	matrixSize = sizeof(float) * 4 * 4;
1488 
1489 	switch(dataType)
1490 	{
1491 		case TYPE_FLOAT_MAT2:
1492 		{
1493 			Mat2 matrix = Mat2(dataPtr);
1494 			result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1495 			result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1496 			break;
1497 		}
1498 		case TYPE_FLOAT_MAT2X3:
1499 		{
1500 			Mat2x3 matrix = Mat2x3(dataPtr);
1501 			result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1502 			result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1503 			break;
1504 		}
1505 		case TYPE_FLOAT_MAT2X4:
1506 		{
1507 			Mat2x4 matrix = Mat2x4(dataPtr);
1508 			result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1509 			result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1510 			break;
1511 		}
1512 		case TYPE_FLOAT_MAT3X2:
1513 		{
1514 			Mat3x2 matrix = Mat3x2(dataPtr);
1515 			result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1516 			result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1517 			result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1518 			break;
1519 		}
1520 		case TYPE_FLOAT_MAT3:
1521 		{
1522 			Mat3 matrix = Mat3(dataPtr);
1523 			result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1524 			result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1525 			result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1526 			break;
1527 		}
1528 		case TYPE_FLOAT_MAT3X4:
1529 		{
1530 			Mat3x4 matrix = Mat3x4(dataPtr);
1531 			result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1532 			result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1533 			result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1534 			break;
1535 		}
1536 		case TYPE_FLOAT_MAT4X2:
1537 		{
1538 			Mat4x2 matrix = Mat4x2(dataPtr);
1539 			result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1540 			result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1541 			result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1542 			result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1543 			break;
1544 		}
1545 		case TYPE_FLOAT_MAT4X3:
1546 		{
1547 			Mat4x3 matrix = Mat4x3(dataPtr);
1548 			result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1549 			result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1550 			result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1551 			result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1552 			break;
1553 		}
1554 		case TYPE_FLOAT_MAT4:
1555 		{
1556 			Mat4 matrix = Mat4(dataPtr);
1557 			result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1558 			result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1559 			result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1560 			result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1561 			break;
1562 		}
1563 		default:
1564 			DE_ASSERT(false);
1565 			break;
1566 	}
1567 
1568 	addUniform(bindingLocation, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, matrixSize, result.getColumnMajorData().getPtr());
1569 }
1570 
setupUniforms(const tcu::Vec4 &)1571 void ShaderMatrixInstance::setupUniforms (const tcu::Vec4&)
1572 {
1573 	const int	numInputs		= isOperationBinary(m_op) ? 2 : 1;
1574 	deUint32	uniformBinding	= 0;
1575 
1576 	for (int inNdx = 0; inNdx < numInputs; inNdx++)
1577 	{
1578 		const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1579 
1580 		if (in.inputType == INPUTTYPE_UNIFORM)
1581 		{
1582 			switch (in.dataType)
1583 			{
1584 				case TYPE_FLOAT:		addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(float), &s_constInFloat[inNdx]);					break;
1585 				case TYPE_FLOAT_VEC2:	addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec2[inNdx]);			break;
1586 				case TYPE_FLOAT_VEC3:	addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec3[inNdx]);			break;
1587 				case TYPE_FLOAT_VEC4:	addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec4[inNdx]);			break;
1588 				// \note GLES3 supports transpose in matrix upload.
1589 				case TYPE_FLOAT_MAT2:	addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x2[inNdx]);	break;
1590 				case TYPE_FLOAT_MAT2X3:	addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x3[inNdx]);	break;
1591 				case TYPE_FLOAT_MAT2X4:	addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x4[inNdx]);	break;
1592 				case TYPE_FLOAT_MAT3X2:	addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x2[inNdx]);	break;
1593 				case TYPE_FLOAT_MAT3:	addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x3[inNdx]);	break;
1594 				case TYPE_FLOAT_MAT3X4:	addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x4[inNdx]);	break;
1595 				case TYPE_FLOAT_MAT4X2:	addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x2[inNdx]);	break;
1596 				case TYPE_FLOAT_MAT4X3:	addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x3[inNdx]);	break;
1597 				case TYPE_FLOAT_MAT4:	addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x4[inNdx]);	break;
1598 				default:
1599 					DE_ASSERT(false);
1600 			}
1601 			uniformBinding++;
1602 		}
1603 	}
1604 }
1605 
1606 // ShaderMatrixCase
1607 
1608 class ShaderMatrixCase : public ShaderRenderCase
1609 {
1610 public:
1611 							ShaderMatrixCase			(tcu::TestContext&	testCtx,
1612 														 const std::string&	name,
1613 														 const std::string&	desc,
1614 														 const ShaderInput&	in0,
1615 														 const ShaderInput&	in1,
1616 														 const MatrixOp		op,
1617 														 bool				isVertexCase);
1618 							~ShaderMatrixCase			(void);
1619 
1620 	virtual TestInstance*	createInstance				(Context& context) const;
1621 
1622 protected:
1623 	void					setupShader					(void);
1624 	std::string				genGLSLMatToVec3Reduction	(const glu::DataType& matType, const char* varName);
1625 
1626 private:
1627 	const ShaderInput		m_in0;
1628 	const ShaderInput		m_in1;
1629 	const MatrixOp			m_op;
1630 };
1631 
ShaderMatrixCase(tcu::TestContext & testCtx,const std::string & name,const std::string & desc,const ShaderInput & in0,const ShaderInput & in1,MatrixOp op,bool isVertexCase)1632 ShaderMatrixCase::ShaderMatrixCase (tcu::TestContext&	testCtx,
1633 									const std::string&	name,
1634 									const std::string&	desc,
1635 									const ShaderInput&	in0,
1636 									const ShaderInput&	in1,
1637 									MatrixOp			op,
1638 									bool				isVertexCase)
1639 	: ShaderRenderCase	(testCtx,
1640 						 name,
1641 						 desc,
1642 						 isVertexCase,
1643 						 new MatrixShaderEvaluator(getEvalFunc(in0, in1, op), in0.inputType, in1.inputType),
1644 						 DE_NULL /* uniform setup */,
1645 						 DE_NULL /* attribute setup */)
1646 	, m_in0				(in0)
1647 	, m_in1				(in1)
1648 	, m_op				(op)
1649 {
1650 	setupShader();
1651 }
1652 
~ShaderMatrixCase(void)1653 ShaderMatrixCase::~ShaderMatrixCase (void)
1654 {
1655 }
1656 
createInstance(Context & context) const1657 TestInstance* ShaderMatrixCase::createInstance (Context& context) const
1658 {
1659 	return new ShaderMatrixInstance(context, m_isVertexCase, *m_evaluator, m_in0, m_in1, m_op);
1660 }
1661 
setupShader(void)1662 void ShaderMatrixCase::setupShader (void)
1663 {
1664 	std::ostringstream	vtx;
1665 	std::ostringstream	frag;
1666 	std::ostringstream&	op				= m_isVertexCase ? vtx : frag;
1667 
1668 	bool				isInDynMat0		= isDataTypeMatrix(m_in0.dataType) && m_in0.inputType == INPUTTYPE_DYNAMIC;
1669 	bool				isInDynMat1		= isDataTypeMatrix(m_in1.dataType) && m_in1.inputType == INPUTTYPE_DYNAMIC;
1670 	string				inValue0;
1671 	string				inValue1;
1672 	DataType			resultType		= TYPE_LAST;
1673 	Precision			resultPrec		= m_in0.precision;
1674 	vector<string>		passVars;
1675 	int					numInputs		= (isOperationBinary(m_op)) ? (2) : (1);
1676 
1677 	std::string			operationValue0;
1678 	std::string			operationValue1;
1679 
1680 	DE_ASSERT(!isInDynMat0 || !isInDynMat1); // Only single dynamic matrix input is allowed.
1681 	DE_UNREF(isInDynMat0 && isInDynMat1);
1682 
1683 	// Compute result type.
1684 	if (m_op == OP_MUL && isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1685 	{
1686 		resultType = getDataTypeMatrix(getDataTypeMatrixNumColumns(m_in1.dataType), getDataTypeMatrixNumRows(m_in0.dataType));
1687 	}
1688 	else if (m_op == OP_OUTER_PRODUCT)
1689 	{
1690 		resultType = getDataTypeMatrix(getDataTypeScalarSize(m_in1.dataType), getDataTypeScalarSize(m_in0.dataType));
1691 	}
1692 	else if (m_op == OP_TRANSPOSE)
1693 	{
1694 		resultType = getDataTypeMatrix(getDataTypeMatrixNumRows(m_in0.dataType), getDataTypeMatrixNumColumns(m_in0.dataType));
1695 	}
1696 	else if (m_op == OP_INVERSE)
1697 	{
1698 		resultType = m_in0.dataType;
1699 	}
1700 	else if (m_op == OP_DETERMINANT)
1701 	{
1702 		resultType = TYPE_FLOAT;
1703 	}
1704 	else if (getOperationType(m_op) == OPERATIONTYPE_UNARY_PREFIX_OPERATOR ||
1705 			 getOperationType(m_op) == OPERATIONTYPE_UNARY_POSTFIX_OPERATOR)
1706 	{
1707 		resultType = m_in0.dataType;
1708 	}
1709 	else if (isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1710 	{
1711 		DE_ASSERT(m_in0.dataType == m_in1.dataType);
1712 		resultType = m_in0.dataType;
1713 	}
1714 	else if (isDataTypeMatrix(m_in0.dataType) || isDataTypeMatrix(m_in1.dataType))
1715 	{
1716 		int			matNdx		= isDataTypeMatrix(m_in0.dataType) ? 0 : 1;
1717 		DataType	matrixType	= matNdx == 0 ? m_in0.dataType : m_in1.dataType;
1718 		DataType	otherType	= matNdx == 0 ? m_in1.dataType : m_in0.dataType;
1719 
1720 		if (otherType == TYPE_FLOAT)
1721 			resultType = matrixType;
1722 		else
1723 		{
1724 			DE_ASSERT(isDataTypeVector(otherType));
1725 			resultType = getDataTypeFloatVec(matNdx == 0 ? getDataTypeMatrixNumRows(matrixType) : getDataTypeMatrixNumColumns(matrixType));
1726 		}
1727 	}
1728 	else
1729 	{
1730 		DE_ASSERT(DE_FALSE);
1731 	}
1732 
1733 	static const std::string header =
1734 		"#version 310 es\n";
1735 
1736 	vtx << header;
1737 	frag << header;
1738 
1739 	vtx << "layout(location = 0) in highp vec4 a_position;\n";
1740 	frag << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1741 	if (m_isVertexCase)
1742 	{
1743 		vtx << "layout(location = 0) out mediump vec4 v_color;\n";
1744 		frag << "layout(location = 0) in mediump vec4 v_color;\n";
1745 	}
1746 
1747 	// Input declarations.
1748 	deUint32 uniformBinding = 0;
1749 	deUint32 padding = 0;
1750 	for (int inNdx = 0; inNdx < numInputs; inNdx++)
1751 	{
1752 		const ShaderInput&	in			= inNdx > 0 ? m_in1 : m_in0;
1753 		const char*			precName	= getPrecisionName(in.precision);
1754 		const char*			typeName	= getDataTypeName(in.dataType);
1755 		string&				inValue		= inNdx > 0 ? inValue1 : inValue0;
1756 
1757 		if (in.inputType == INPUTTYPE_DYNAMIC)
1758 		{
1759 			if (isDataTypeMatrix(in.dataType))
1760 			{
1761 				vtx << "layout(location = " << 4 + inNdx + padding << ") in " << precName << " " << typeName << " a_";
1762 				// a_matN, v_matN
1763 				vtx << typeName << ";\n";
1764 				if (!m_isVertexCase)
1765 				{
1766 					vtx << "layout(location = " << 1 + inNdx + padding << ") out " << precName << " " << typeName << " v_" << typeName << ";\n";
1767 					frag << "layout(location = " << 1 + inNdx + padding << ") in " << precName << " " << typeName << " v_" << typeName << ";\n";
1768 					passVars.push_back(typeName);
1769 				}
1770 
1771 				inValue = string(m_isVertexCase ? "a_" : "v_") + getDataTypeName(in.dataType);
1772 				padding += getDataTypeMatrixNumColumns(in.dataType);
1773 			}
1774 			else
1775 			{
1776 				// a_coords, v_coords
1777 				vtx << "layout(location = 1) in " << precName << " " << typeName << " a_coords;\n";
1778 				if (!m_isVertexCase)
1779 				{
1780 					vtx << "layout(location = " << 1 + padding << ") out " << precName << " " << typeName << " v_coords;\n";
1781 					frag << "layout(location = " << 1 + padding << ") in " << precName << " " << typeName << " v_coords;\n";
1782 					passVars.push_back("coords");
1783 				}
1784 
1785 				inValue = m_isVertexCase ? "a_coords" : "v_coords";
1786 			}
1787 		}
1788 		else if (in.inputType == INPUTTYPE_UNIFORM)
1789 		{
1790 			op << "layout(std140, set = 0, binding = " << uniformBinding++ <<  ") uniform buffer"<< inNdx <<" { " << precName << " " << typeName << " u_in" << inNdx << "; };\n";
1791 			inValue = string("u_in") + de::toString(inNdx);
1792 		}
1793 		else if (in.inputType == INPUTTYPE_CONST)
1794 		{
1795 			op << "const " << precName << " " << typeName << " in" << inNdx << " = ";
1796 
1797 			// Generate declaration.
1798 			switch (in.dataType)
1799 			{
1800 				case TYPE_FLOAT:		op << de::floatToString(s_constInFloat[inNdx], 1);					break;
1801 				case TYPE_FLOAT_VEC2:	writeVectorConstructor<2>(op, s_constInVec2[inNdx]);				break;
1802 				case TYPE_FLOAT_VEC3:	writeVectorConstructor<3>(op, s_constInVec3[inNdx]);				break;
1803 				case TYPE_FLOAT_VEC4:	writeVectorConstructor<4>(op, s_constInVec4[inNdx]);				break;
1804 				case TYPE_FLOAT_MAT2:	writeMatrixConstructor<2, 2>(op, Mat2(s_constInMat2x2[inNdx]));		break;
1805 				case TYPE_FLOAT_MAT2X3:	writeMatrixConstructor<2, 3>(op, Mat2x3(s_constInMat2x3[inNdx]));	break;
1806 				case TYPE_FLOAT_MAT2X4:	writeMatrixConstructor<2, 4>(op, Mat2x4(s_constInMat2x4[inNdx]));	break;
1807 				case TYPE_FLOAT_MAT3X2:	writeMatrixConstructor<3, 2>(op, Mat3x2(s_constInMat3x2[inNdx]));	break;
1808 				case TYPE_FLOAT_MAT3:	writeMatrixConstructor<3, 3>(op, Mat3(s_constInMat3x3[inNdx]));		break;
1809 				case TYPE_FLOAT_MAT3X4:	writeMatrixConstructor<3, 4>(op, Mat3x4(s_constInMat3x4[inNdx]));	break;
1810 				case TYPE_FLOAT_MAT4X2:	writeMatrixConstructor<4, 2>(op, Mat4x2(s_constInMat4x2[inNdx]));	break;
1811 				case TYPE_FLOAT_MAT4X3:	writeMatrixConstructor<4, 3>(op, Mat4x3(s_constInMat4x3[inNdx]));	break;
1812 				case TYPE_FLOAT_MAT4:	writeMatrixConstructor<4, 4>(op, Mat4(s_constInMat4x4[inNdx]));		break;
1813 
1814 				default:
1815 					DE_ASSERT(DE_FALSE);
1816 			}
1817 
1818 			op << ";\n";
1819 
1820 			inValue = string("in") + de::toString(inNdx);
1821 		}
1822 	}
1823 
1824 	vtx << "\n"
1825 		<< "void main (void)\n"
1826 		<< "{\n"
1827 		<< "	gl_Position = a_position;\n";
1828 	frag << "\n"
1829 		 << "void main (void)\n"
1830 		 << "{\n";
1831 
1832 	if (m_isVertexCase)
1833 		frag << "	dEQP_FragColor = v_color;\n";
1834 	else
1835 	{
1836 		for (vector<string>::const_iterator copyIter = passVars.begin(); copyIter != passVars.end(); copyIter++)
1837 			vtx << "	v_" << *copyIter << " = " << "a_" << *copyIter << ";\n";
1838 	}
1839 
1840 	// Operation.
1841 
1842 	switch (getOperationNature(m_op))
1843 	{
1844 		case OPERATIONNATURE_PURE:
1845 			DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1846 
1847 			operationValue0 = inValue0;
1848 			operationValue1 = inValue1;
1849 			break;
1850 
1851 		case OPERATIONNATURE_MUTATING:
1852 			DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1853 
1854 			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " tmpValue = " << inValue0 << ";\n";
1855 
1856 			operationValue0 = "tmpValue";
1857 			operationValue1 = inValue1;
1858 			break;
1859 
1860 		case OPERATIONNATURE_ASSIGNMENT:
1861 			DE_ASSERT(getOperationType(m_op) == OPERATIONTYPE_ASSIGNMENT);
1862 
1863 			operationValue0 = inValue0;
1864 			operationValue1 = inValue1;
1865 			break;
1866 
1867 		default:
1868 			DE_ASSERT(DE_FALSE);
1869 	}
1870 
1871 	switch (getOperationType(m_op))
1872 	{
1873 		case OPERATIONTYPE_BINARY_OPERATOR:
1874 			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << " " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1875 			break;
1876 
1877 		case OPERATIONTYPE_UNARY_PREFIX_OPERATOR:
1878 			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << operationValue0 << ";\n";
1879 			break;
1880 
1881 		case OPERATIONTYPE_UNARY_POSTFIX_OPERATOR:
1882 			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << getOperationName(m_op) << ";\n";
1883 			break;
1884 
1885 		case OPERATIONTYPE_BINARY_FUNCTION:
1886 			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ", " << operationValue1 << ");\n";
1887 			break;
1888 
1889 		case OPERATIONTYPE_UNARY_FUNCTION:
1890 			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ");\n";
1891 			break;
1892 
1893 		case OPERATIONTYPE_ASSIGNMENT:
1894 			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << ";\n";
1895 			op << "	res " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1896 			break;
1897 
1898 		default:
1899 			DE_ASSERT(DE_FALSE);
1900 	}
1901 
1902 	// Reduction to vec3 (rgb). Check the used value too if it was modified
1903 	op << "	" << (m_isVertexCase ? "v_color" : "dEQP_FragColor") << " = ";
1904 
1905 	if (isOperationValueModifying(m_op))
1906 		op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0) + vec4(" << genGLSLMatToVec3Reduction(resultType, "tmpValue") << ", 0.0);\n";
1907 	else
1908 		op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0);\n";
1909 
1910 	vtx << "}\n";
1911 	frag << "}\n";
1912 
1913 	m_vertShaderSource	= vtx.str();
1914 	m_fragShaderSource	= frag.str();
1915 }
1916 
genGLSLMatToVec3Reduction(const glu::DataType & matType,const char * varName)1917 std::string ShaderMatrixCase::genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName)
1918 {
1919 	std::ostringstream op;
1920 
1921 	switch (matType)
1922 	{
1923 		case TYPE_FLOAT:		op << varName << ", "			<< varName << ", "			<< varName << "";																																			break;
1924 		case TYPE_FLOAT_VEC2:	op << varName << ".x, "			<< varName << ".y, "		<< varName << ".x";																																			break;
1925 		case TYPE_FLOAT_VEC3:	op << varName << "";																																																	break;
1926 		case TYPE_FLOAT_VEC4:	op << varName << ".x, "			<< varName << ".y, "		<< varName << ".z+"			<< varName << ".w";																												break;
1927 		case TYPE_FLOAT_MAT2:	op << varName << "[0][0], "		<< varName << "[1][0], "	<< varName << "[0][1]+"		<< varName << "[1][1]";																											break;
1928 		case TYPE_FLOAT_MAT2X3:	op << varName << "[0] + "		<< varName << "[1]";																																									break;
1929 		case TYPE_FLOAT_MAT2X4:	op << varName << "[0].xyz + "	<< varName << "[1].yzw";																																								break;
1930 		case TYPE_FLOAT_MAT3X2:	op << varName << "[0][0]+"		<< varName << "[0][1], "	<< varName << "[1][0]+"		<< varName << "[1][1], "	<< varName << "[2][0]+" << varName << "[2][1]";														break;
1931 		case TYPE_FLOAT_MAT3:	op << varName << "[0] + "		<< varName << "[1] + "		<< varName << "[2]";																																		break;
1932 		case TYPE_FLOAT_MAT3X4:	op << varName << "[0].xyz + "	<< varName << "[1].yzw + "	<< varName << "[2].zwx";																																	break;
1933 		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;
1934 		case TYPE_FLOAT_MAT4X3:	op << varName << "[0] + "		<< varName << "[1] + "		<< varName << "[2] + "		<< varName << "[3]";																											break;
1935 		case TYPE_FLOAT_MAT4:	op << varName << "[0].xyz+"		<< varName << "[1].yzw+"	<< varName << "[2].zwx+"	<< varName << "[3].wxy";																										break;
1936 
1937 		default:
1938 			DE_ASSERT(DE_FALSE);
1939 	}
1940 
1941 	return op.str();
1942 }
1943 
1944 class ShaderMatrixTests : public tcu::TestCaseGroup
1945 {
1946 public:
1947 							ShaderMatrixTests		(tcu::TestContext& testCtx);
1948 	virtual					~ShaderMatrixTests		(void);
1949 
1950 	virtual void			init					(void);
1951 
1952 private:
1953 							ShaderMatrixTests		(const ShaderMatrixTests&);		// not allowed!
1954 	ShaderMatrixTests&		operator=				(const ShaderMatrixTests&);		// not allowed!
1955 };
1956 
ShaderMatrixTests(tcu::TestContext & testCtx)1957 ShaderMatrixTests::ShaderMatrixTests (tcu::TestContext& testCtx)
1958 	: TestCaseGroup(testCtx, "matrix", "Matrix Tests")
1959 {
1960 }
1961 
~ShaderMatrixTests(void)1962 ShaderMatrixTests::~ShaderMatrixTests (void)
1963 {
1964 }
1965 
init(void)1966 void ShaderMatrixTests::init (void)
1967 {
1968 	static const struct
1969 	{
1970 		const char*		name;
1971 		const char*		desc;
1972 		const MatrixOp	op;
1973 		const bool		extendedInputTypeCases; // !< test with const and uniform types too
1974 		const bool		createInputTypeGroup;	// !< create group for input types
1975 	} ops[] =
1976 	{
1977 		{ "add",			"Matrix addition tests",						OP_ADD,				true,	true	},
1978 		{ "sub",			"Matrix subtraction tests",						OP_SUB,				true,	true	},
1979 		{ "mul",			"Matrix multiplication tests",					OP_MUL,				true,	true	},
1980 		{ "div",			"Matrix division tests",						OP_DIV,				true,	true	},
1981 		{ "matrixcompmult",	"Matrix component-wise multiplication tests",	OP_COMP_MUL,		false,	true	},
1982 		{ "outerproduct",	"Matrix outerProduct() tests",					OP_OUTER_PRODUCT,	false,	true	},
1983 		{ "transpose",		"Matrix transpose() tests",						OP_TRANSPOSE,		false,	true	},
1984 		{ "determinant",	"Matrix determinant() tests",					OP_DETERMINANT,		false,	true	},
1985 		{ "inverse",		"Matrix inverse() tests",						OP_INVERSE,			false,	true	},
1986 		{ "unary_addition",	"Matrix unary addition tests",					OP_UNARY_PLUS,		false,	false	},
1987 		{ "negation",		"Matrix negation tests",						OP_NEGATION,		false,	false	},
1988 		{ "pre_increment",	"Matrix prefix increment tests",				OP_PRE_INCREMENT,	false,	false	},
1989 		{ "pre_decrement",	"Matrix prefix decrement tests",				OP_PRE_DECREMENT,	false,	false	},
1990 		{ "post_increment",	"Matrix postfix increment tests",				OP_POST_INCREMENT,	false,	false	},
1991 		{ "post_decrement",	"Matrix postfix decrement tests",				OP_POST_DECREMENT,	false,	false	},
1992 		{ "add_assign",		"Matrix add into tests",						OP_ADD_INTO,		false,	false	},
1993 		{ "sub_assign",		"Matrix subtract from tests",					OP_SUBTRACT_FROM,	false,	false	},
1994 		{ "mul_assign",		"Matrix multiply into tests",					OP_MULTIPLY_INTO,	false,	false	},
1995 		{ "div_assign",		"Matrix divide into tests",						OP_DIVIDE_INTO,		false,	false	},
1996 	};
1997 
1998 	struct InputTypeSpec
1999 	{
2000 		const char*		name;
2001 		const char*		desc;
2002 		const InputType	type;
2003 	};
2004 	static const InputTypeSpec extendedInputTypes[] =
2005 	{
2006 		{ "const",		"Constant matrix input",	INPUTTYPE_CONST		},
2007 		{ "uniform",	"Uniform matrix input",		INPUTTYPE_UNIFORM	},
2008 		{ "dynamic",	"Dynamic matrix input",		INPUTTYPE_DYNAMIC	}
2009 	};
2010 	static const InputTypeSpec reducedInputTypes[] =
2011 	{
2012 		{ "dynamic",	"Dynamic matrix input",		INPUTTYPE_DYNAMIC	}
2013 	};
2014 
2015 	static const DataType matrixTypes[] =
2016 	{
2017 		TYPE_FLOAT_MAT2,
2018 		TYPE_FLOAT_MAT2X3,
2019 		TYPE_FLOAT_MAT2X4,
2020 		TYPE_FLOAT_MAT3X2,
2021 		TYPE_FLOAT_MAT3,
2022 		TYPE_FLOAT_MAT3X4,
2023 		TYPE_FLOAT_MAT4X2,
2024 		TYPE_FLOAT_MAT4X3,
2025 		TYPE_FLOAT_MAT4
2026 	};
2027 
2028 	static const Precision precisions[] =
2029 	{
2030 		PRECISION_MEDIUMP,
2031 		PRECISION_HIGHP
2032 	};
2033 
2034 	for (int opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
2035 	{
2036 		const InputTypeSpec*	inTypeList		= (ops[opNdx].extendedInputTypeCases) ? (extendedInputTypes) : (reducedInputTypes);
2037 		const int				inTypeListSize	= (ops[opNdx].extendedInputTypeCases) ? (DE_LENGTH_OF_ARRAY(extendedInputTypes)) : (DE_LENGTH_OF_ARRAY(reducedInputTypes));
2038 		const MatrixOp			op				= ops[opNdx].op;
2039 		tcu::TestCaseGroup*		opGroup			= new tcu::TestCaseGroup(m_testCtx, ops[opNdx].name, ops[opNdx].desc);
2040 
2041 		addChild(opGroup);
2042 
2043 		for (int inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++)
2044 		{
2045 			const InputType		inputType	= inTypeList[inTypeNdx].type;
2046 			tcu::TestCaseGroup* inGroup;
2047 
2048 			if (ops[opNdx].createInputTypeGroup)
2049 			{
2050 				inGroup = new tcu::TestCaseGroup(m_testCtx, inTypeList[inTypeNdx].name, inTypeList[inTypeNdx].desc);
2051 				opGroup->addChild(inGroup);
2052 			}
2053 			else
2054 				inGroup = opGroup;
2055 
2056 			for (int matTypeNdx = 0; matTypeNdx < DE_LENGTH_OF_ARRAY(matrixTypes); matTypeNdx++)
2057 			{
2058 				DataType	matType		= matrixTypes[matTypeNdx];
2059 				int			numCols		= getDataTypeMatrixNumColumns(matType);
2060 				int			numRows		= getDataTypeMatrixNumRows(matType);
2061 				const char*	matTypeName	= getDataTypeName(matType);
2062 
2063 				for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
2064 				{
2065 					Precision	precision	= precisions[precNdx];
2066 					const char*	precName	= getPrecisionName(precision);
2067 					string		baseName	= string(precName) + "_" + matTypeName + "_";
2068 					ShaderInput	matIn		(inputType, matType, precision);
2069 
2070 					if (isOperationMatrixScalar(op))
2071 					{
2072 						// Matrix-scalar \note For div cases we use uniform input.
2073 						ShaderInput scalarIn(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, TYPE_FLOAT, precision);
2074 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(),		"Matrix-scalar case", matIn, scalarIn, op, true));
2075 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(),	"Matrix-scalar case", matIn, scalarIn, op, false));
2076 					}
2077 
2078 					if (isOperationMatrixVector(op))
2079 					{
2080 						// Matrix-vector.
2081 						DataType	colVecType	= getDataTypeFloatVec(numCols);
2082 						ShaderInput colVecIn	(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, colVecType, precision);
2083 
2084 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_vertex").c_str(),		"Matrix-vector case", matIn, colVecIn, op, true));
2085 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_fragment").c_str(),	"Matrix-vector case", matIn, colVecIn, op, false));
2086 
2087 						// Vector-matrix.
2088 						DataType	rowVecType	= getDataTypeFloatVec(numRows);
2089 						ShaderInput	rowVecIn	(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, rowVecType, precision);
2090 						string		vecMatName	= string(precName) + "_" + getDataTypeName(rowVecType) + "_" + matTypeName;
2091 
2092 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_vertex").c_str(),		"Vector-matrix case", rowVecIn, matIn, op, true));
2093 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_fragment").c_str(),	"Vector-matrix case", rowVecIn, matIn, op, false));
2094 					}
2095 
2096 					if (isOperationArithmeticMatrixMatrix(op))
2097 					{
2098 						// Arithmetic matrix-matrix multiplication.
2099 						for (int otherCols = 2; otherCols <= 4; otherCols++)
2100 						{
2101 							ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, getDataTypeMatrix(otherCols, numCols /* rows */), precision);
2102 							inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_vertex").c_str(),	"Matrix-matrix case", matIn, otherMatIn, op, true));
2103 							inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_fragment").c_str(),	"Matrix-matrix case", matIn, otherMatIn, op, false));
2104 						}
2105 					}
2106 					else if (isOperationComponentwiseMatrixMatrix(op))
2107 					{
2108 						// Component-wise.
2109 						ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2110 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_vertex").c_str(),		"Matrix-matrix case", matIn, otherMatIn, op, true));
2111 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_fragment").c_str(),	"Matrix-matrix case", matIn, otherMatIn, op, false));
2112 					}
2113 
2114 					if (isOperationVectorVector(op))
2115 					{
2116 						ShaderInput vec1In(inputType,																getDataTypeFloatVec(numRows), precision);
2117 						ShaderInput vec2In((inputType == INPUTTYPE_DYNAMIC) ? (INPUTTYPE_UNIFORM) : (inputType),	getDataTypeFloatVec(numCols), precision);
2118 
2119 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(),		"Vector-vector case", vec1In, vec2In, op, true));
2120 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(),	"Vector-vector case", vec1In, vec2In, op, false));
2121 					}
2122 
2123 					if ((isOperationUnaryAnyMatrix(op)) ||
2124 						(isOperationUnarySymmetricMatrix(op) && numCols == numRows))
2125 					{
2126 						ShaderInput voidInput(INPUTTYPE_LAST, TYPE_LAST, PRECISION_LAST);
2127 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(),		"Matrix case", matIn, voidInput, op, true));
2128 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(),	"Matrix case", matIn, voidInput, op, false));
2129 					}
2130 
2131 					if ((isOperationAssignmentAnyMatrix(op)) ||
2132 						(isOperationAssignmentSymmetricMatrix(op) && numCols == numRows))
2133 					{
2134 						ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2135 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(),		"Matrix assignment case", matIn, otherMatIn, op, true));
2136 						inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(),	"Matrix assignment case", matIn, otherMatIn, op, false));
2137 					}
2138 				}
2139 			}
2140 		}
2141 	}
2142 }
2143 
2144 } // anonymous
2145 
createMatrixTests(tcu::TestContext & testCtx)2146 tcu::TestCaseGroup* createMatrixTests (tcu::TestContext& testCtx)
2147 {
2148 	return new ShaderMatrixTests(testCtx);
2149 }
2150 
2151 } // sr
2152 } // vkt
2153