1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 2.0 Module
3e5c31af7Sopenharmony_ci * -------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Shader matrix arithmetic tests.
22e5c31af7Sopenharmony_ci *
23e5c31af7Sopenharmony_ci * Variables:
24e5c31af7Sopenharmony_ci *  + operation
25e5c31af7Sopenharmony_ci *    - mat OP mat
26e5c31af7Sopenharmony_ci *    - mat OP vec
27e5c31af7Sopenharmony_ci *    - vec OP mat
28e5c31af7Sopenharmony_ci *    - mat OP scalar
29e5c31af7Sopenharmony_ci *    - OP mat
30e5c31af7Sopenharmony_ci *  + matrix source
31e5c31af7Sopenharmony_ci *    - constant (ctor)
32e5c31af7Sopenharmony_ci *    - uniform
33e5c31af7Sopenharmony_ci *    - vertex input
34e5c31af7Sopenharmony_ci *    - fragment input
35e5c31af7Sopenharmony_ci *  + other operand: always dynamic data?
36e5c31af7Sopenharmony_ci *  + how to reduce to vec3?
37e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_ci#include "es2fShaderMatrixTests.hpp"
40e5c31af7Sopenharmony_ci#include "glsShaderRenderCase.hpp"
41e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp"
42e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
43e5c31af7Sopenharmony_ci#include "tcuMatrix.hpp"
44e5c31af7Sopenharmony_ci#include "tcuMatrixUtil.hpp"
45e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
48e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_cinamespace deqp
51e5c31af7Sopenharmony_ci{
52e5c31af7Sopenharmony_cinamespace gles2
53e5c31af7Sopenharmony_ci{
54e5c31af7Sopenharmony_cinamespace Functional
55e5c31af7Sopenharmony_ci{
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_ciusing std::string;
58e5c31af7Sopenharmony_ciusing std::vector;
59e5c31af7Sopenharmony_ciusing namespace glu;
60e5c31af7Sopenharmony_ciusing namespace deqp::gls;
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_ciusing tcu::Vec2;
63e5c31af7Sopenharmony_ciusing tcu::Vec3;
64e5c31af7Sopenharmony_ciusing tcu::Vec4;
65e5c31af7Sopenharmony_ciusing tcu::Mat2;
66e5c31af7Sopenharmony_ciusing tcu::Mat3;
67e5c31af7Sopenharmony_ciusing tcu::Mat4;
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_ci// Uniform / constant values for tests.
70e5c31af7Sopenharmony_ci// \note Input1 should not contain 0 components as it is used as divisor in div cases.
71e5c31af7Sopenharmony_ci// \todo [2012-02-14 pyry] Make these dynamic.
72e5c31af7Sopenharmony_cistatic const float	s_constInFloat[2]	= { 0.5f, -0.2f };
73e5c31af7Sopenharmony_cistatic const Vec2	s_constInVec2[2]	= { Vec2(1.2f, 0.5f), Vec2(0.5f, 1.0f) };
74e5c31af7Sopenharmony_cistatic const Vec3	s_constInVec3[2]	= { Vec3(1.1f, 0.1f, 0.5f), Vec3(-0.2f, 0.5f, 0.8f) };
75e5c31af7Sopenharmony_cistatic const Vec4	s_constInVec4[2]	= { Vec4(1.4f, 0.2f, -0.5f, 0.7f), Vec4(0.2f, -1.0f, 0.5f, 0.8f) };
76e5c31af7Sopenharmony_ci
77e5c31af7Sopenharmony_cistatic const float s_constInMat20[] = { 0.6f, -1.0f, 0.7f, 0.4f };
78e5c31af7Sopenharmony_cistatic const float s_constInMat21[] = { -0.5f, -0.4f, 0.7f, -0.8f };
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_cistatic const float s_constInMat31[] =
81e5c31af7Sopenharmony_ci{
82e5c31af7Sopenharmony_ci	1.2f,  0.1f, -0.1f,
83e5c31af7Sopenharmony_ci	0.1f,  0.9f,  0.2f,
84e5c31af7Sopenharmony_ci	0.2f, -0.1f,  0.7f
85e5c31af7Sopenharmony_ci};
86e5c31af7Sopenharmony_cistatic const float s_constInMat41[] =
87e5c31af7Sopenharmony_ci{
88e5c31af7Sopenharmony_ci	 1.2f, -0.2f,  0.4f,  0.1f,
89e5c31af7Sopenharmony_ci	 0.1f,  0.8f, -0.1f, -0.2f,
90e5c31af7Sopenharmony_ci	-0.2f,  0.1f, -1.1f,  0.3f,
91e5c31af7Sopenharmony_ci	 0.1f,  0.2f,  0.3f,  0.9f
92e5c31af7Sopenharmony_ci};
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_cistatic const Mat2	s_constInMat2[2]	= { tcu::Mat2(s_constInMat20), tcu::Mat2(s_constInMat21) };
95e5c31af7Sopenharmony_cistatic const Mat3	s_constInMat3[2]	= { tcu::translationMatrix(tcu::Vec2(0.2f, -0.3f)), tcu::Mat3(s_constInMat31) };
96e5c31af7Sopenharmony_cistatic const Mat4	s_constInMat4[2]	= { tcu::translationMatrix(tcu::Vec3(0.2f, -0.3f, 0.15f)), tcu::Mat4(s_constInMat41) };
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_cinamespace MatrixCaseUtils
99e5c31af7Sopenharmony_ci{
100e5c31af7Sopenharmony_ci
101e5c31af7Sopenharmony_cienum InputType
102e5c31af7Sopenharmony_ci{
103e5c31af7Sopenharmony_ci	INPUTTYPE_CONST = 0,
104e5c31af7Sopenharmony_ci	INPUTTYPE_UNIFORM,
105e5c31af7Sopenharmony_ci	INPUTTYPE_DYNAMIC,
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	INPUTTYPE_LAST
108e5c31af7Sopenharmony_ci};
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_cistruct ShaderInput
111e5c31af7Sopenharmony_ci{
112e5c31af7Sopenharmony_ci	ShaderInput (InputType inputType_, DataType dataType_, Precision precision_)
113e5c31af7Sopenharmony_ci		: inputType	(inputType_)
114e5c31af7Sopenharmony_ci		, dataType	(dataType_)
115e5c31af7Sopenharmony_ci		, precision	(precision_)
116e5c31af7Sopenharmony_ci	{
117e5c31af7Sopenharmony_ci	}
118e5c31af7Sopenharmony_ci
119e5c31af7Sopenharmony_ci	InputType		inputType;
120e5c31af7Sopenharmony_ci	DataType		dataType;
121e5c31af7Sopenharmony_ci	Precision		precision;
122e5c31af7Sopenharmony_ci};
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_cienum MatrixOp
125e5c31af7Sopenharmony_ci{
126e5c31af7Sopenharmony_ci	OP_ADD = 0,
127e5c31af7Sopenharmony_ci	OP_SUB,
128e5c31af7Sopenharmony_ci	OP_MUL,
129e5c31af7Sopenharmony_ci	OP_DIV,
130e5c31af7Sopenharmony_ci	OP_COMP_MUL,
131e5c31af7Sopenharmony_ci	OP_UNARY_PLUS,
132e5c31af7Sopenharmony_ci	OP_NEGATION,
133e5c31af7Sopenharmony_ci	OP_PRE_INCREMENT,
134e5c31af7Sopenharmony_ci	OP_PRE_DECREMENT,
135e5c31af7Sopenharmony_ci	OP_POST_INCREMENT,
136e5c31af7Sopenharmony_ci	OP_POST_DECREMENT,
137e5c31af7Sopenharmony_ci	OP_ADD_INTO,
138e5c31af7Sopenharmony_ci	OP_SUBTRACT_FROM,
139e5c31af7Sopenharmony_ci	OP_MULTIPLY_INTO,
140e5c31af7Sopenharmony_ci	OP_DIVIDE_INTO,
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_ci	OP_LAST
143e5c31af7Sopenharmony_ci};
144e5c31af7Sopenharmony_ci
145e5c31af7Sopenharmony_ci// Type traits.
146e5c31af7Sopenharmony_ci
147e5c31af7Sopenharmony_citemplate <int DataT>
148e5c31af7Sopenharmony_cistruct TypeTraits;
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_ci#define DECLARE_TYPE_TRAIT(DATATYPE, TYPE)	\
151e5c31af7Sopenharmony_citemplate<>									\
152e5c31af7Sopenharmony_cistruct TypeTraits<DATATYPE> {				\
153e5c31af7Sopenharmony_ci	typedef TYPE Type;						\
154e5c31af7Sopenharmony_ci}
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ciDECLARE_TYPE_TRAIT(TYPE_FLOAT,		float);
157e5c31af7Sopenharmony_ciDECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC2,	tcu::Vec2);
158e5c31af7Sopenharmony_ciDECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC3,	tcu::Vec3);
159e5c31af7Sopenharmony_ciDECLARE_TYPE_TRAIT(TYPE_FLOAT_VEC4,	tcu::Vec4);
160e5c31af7Sopenharmony_ciDECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT2, tcu::Mat2);
161e5c31af7Sopenharmony_ciDECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT3, tcu::Mat3);
162e5c31af7Sopenharmony_ciDECLARE_TYPE_TRAIT(TYPE_FLOAT_MAT4, tcu::Mat4);
163e5c31af7Sopenharmony_ci
164e5c31af7Sopenharmony_ci// Operation info
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_cienum OperationType
167e5c31af7Sopenharmony_ci{
168e5c31af7Sopenharmony_ci	OPERATIONTYPE_BINARY_OPERATOR = 0,
169e5c31af7Sopenharmony_ci	OPERATIONTYPE_BINARY_FUNCTION,
170e5c31af7Sopenharmony_ci	OPERATIONTYPE_UNARY_PREFIX_OPERATOR,
171e5c31af7Sopenharmony_ci	OPERATIONTYPE_UNARY_POSTFIX_OPERATOR,
172e5c31af7Sopenharmony_ci	OPERATIONTYPE_ASSIGNMENT,
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_ci	OPERATIONTYPE_LAST
175e5c31af7Sopenharmony_ci};
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_cistatic const char* getOperationName (MatrixOp op)
178e5c31af7Sopenharmony_ci{
179e5c31af7Sopenharmony_ci	switch (op)
180e5c31af7Sopenharmony_ci	{
181e5c31af7Sopenharmony_ci		case OP_ADD:			return "+";
182e5c31af7Sopenharmony_ci		case OP_SUB:			return "-";
183e5c31af7Sopenharmony_ci		case OP_MUL:			return "*";
184e5c31af7Sopenharmony_ci		case OP_DIV:			return "/";
185e5c31af7Sopenharmony_ci		case OP_COMP_MUL:		return "matrixCompMult";
186e5c31af7Sopenharmony_ci		case OP_UNARY_PLUS:		return "+";
187e5c31af7Sopenharmony_ci		case OP_NEGATION:		return "-";
188e5c31af7Sopenharmony_ci		case OP_PRE_INCREMENT:	return "++";
189e5c31af7Sopenharmony_ci		case OP_PRE_DECREMENT:	return "--";
190e5c31af7Sopenharmony_ci		case OP_POST_INCREMENT:	return "++";
191e5c31af7Sopenharmony_ci		case OP_POST_DECREMENT:	return "--";
192e5c31af7Sopenharmony_ci		case OP_ADD_INTO:		return "+=";
193e5c31af7Sopenharmony_ci		case OP_SUBTRACT_FROM:	return "-=";
194e5c31af7Sopenharmony_ci		case OP_MULTIPLY_INTO:	return "*=";
195e5c31af7Sopenharmony_ci		case OP_DIVIDE_INTO:	return "/=";
196e5c31af7Sopenharmony_ci		default:
197e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
198e5c31af7Sopenharmony_ci			return "";
199e5c31af7Sopenharmony_ci	}
200e5c31af7Sopenharmony_ci}
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_cistatic OperationType getOperationType (MatrixOp op)
203e5c31af7Sopenharmony_ci{
204e5c31af7Sopenharmony_ci	switch (op)
205e5c31af7Sopenharmony_ci	{
206e5c31af7Sopenharmony_ci		case OP_ADD:			return OPERATIONTYPE_BINARY_OPERATOR;
207e5c31af7Sopenharmony_ci		case OP_SUB:			return OPERATIONTYPE_BINARY_OPERATOR;
208e5c31af7Sopenharmony_ci		case OP_MUL:			return OPERATIONTYPE_BINARY_OPERATOR;
209e5c31af7Sopenharmony_ci		case OP_DIV:			return OPERATIONTYPE_BINARY_OPERATOR;
210e5c31af7Sopenharmony_ci		case OP_COMP_MUL:		return OPERATIONTYPE_BINARY_FUNCTION;
211e5c31af7Sopenharmony_ci		case OP_UNARY_PLUS:		return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
212e5c31af7Sopenharmony_ci		case OP_NEGATION:		return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
213e5c31af7Sopenharmony_ci		case OP_PRE_INCREMENT:	return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
214e5c31af7Sopenharmony_ci		case OP_PRE_DECREMENT:	return OPERATIONTYPE_UNARY_PREFIX_OPERATOR;
215e5c31af7Sopenharmony_ci		case OP_POST_INCREMENT:	return OPERATIONTYPE_UNARY_POSTFIX_OPERATOR;
216e5c31af7Sopenharmony_ci		case OP_POST_DECREMENT:	return OPERATIONTYPE_UNARY_POSTFIX_OPERATOR;
217e5c31af7Sopenharmony_ci		case OP_ADD_INTO:		return OPERATIONTYPE_ASSIGNMENT;
218e5c31af7Sopenharmony_ci		case OP_SUBTRACT_FROM:	return OPERATIONTYPE_ASSIGNMENT;
219e5c31af7Sopenharmony_ci		case OP_MULTIPLY_INTO:	return OPERATIONTYPE_ASSIGNMENT;
220e5c31af7Sopenharmony_ci		case OP_DIVIDE_INTO:	return OPERATIONTYPE_ASSIGNMENT;
221e5c31af7Sopenharmony_ci		default:
222e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
223e5c31af7Sopenharmony_ci			return OPERATIONTYPE_LAST;
224e5c31af7Sopenharmony_ci	}
225e5c31af7Sopenharmony_ci}
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_cienum TestMatrixType
228e5c31af7Sopenharmony_ci{
229e5c31af7Sopenharmony_ci	TESTMATRIXTYPE_DEFAULT = 0,
230e5c31af7Sopenharmony_ci	TESTMATRIXTYPE_NEGATED,
231e5c31af7Sopenharmony_ci	TESTMATRIXTYPE_INCREMENTED,
232e5c31af7Sopenharmony_ci	TESTMATRIXTYPE_DECREMENTED,
233e5c31af7Sopenharmony_ci
234e5c31af7Sopenharmony_ci	TESTMATRIXTYPE_LAST
235e5c31af7Sopenharmony_ci};
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_cistatic TestMatrixType getOperationTestMatrixType (MatrixOp op)
238e5c31af7Sopenharmony_ci{
239e5c31af7Sopenharmony_ci	switch(op)
240e5c31af7Sopenharmony_ci	{
241e5c31af7Sopenharmony_ci		case OP_ADD:			return TESTMATRIXTYPE_DEFAULT;
242e5c31af7Sopenharmony_ci		case OP_SUB:			return TESTMATRIXTYPE_DEFAULT;
243e5c31af7Sopenharmony_ci		case OP_MUL:			return TESTMATRIXTYPE_DEFAULT;
244e5c31af7Sopenharmony_ci		case OP_DIV:			return TESTMATRIXTYPE_DEFAULT;
245e5c31af7Sopenharmony_ci		case OP_COMP_MUL:		return TESTMATRIXTYPE_DEFAULT;
246e5c31af7Sopenharmony_ci		case OP_UNARY_PLUS:		return TESTMATRIXTYPE_DEFAULT;
247e5c31af7Sopenharmony_ci		case OP_NEGATION:		return TESTMATRIXTYPE_NEGATED;
248e5c31af7Sopenharmony_ci		case OP_PRE_INCREMENT:	return TESTMATRIXTYPE_NEGATED;
249e5c31af7Sopenharmony_ci		case OP_PRE_DECREMENT:	return TESTMATRIXTYPE_INCREMENTED;
250e5c31af7Sopenharmony_ci		case OP_POST_INCREMENT:	return TESTMATRIXTYPE_NEGATED;
251e5c31af7Sopenharmony_ci		case OP_POST_DECREMENT:	return TESTMATRIXTYPE_DEFAULT;
252e5c31af7Sopenharmony_ci		case OP_ADD_INTO:		return TESTMATRIXTYPE_DECREMENTED;
253e5c31af7Sopenharmony_ci		case OP_SUBTRACT_FROM:	return TESTMATRIXTYPE_DEFAULT;
254e5c31af7Sopenharmony_ci		case OP_MULTIPLY_INTO:	return TESTMATRIXTYPE_DEFAULT;
255e5c31af7Sopenharmony_ci		case OP_DIVIDE_INTO:	return TESTMATRIXTYPE_DEFAULT;
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci		default:
258e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
259e5c31af7Sopenharmony_ci			return TESTMATRIXTYPE_LAST;
260e5c31af7Sopenharmony_ci	}
261e5c31af7Sopenharmony_ci}
262e5c31af7Sopenharmony_ci
263e5c31af7Sopenharmony_cistatic bool isOperationBinary (MatrixOp op)
264e5c31af7Sopenharmony_ci{
265e5c31af7Sopenharmony_ci	return getOperationType(op) == OPERATIONTYPE_BINARY_OPERATOR ||
266e5c31af7Sopenharmony_ci	       getOperationType(op) == OPERATIONTYPE_BINARY_FUNCTION ||
267e5c31af7Sopenharmony_ci	       getOperationType(op) == OPERATIONTYPE_ASSIGNMENT;
268e5c31af7Sopenharmony_ci}
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_cistatic bool isOperationMatrixScalar (MatrixOp op)
271e5c31af7Sopenharmony_ci{
272e5c31af7Sopenharmony_ci	return op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV;
273e5c31af7Sopenharmony_ci}
274e5c31af7Sopenharmony_ci
275e5c31af7Sopenharmony_cistatic bool isOperationMatrixVector (MatrixOp op)
276e5c31af7Sopenharmony_ci{
277e5c31af7Sopenharmony_ci	return op == OP_MUL;
278e5c31af7Sopenharmony_ci}
279e5c31af7Sopenharmony_ci
280e5c31af7Sopenharmony_cistatic bool isOperationMatrixMatrix (MatrixOp op)
281e5c31af7Sopenharmony_ci{
282e5c31af7Sopenharmony_ci	return op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV || op == OP_COMP_MUL;
283e5c31af7Sopenharmony_ci}
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_cistatic bool isOperationUnary (MatrixOp op)
286e5c31af7Sopenharmony_ci{
287e5c31af7Sopenharmony_ci	return  op == OP_UNARY_PLUS			||
288e5c31af7Sopenharmony_ci			op == OP_NEGATION			||
289e5c31af7Sopenharmony_ci			op == OP_PRE_INCREMENT		||
290e5c31af7Sopenharmony_ci			op == OP_PRE_DECREMENT		||
291e5c31af7Sopenharmony_ci			op == OP_POST_INCREMENT		||
292e5c31af7Sopenharmony_ci			op == OP_POST_DECREMENT;
293e5c31af7Sopenharmony_ci}
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_cistatic bool isOperationValueModifying (MatrixOp op)
296e5c31af7Sopenharmony_ci{
297e5c31af7Sopenharmony_ci	return  op == OP_PRE_INCREMENT		||
298e5c31af7Sopenharmony_ci			op == OP_PRE_DECREMENT		||
299e5c31af7Sopenharmony_ci			op == OP_POST_INCREMENT		||
300e5c31af7Sopenharmony_ci			op == OP_POST_DECREMENT;
301e5c31af7Sopenharmony_ci}
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_cistatic bool isOperationAssignment (MatrixOp op)
304e5c31af7Sopenharmony_ci{
305e5c31af7Sopenharmony_ci	return  op == OP_ADD_INTO		 ||
306e5c31af7Sopenharmony_ci			op == OP_SUBTRACT_FROM	 ||
307e5c31af7Sopenharmony_ci			op == OP_MULTIPLY_INTO	 ||
308e5c31af7Sopenharmony_ci			op == OP_DIVIDE_INTO;
309e5c31af7Sopenharmony_ci}
310e5c31af7Sopenharmony_ci
311e5c31af7Sopenharmony_ci// Operation nature
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_cienum OperationNature
314e5c31af7Sopenharmony_ci{
315e5c31af7Sopenharmony_ci	OPERATIONNATURE_PURE = 0,
316e5c31af7Sopenharmony_ci	OPERATIONNATURE_MUTATING,
317e5c31af7Sopenharmony_ci	OPERATIONNATURE_ASSIGNMENT,
318e5c31af7Sopenharmony_ci
319e5c31af7Sopenharmony_ci	OPERATIONNATURE_LAST
320e5c31af7Sopenharmony_ci};
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_cistatic OperationNature getOperationNature (MatrixOp op)
323e5c31af7Sopenharmony_ci{
324e5c31af7Sopenharmony_ci	if (isOperationAssignment(op))
325e5c31af7Sopenharmony_ci		return OPERATIONNATURE_ASSIGNMENT;
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_ci	if (isOperationValueModifying(op))
328e5c31af7Sopenharmony_ci		return OPERATIONNATURE_MUTATING;
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_ci	return OPERATIONNATURE_PURE;
331e5c31af7Sopenharmony_ci}
332e5c31af7Sopenharmony_ci
333e5c31af7Sopenharmony_ci// Input value loader.
334e5c31af7Sopenharmony_ci
335e5c31af7Sopenharmony_citemplate <int InputT, int DataT>
336e5c31af7Sopenharmony_citypename TypeTraits<DataT>::Type getInputValue (const ShaderEvalContext& evalCtx, int inputNdx);
337e5c31af7Sopenharmony_ci
338e5c31af7Sopenharmony_citemplate <> inline float		getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT>			(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInFloat[inputNdx];	}
339e5c31af7Sopenharmony_citemplate <> inline tcu::Vec2	getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT_VEC2>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec2[inputNdx];	}
340e5c31af7Sopenharmony_citemplate <> inline tcu::Vec3	getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT_VEC3>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec3[inputNdx];	}
341e5c31af7Sopenharmony_citemplate <> inline tcu::Vec4	getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT_VEC4>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInVec4[inputNdx];	}
342e5c31af7Sopenharmony_citemplate <> inline tcu::Mat2	getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT_MAT2>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInMat2[inputNdx];	}
343e5c31af7Sopenharmony_citemplate <> inline tcu::Mat3	getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT_MAT3>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInMat3[inputNdx];	}
344e5c31af7Sopenharmony_citemplate <> inline tcu::Mat4	getInputValue<INPUTTYPE_CONST,		TYPE_FLOAT_MAT4>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(evalCtx); return s_constInMat4[inputNdx];	}
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_citemplate <> inline float		getInputValue<INPUTTYPE_DYNAMIC,	TYPE_FLOAT>			(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.x();					}
347e5c31af7Sopenharmony_citemplate <> inline tcu::Vec2	getInputValue<INPUTTYPE_DYNAMIC,	TYPE_FLOAT_VEC2>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.swizzle(0, 1);			}
348e5c31af7Sopenharmony_citemplate <> inline tcu::Vec3	getInputValue<INPUTTYPE_DYNAMIC,	TYPE_FLOAT_VEC3>	(const ShaderEvalContext& evalCtx, int inputNdx) { DE_UNREF(inputNdx); return evalCtx.coords.swizzle(0, 1, 2);		}
349e5c31af7Sopenharmony_citemplate <> 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);	}
350e5c31af7Sopenharmony_ci
351e5c31af7Sopenharmony_citemplate <> inline tcu::Mat2 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT2> (const ShaderEvalContext& evalCtx, int inputNdx)
352e5c31af7Sopenharmony_ci{
353e5c31af7Sopenharmony_ci	DE_UNREF(inputNdx); // Not used.
354e5c31af7Sopenharmony_ci	tcu::Mat2 m;
355e5c31af7Sopenharmony_ci	m.setColumn(0, evalCtx.in[0].swizzle(0,1));
356e5c31af7Sopenharmony_ci	m.setColumn(1, evalCtx.in[1].swizzle(0,1));
357e5c31af7Sopenharmony_ci	return m;
358e5c31af7Sopenharmony_ci}
359e5c31af7Sopenharmony_ci
360e5c31af7Sopenharmony_citemplate <> inline tcu::Mat3 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT3> (const ShaderEvalContext& evalCtx, int inputNdx)
361e5c31af7Sopenharmony_ci{
362e5c31af7Sopenharmony_ci	DE_UNREF(inputNdx); // Not used.
363e5c31af7Sopenharmony_ci	tcu::Mat3 m;
364e5c31af7Sopenharmony_ci	m.setColumn(0, evalCtx.in[0].swizzle(0,1,2));
365e5c31af7Sopenharmony_ci	m.setColumn(1, evalCtx.in[1].swizzle(0,1,2));
366e5c31af7Sopenharmony_ci	m.setColumn(2, evalCtx.in[2].swizzle(0,1,2));
367e5c31af7Sopenharmony_ci	return m;
368e5c31af7Sopenharmony_ci}
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_citemplate <> inline tcu::Mat4 getInputValue<INPUTTYPE_DYNAMIC, TYPE_FLOAT_MAT4> (const ShaderEvalContext& evalCtx, int inputNdx)
371e5c31af7Sopenharmony_ci{
372e5c31af7Sopenharmony_ci	DE_UNREF(inputNdx); // Not used.
373e5c31af7Sopenharmony_ci	tcu::Mat4 m;
374e5c31af7Sopenharmony_ci	m.setColumn(0, evalCtx.in[0]);
375e5c31af7Sopenharmony_ci	m.setColumn(1, evalCtx.in[1]);
376e5c31af7Sopenharmony_ci	m.setColumn(2, evalCtx.in[2]);
377e5c31af7Sopenharmony_ci	m.setColumn(3, evalCtx.in[3]);
378e5c31af7Sopenharmony_ci	return m;
379e5c31af7Sopenharmony_ci}
380e5c31af7Sopenharmony_ci
381e5c31af7Sopenharmony_ci// Reduction from expression result to vec3.
382e5c31af7Sopenharmony_ci
383e5c31af7Sopenharmony_ciinline tcu::Vec3 reduceToVec3 (const tcu::Vec2& value) { return value.swizzle(0,1,0); }
384e5c31af7Sopenharmony_ciinline tcu::Vec3 reduceToVec3 (const tcu::Vec3& value) { return value; }
385e5c31af7Sopenharmony_ciinline tcu::Vec3 reduceToVec3 (const tcu::Vec4& value) { return tcu::Vec3(value.x(), value.y(), value.z()+value.w()); }
386e5c31af7Sopenharmony_ciinline tcu::Vec3 reduceToVec3 (const tcu::Mat2& value) { return tcu::Vec3(value(0, 0), value(0, 1), value(1, 0)+value(1, 1)); }
387e5c31af7Sopenharmony_ciinline tcu::Vec3 reduceToVec3 (const tcu::Mat3& value) { return value.getColumn(0) + value.getColumn(1) + value.getColumn(2); }
388e5c31af7Sopenharmony_ciinline 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); }
389e5c31af7Sopenharmony_ci
390e5c31af7Sopenharmony_ci// matrixCompMult
391e5c31af7Sopenharmony_ci
392e5c31af7Sopenharmony_citemplate <typename T, int Rows, int Cols>
393e5c31af7Sopenharmony_citcu::Matrix<T, Rows, Cols> matrixCompMult (const tcu::Matrix<T, Rows, Cols>& a, const tcu::Matrix<T, Rows, Cols>& b)
394e5c31af7Sopenharmony_ci{
395e5c31af7Sopenharmony_ci	tcu::Matrix<T, Rows, Cols> retVal;
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci	for (int r = 0; r < Rows; ++r)
398e5c31af7Sopenharmony_ci		for (int c = 0; c < Cols; ++c)
399e5c31af7Sopenharmony_ci			retVal(r,c) = a(r,c) * b(r, c);
400e5c31af7Sopenharmony_ci
401e5c31af7Sopenharmony_ci	return retVal;
402e5c31af7Sopenharmony_ci}
403e5c31af7Sopenharmony_ci
404e5c31af7Sopenharmony_ci// negate
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_citemplate <typename T, int Rows, int Cols>
407e5c31af7Sopenharmony_citcu::Matrix<T, Rows, Cols> negate (const tcu::Matrix<T, Rows, Cols>& mat)
408e5c31af7Sopenharmony_ci{
409e5c31af7Sopenharmony_ci	tcu::Matrix<T, Rows, Cols> retVal;
410e5c31af7Sopenharmony_ci
411e5c31af7Sopenharmony_ci	for (int r = 0; r < Rows; ++r)
412e5c31af7Sopenharmony_ci		for (int c = 0; c < Cols; ++c)
413e5c31af7Sopenharmony_ci			retVal(r,c) = -mat(r, c);
414e5c31af7Sopenharmony_ci
415e5c31af7Sopenharmony_ci	return retVal;
416e5c31af7Sopenharmony_ci}
417e5c31af7Sopenharmony_ci
418e5c31af7Sopenharmony_ci// increment/decrement
419e5c31af7Sopenharmony_ci
420e5c31af7Sopenharmony_citemplate <typename T, int Rows, int Cols>
421e5c31af7Sopenharmony_citcu::Matrix<T, Rows, Cols> increment (const tcu::Matrix<T, Rows, Cols>& mat)
422e5c31af7Sopenharmony_ci{
423e5c31af7Sopenharmony_ci	tcu::Matrix<T, Rows, Cols> retVal;
424e5c31af7Sopenharmony_ci
425e5c31af7Sopenharmony_ci	for (int r = 0; r < Rows; ++r)
426e5c31af7Sopenharmony_ci		for (int c = 0; c < Cols; ++c)
427e5c31af7Sopenharmony_ci			retVal(r,c) = mat(r, c) + 1.0f;
428e5c31af7Sopenharmony_ci
429e5c31af7Sopenharmony_ci	return retVal;
430e5c31af7Sopenharmony_ci}
431e5c31af7Sopenharmony_ci
432e5c31af7Sopenharmony_citemplate <typename T, int Rows, int Cols>
433e5c31af7Sopenharmony_citcu::Matrix<T, Rows, Cols> decrement (const tcu::Matrix<T, Rows, Cols>& mat)
434e5c31af7Sopenharmony_ci{
435e5c31af7Sopenharmony_ci	tcu::Matrix<T, Rows, Cols> retVal;
436e5c31af7Sopenharmony_ci
437e5c31af7Sopenharmony_ci	for (int r = 0; r < Rows; ++r)
438e5c31af7Sopenharmony_ci		for (int c = 0; c < Cols; ++c)
439e5c31af7Sopenharmony_ci			retVal(r,c) = mat(r, c) - 1.0f;
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci	return retVal;
442e5c31af7Sopenharmony_ci}
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci// Evaluator template.
445e5c31af7Sopenharmony_ci
446e5c31af7Sopenharmony_citemplate <int Op, int In0Type, int In0DataType, int In1Type, int In1DataType>
447e5c31af7Sopenharmony_cistruct Evaluator;
448e5c31af7Sopenharmony_ci
449e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
450e5c31af7Sopenharmony_cistruct Evaluator<OP_ADD, In0Type, In0DataType, In1Type, In1DataType>
451e5c31af7Sopenharmony_ci{
452e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
453e5c31af7Sopenharmony_ci	{
454e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) + getInputValue<In1Type, In1DataType>(evalCtx, 1));
455e5c31af7Sopenharmony_ci	}
456e5c31af7Sopenharmony_ci};
457e5c31af7Sopenharmony_ci
458e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
459e5c31af7Sopenharmony_cistruct Evaluator<OP_SUB, In0Type, In0DataType, In1Type, In1DataType>
460e5c31af7Sopenharmony_ci{
461e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
462e5c31af7Sopenharmony_ci	{
463e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) - getInputValue<In1Type, In1DataType>(evalCtx, 1));
464e5c31af7Sopenharmony_ci	}
465e5c31af7Sopenharmony_ci};
466e5c31af7Sopenharmony_ci
467e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
468e5c31af7Sopenharmony_cistruct Evaluator<OP_MUL, In0Type, In0DataType, In1Type, In1DataType>
469e5c31af7Sopenharmony_ci{
470e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
471e5c31af7Sopenharmony_ci	{
472e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) * getInputValue<In1Type, In1DataType>(evalCtx, 1));
473e5c31af7Sopenharmony_ci	}
474e5c31af7Sopenharmony_ci};
475e5c31af7Sopenharmony_ci
476e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
477e5c31af7Sopenharmony_cistruct Evaluator<OP_DIV, In0Type, In0DataType, In1Type, In1DataType>
478e5c31af7Sopenharmony_ci{
479e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
480e5c31af7Sopenharmony_ci	{
481e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) / getInputValue<In1Type, In1DataType>(evalCtx, 1));
482e5c31af7Sopenharmony_ci	}
483e5c31af7Sopenharmony_ci};
484e5c31af7Sopenharmony_ci
485e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
486e5c31af7Sopenharmony_cistruct Evaluator<OP_COMP_MUL, In0Type, In0DataType, In1Type, In1DataType>
487e5c31af7Sopenharmony_ci{
488e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
489e5c31af7Sopenharmony_ci	{
490e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(matrixCompMult(getInputValue<In0Type, In0DataType>(evalCtx, 0), getInputValue<In1Type, In1DataType>(evalCtx, 1)));
491e5c31af7Sopenharmony_ci	}
492e5c31af7Sopenharmony_ci};
493e5c31af7Sopenharmony_ci
494e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
495e5c31af7Sopenharmony_cistruct Evaluator<OP_UNARY_PLUS, In0Type, In0DataType, In1Type, In1DataType>
496e5c31af7Sopenharmony_ci{
497e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
498e5c31af7Sopenharmony_ci	{
499e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0));
500e5c31af7Sopenharmony_ci	}
501e5c31af7Sopenharmony_ci};
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
504e5c31af7Sopenharmony_cistruct Evaluator<OP_NEGATION, In0Type, In0DataType, In1Type, In1DataType>
505e5c31af7Sopenharmony_ci{
506e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
507e5c31af7Sopenharmony_ci	{
508e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(negate(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
509e5c31af7Sopenharmony_ci	}
510e5c31af7Sopenharmony_ci};
511e5c31af7Sopenharmony_ci
512e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
513e5c31af7Sopenharmony_cistruct Evaluator<OP_PRE_INCREMENT, In0Type, In0DataType, In1Type, In1DataType>
514e5c31af7Sopenharmony_ci{
515e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
516e5c31af7Sopenharmony_ci	{
517e5c31af7Sopenharmony_ci		// modifying reduction: sum modified value too
518e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(increment(getInputValue<In0Type, In0DataType>(evalCtx, 0))) + reduceToVec3(increment(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
519e5c31af7Sopenharmony_ci	}
520e5c31af7Sopenharmony_ci};
521e5c31af7Sopenharmony_ci
522e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
523e5c31af7Sopenharmony_cistruct Evaluator<OP_PRE_DECREMENT, In0Type, In0DataType, In1Type, In1DataType>
524e5c31af7Sopenharmony_ci{
525e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
526e5c31af7Sopenharmony_ci	{
527e5c31af7Sopenharmony_ci		// modifying reduction: sum modified value too
528e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(decrement(getInputValue<In0Type, In0DataType>(evalCtx, 0))) + reduceToVec3(decrement(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
529e5c31af7Sopenharmony_ci	}
530e5c31af7Sopenharmony_ci};
531e5c31af7Sopenharmony_ci
532e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
533e5c31af7Sopenharmony_cistruct Evaluator<OP_POST_INCREMENT, In0Type, In0DataType, In1Type, In1DataType>
534e5c31af7Sopenharmony_ci{
535e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
536e5c31af7Sopenharmony_ci	{
537e5c31af7Sopenharmony_ci		// modifying reduction: sum modified value too
538e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0)) + reduceToVec3(increment(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
539e5c31af7Sopenharmony_ci	}
540e5c31af7Sopenharmony_ci};
541e5c31af7Sopenharmony_ci
542e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
543e5c31af7Sopenharmony_cistruct Evaluator<OP_POST_DECREMENT, In0Type, In0DataType, In1Type, In1DataType>
544e5c31af7Sopenharmony_ci{
545e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
546e5c31af7Sopenharmony_ci	{
547e5c31af7Sopenharmony_ci		// modifying reduction: sum modified value too
548e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0)) + reduceToVec3(decrement(getInputValue<In0Type, In0DataType>(evalCtx, 0)));
549e5c31af7Sopenharmony_ci	}
550e5c31af7Sopenharmony_ci};
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
553e5c31af7Sopenharmony_cistruct Evaluator<OP_ADD_INTO, In0Type, In0DataType, In1Type, In1DataType>
554e5c31af7Sopenharmony_ci{
555e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
556e5c31af7Sopenharmony_ci	{
557e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) + getInputValue<In1Type, In1DataType>(evalCtx, 1));
558e5c31af7Sopenharmony_ci	}
559e5c31af7Sopenharmony_ci};
560e5c31af7Sopenharmony_ci
561e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
562e5c31af7Sopenharmony_cistruct Evaluator<OP_SUBTRACT_FROM, In0Type, In0DataType, In1Type, In1DataType>
563e5c31af7Sopenharmony_ci{
564e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
565e5c31af7Sopenharmony_ci	{
566e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) - getInputValue<In1Type, In1DataType>(evalCtx, 1));
567e5c31af7Sopenharmony_ci	}
568e5c31af7Sopenharmony_ci};
569e5c31af7Sopenharmony_ci
570e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
571e5c31af7Sopenharmony_cistruct Evaluator<OP_MULTIPLY_INTO, In0Type, In0DataType, In1Type, In1DataType>
572e5c31af7Sopenharmony_ci{
573e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
574e5c31af7Sopenharmony_ci	{
575e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) * getInputValue<In1Type, In1DataType>(evalCtx, 1));
576e5c31af7Sopenharmony_ci	}
577e5c31af7Sopenharmony_ci};
578e5c31af7Sopenharmony_ci
579e5c31af7Sopenharmony_citemplate <int In0Type, int In0DataType, int In1Type, int In1DataType>
580e5c31af7Sopenharmony_cistruct Evaluator<OP_DIVIDE_INTO, In0Type, In0DataType, In1Type, In1DataType>
581e5c31af7Sopenharmony_ci{
582e5c31af7Sopenharmony_ci	static void evaluate (ShaderEvalContext& evalCtx)
583e5c31af7Sopenharmony_ci	{
584e5c31af7Sopenharmony_ci		evalCtx.color.xyz() = reduceToVec3(getInputValue<In0Type, In0DataType>(evalCtx, 0) / getInputValue<In1Type, In1DataType>(evalCtx, 1));
585e5c31af7Sopenharmony_ci	}
586e5c31af7Sopenharmony_ci};
587e5c31af7Sopenharmony_ci
588e5c31af7Sopenharmony_ciShaderEvalFunc getEvalFunc (const ShaderInput& in0, const ShaderInput& in1, MatrixOp op)
589e5c31af7Sopenharmony_ci{
590e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TYPE_LAST		<= (1<<7));
591e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(OP_LAST		<= (1<<4));
592e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(INPUTTYPE_LAST	<= (1<<2));
593e5c31af7Sopenharmony_ci
594e5c31af7Sopenharmony_ci#define PACK_EVAL_CASE(OP, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)	(((OP) << 18) | ((IN0TYPE) << 16) | ((IN0DATATYPE) << 9) | ((IN1TYPE) << 7) | (IN1DATATYPE))
595e5c31af7Sopenharmony_ci
596e5c31af7Sopenharmony_ci#define MAKE_EVAL_CASE(OP, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)		\
597e5c31af7Sopenharmony_ci	case PACK_EVAL_CASE(OP, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE):	\
598e5c31af7Sopenharmony_ci		return Evaluator<OP, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE>::evaluate
599e5c31af7Sopenharmony_ci
600e5c31af7Sopenharmony_ci#define SCALAR_OPS(IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)	\
601e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_ADD,		IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
602e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_SUB,		IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
603e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_MUL,		IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
604e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_DIV,		IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)
605e5c31af7Sopenharmony_ci
606e5c31af7Sopenharmony_ci#define ALL_OPS(IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)	\
607e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_ADD,			IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
608e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_SUB,			IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
609e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_MUL,			IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
610e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_DIV,			IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
611e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_COMP_MUL,		IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)
612e5c31af7Sopenharmony_ci
613e5c31af7Sopenharmony_ci#define MUL_OP(IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)	\
614e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_MUL, IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)
615e5c31af7Sopenharmony_ci
616e5c31af7Sopenharmony_ci#define MAKE_MAT_SCALAR_VEC_CASES(OP, TYPE0, TYPE1)				\
617e5c31af7Sopenharmony_ci	OP(INPUTTYPE_CONST,		TYPE0, INPUTTYPE_CONST,		TYPE1);	\
618e5c31af7Sopenharmony_ci	OP(INPUTTYPE_DYNAMIC,	TYPE0, INPUTTYPE_CONST,		TYPE1);	\
619e5c31af7Sopenharmony_ci	OP(INPUTTYPE_CONST,		TYPE0, INPUTTYPE_DYNAMIC,	TYPE1);	\
620e5c31af7Sopenharmony_ci	OP(INPUTTYPE_DYNAMIC,	TYPE0, INPUTTYPE_DYNAMIC,	TYPE1)
621e5c31af7Sopenharmony_ci
622e5c31af7Sopenharmony_ci#define MAKE_MAT_MAT_CASES(OP, MATTYPE)								\
623e5c31af7Sopenharmony_ci	OP(INPUTTYPE_CONST,		MATTYPE, INPUTTYPE_CONST,	MATTYPE);	\
624e5c31af7Sopenharmony_ci	OP(INPUTTYPE_DYNAMIC,	MATTYPE, INPUTTYPE_CONST,	MATTYPE)
625e5c31af7Sopenharmony_ci
626e5c31af7Sopenharmony_ci#define UNARY_OP(IN0TYPE, IN0DATATYPE)														\
627e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_UNARY_PLUS,		IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST);	\
628e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_NEGATION,			IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST);	\
629e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_PRE_INCREMENT,	IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST);	\
630e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_PRE_DECREMENT,	IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST);	\
631e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_POST_INCREMENT,	IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST);	\
632e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_POST_DECREMENT,	IN0TYPE, IN0DATATYPE, INPUTTYPE_CONST, TYPE_LAST)
633e5c31af7Sopenharmony_ci
634e5c31af7Sopenharmony_ci#define MAKE_UNARY_CASES(OP, MATTYPE)	\
635e5c31af7Sopenharmony_ci	OP(INPUTTYPE_CONST,		MATTYPE);	\
636e5c31af7Sopenharmony_ci	OP(INPUTTYPE_DYNAMIC,	MATTYPE)
637e5c31af7Sopenharmony_ci
638e5c31af7Sopenharmony_ci#define ASSIGN_OP(IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)							\
639e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_ADD_INTO,			IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
640e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_SUBTRACT_FROM,	IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
641e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_MULTIPLY_INTO,	IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE);	\
642e5c31af7Sopenharmony_ci	MAKE_EVAL_CASE(OP_DIVIDE_INTO,		IN0TYPE, IN0DATATYPE, IN1TYPE, IN1DATATYPE)
643e5c31af7Sopenharmony_ci
644e5c31af7Sopenharmony_ci#define MAKE_ASSIGNMENT_CASES(OP, MATTYPE)						\
645e5c31af7Sopenharmony_ci	OP(INPUTTYPE_CONST,		MATTYPE, INPUTTYPE_CONST,	MATTYPE);	\
646e5c31af7Sopenharmony_ci	OP(INPUTTYPE_DYNAMIC,	MATTYPE, INPUTTYPE_CONST,	MATTYPE);	\
647e5c31af7Sopenharmony_ci	OP(INPUTTYPE_CONST,		MATTYPE, INPUTTYPE_DYNAMIC,	MATTYPE);	\
648e5c31af7Sopenharmony_ci	OP(INPUTTYPE_DYNAMIC,	MATTYPE, INPUTTYPE_DYNAMIC,	MATTYPE)
649e5c31af7Sopenharmony_ci
650e5c31af7Sopenharmony_ci	// \note At the moment there is no difference between uniform and const inputs. This saves binary size.
651e5c31af7Sopenharmony_ci	InputType in0Type = in0.inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_DYNAMIC : INPUTTYPE_CONST;
652e5c31af7Sopenharmony_ci	InputType in1Type = in1.inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_DYNAMIC : INPUTTYPE_CONST;
653e5c31af7Sopenharmony_ci
654e5c31af7Sopenharmony_ci	switch (PACK_EVAL_CASE(op, in0Type, in0.dataType, in1Type, in1.dataType))
655e5c31af7Sopenharmony_ci	{
656e5c31af7Sopenharmony_ci		// Matrix-scalar.
657e5c31af7Sopenharmony_ci		MAKE_MAT_SCALAR_VEC_CASES(SCALAR_OPS,	TYPE_FLOAT_MAT2, TYPE_FLOAT);
658e5c31af7Sopenharmony_ci		MAKE_MAT_SCALAR_VEC_CASES(SCALAR_OPS,	TYPE_FLOAT_MAT3, TYPE_FLOAT);
659e5c31af7Sopenharmony_ci		MAKE_MAT_SCALAR_VEC_CASES(SCALAR_OPS,	TYPE_FLOAT_MAT4, TYPE_FLOAT);
660e5c31af7Sopenharmony_ci
661e5c31af7Sopenharmony_ci		// Matrix-vector.
662e5c31af7Sopenharmony_ci		MAKE_MAT_SCALAR_VEC_CASES(MUL_OP,		TYPE_FLOAT_MAT2, TYPE_FLOAT_VEC2);
663e5c31af7Sopenharmony_ci		MAKE_MAT_SCALAR_VEC_CASES(MUL_OP,		TYPE_FLOAT_MAT3, TYPE_FLOAT_VEC3);
664e5c31af7Sopenharmony_ci		MAKE_MAT_SCALAR_VEC_CASES(MUL_OP,		TYPE_FLOAT_MAT4, TYPE_FLOAT_VEC4);
665e5c31af7Sopenharmony_ci
666e5c31af7Sopenharmony_ci		// Vector-matrix.
667e5c31af7Sopenharmony_ci		MAKE_MAT_SCALAR_VEC_CASES(MUL_OP,		TYPE_FLOAT_VEC2, TYPE_FLOAT_MAT2);
668e5c31af7Sopenharmony_ci		MAKE_MAT_SCALAR_VEC_CASES(MUL_OP,		TYPE_FLOAT_VEC3, TYPE_FLOAT_MAT3);
669e5c31af7Sopenharmony_ci		MAKE_MAT_SCALAR_VEC_CASES(MUL_OP,		TYPE_FLOAT_VEC4, TYPE_FLOAT_MAT4);
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_ci		// Matrix-matrix.
672e5c31af7Sopenharmony_ci		MAKE_MAT_MAT_CASES(ALL_OPS,	TYPE_FLOAT_MAT2);
673e5c31af7Sopenharmony_ci		MAKE_MAT_MAT_CASES(ALL_OPS,	TYPE_FLOAT_MAT3);
674e5c31af7Sopenharmony_ci		MAKE_MAT_MAT_CASES(ALL_OPS,	TYPE_FLOAT_MAT4);
675e5c31af7Sopenharmony_ci
676e5c31af7Sopenharmony_ci		// Unary matrix
677e5c31af7Sopenharmony_ci		MAKE_UNARY_CASES(UNARY_OP, TYPE_FLOAT_MAT2);
678e5c31af7Sopenharmony_ci		MAKE_UNARY_CASES(UNARY_OP, TYPE_FLOAT_MAT3);
679e5c31af7Sopenharmony_ci		MAKE_UNARY_CASES(UNARY_OP, TYPE_FLOAT_MAT4);
680e5c31af7Sopenharmony_ci
681e5c31af7Sopenharmony_ci		// Assignment matrix
682e5c31af7Sopenharmony_ci		MAKE_ASSIGNMENT_CASES(ASSIGN_OP, TYPE_FLOAT_MAT2);
683e5c31af7Sopenharmony_ci		MAKE_ASSIGNMENT_CASES(ASSIGN_OP, TYPE_FLOAT_MAT3);
684e5c31af7Sopenharmony_ci		MAKE_ASSIGNMENT_CASES(ASSIGN_OP, TYPE_FLOAT_MAT4);
685e5c31af7Sopenharmony_ci
686e5c31af7Sopenharmony_ci		default:
687e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
688e5c31af7Sopenharmony_ci			return DE_NULL;
689e5c31af7Sopenharmony_ci	}
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ci#undef PACK_EVAL_CASE
692e5c31af7Sopenharmony_ci#undef MAKE_EVAL_CASE
693e5c31af7Sopenharmony_ci#undef MUL_OP
694e5c31af7Sopenharmony_ci#undef ALL_OPS
695e5c31af7Sopenharmony_ci#undef MAKE_MAT_SCALAR_VEC_CASES
696e5c31af7Sopenharmony_ci#undef MAKE_MAT_MAT_CASES
697e5c31af7Sopenharmony_ci}
698e5c31af7Sopenharmony_ci
699e5c31af7Sopenharmony_ci// Shader source format utilities.
700e5c31af7Sopenharmony_ci
701e5c31af7Sopenharmony_citemplate <int Size>
702e5c31af7Sopenharmony_civoid writeVectorConstructor (std::ostream& str, const tcu::Vector<float, Size>& v)
703e5c31af7Sopenharmony_ci{
704e5c31af7Sopenharmony_ci	str << "vec" << Size << "(";
705e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < Size; ndx++)
706e5c31af7Sopenharmony_ci	{
707e5c31af7Sopenharmony_ci		if (ndx != 0)
708e5c31af7Sopenharmony_ci			str << ", ";
709e5c31af7Sopenharmony_ci		str << de::floatToString(v[ndx], 1);
710e5c31af7Sopenharmony_ci	}
711e5c31af7Sopenharmony_ci	str << ")";
712e5c31af7Sopenharmony_ci}
713e5c31af7Sopenharmony_ci
714e5c31af7Sopenharmony_citemplate <int Cols, int Rows>
715e5c31af7Sopenharmony_civoid writeMatrixConstructor (std::ostream& str, const tcu::Matrix<float, Rows, Cols>& m)
716e5c31af7Sopenharmony_ci{
717e5c31af7Sopenharmony_ci	if (Rows == Cols)
718e5c31af7Sopenharmony_ci		str << "mat" << Cols;
719e5c31af7Sopenharmony_ci	else
720e5c31af7Sopenharmony_ci		str << "mat" << Cols << "x" << Rows;
721e5c31af7Sopenharmony_ci
722e5c31af7Sopenharmony_ci	str << "(";
723e5c31af7Sopenharmony_ci	for (int colNdx = 0; colNdx < Cols; colNdx++)
724e5c31af7Sopenharmony_ci	{
725e5c31af7Sopenharmony_ci		for (int rowNdx = 0; rowNdx < Rows; rowNdx++)
726e5c31af7Sopenharmony_ci		{
727e5c31af7Sopenharmony_ci			if (rowNdx > 0 || colNdx > 0)
728e5c31af7Sopenharmony_ci				str << ", ";
729e5c31af7Sopenharmony_ci			str << de::floatToString(m(rowNdx, colNdx), 1);
730e5c31af7Sopenharmony_ci		}
731e5c31af7Sopenharmony_ci	}
732e5c31af7Sopenharmony_ci	str << ")";
733e5c31af7Sopenharmony_ci}
734e5c31af7Sopenharmony_ci
735e5c31af7Sopenharmony_ci} // MatrixCaseUtils
736e5c31af7Sopenharmony_ci
737e5c31af7Sopenharmony_ciusing namespace MatrixCaseUtils;
738e5c31af7Sopenharmony_ci
739e5c31af7Sopenharmony_ciclass ShaderMatrixCase : public ShaderRenderCase
740e5c31af7Sopenharmony_ci{
741e5c31af7Sopenharmony_cipublic:
742e5c31af7Sopenharmony_ci					ShaderMatrixCase			(Context& context, const char* name, const char* desc, const ShaderInput& in0, const ShaderInput& in1, MatrixOp op, bool isVertexCase);
743e5c31af7Sopenharmony_ci					~ShaderMatrixCase			(void);
744e5c31af7Sopenharmony_ci
745e5c31af7Sopenharmony_ci	void			init						(void);
746e5c31af7Sopenharmony_ci
747e5c31af7Sopenharmony_ciprotected:
748e5c31af7Sopenharmony_ci	std::string		genGLSLMatToVec3Reduction	(const glu::DataType& matType, const char* varName);
749e5c31af7Sopenharmony_ci	void			setupUniforms				(int programID, const tcu::Vec4& constCoords);
750e5c31af7Sopenharmony_ci
751e5c31af7Sopenharmony_ciprivate:
752e5c31af7Sopenharmony_ci	ShaderInput		m_in0;
753e5c31af7Sopenharmony_ci	ShaderInput		m_in1;
754e5c31af7Sopenharmony_ci	MatrixOp		m_op;
755e5c31af7Sopenharmony_ci};
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_ciShaderMatrixCase::ShaderMatrixCase (Context& context, const char* name, const char* desc, const ShaderInput& in0, const ShaderInput& in1, MatrixOp op, bool isVertexCase)
758e5c31af7Sopenharmony_ci	: ShaderRenderCase	(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, getEvalFunc(in0, in1, op))
759e5c31af7Sopenharmony_ci	, m_in0				(in0)
760e5c31af7Sopenharmony_ci	, m_in1				(in1)
761e5c31af7Sopenharmony_ci	, m_op				(op)
762e5c31af7Sopenharmony_ci{
763e5c31af7Sopenharmony_ci}
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ciShaderMatrixCase::~ShaderMatrixCase (void)
766e5c31af7Sopenharmony_ci{
767e5c31af7Sopenharmony_ci}
768e5c31af7Sopenharmony_ci
769e5c31af7Sopenharmony_civoid ShaderMatrixCase::init (void)
770e5c31af7Sopenharmony_ci{
771e5c31af7Sopenharmony_ci	std::ostringstream	vtx;
772e5c31af7Sopenharmony_ci	std::ostringstream	frag;
773e5c31af7Sopenharmony_ci	std::ostringstream&	op				= m_isVertexCase ? vtx : frag;
774e5c31af7Sopenharmony_ci
775e5c31af7Sopenharmony_ci	bool				isInDynMat0		= isDataTypeMatrix(m_in0.dataType) && m_in0.inputType == INPUTTYPE_DYNAMIC;
776e5c31af7Sopenharmony_ci	bool				isInDynMat1		= isDataTypeMatrix(m_in1.dataType) && m_in1.inputType == INPUTTYPE_DYNAMIC;
777e5c31af7Sopenharmony_ci	string				inValue0;
778e5c31af7Sopenharmony_ci	string				inValue1;
779e5c31af7Sopenharmony_ci	DataType			resultType		= TYPE_LAST;
780e5c31af7Sopenharmony_ci	Precision			resultPrec		= m_in0.precision;
781e5c31af7Sopenharmony_ci	vector<string>		passVars;
782e5c31af7Sopenharmony_ci	int					numInputs		= (isOperationBinary(m_op)) ? (2) : (1);
783e5c31af7Sopenharmony_ci
784e5c31af7Sopenharmony_ci	std::string			operationValue0;
785e5c31af7Sopenharmony_ci	std::string			operationValue1;
786e5c31af7Sopenharmony_ci
787e5c31af7Sopenharmony_ci	DE_ASSERT(!isInDynMat0 || !isInDynMat1); // Only single dynamic matrix input is allowed.
788e5c31af7Sopenharmony_ci	DE_UNREF(isInDynMat0 && isInDynMat1);
789e5c31af7Sopenharmony_ci
790e5c31af7Sopenharmony_ci	// Compute result type.
791e5c31af7Sopenharmony_ci	if (isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
792e5c31af7Sopenharmony_ci	{
793e5c31af7Sopenharmony_ci		DE_ASSERT(m_in0.dataType == m_in1.dataType);
794e5c31af7Sopenharmony_ci		resultType = m_in0.dataType;
795e5c31af7Sopenharmony_ci	}
796e5c31af7Sopenharmony_ci	else if (getOperationType(m_op) == OPERATIONTYPE_UNARY_PREFIX_OPERATOR ||
797e5c31af7Sopenharmony_ci			 getOperationType(m_op) == OPERATIONTYPE_UNARY_POSTFIX_OPERATOR)
798e5c31af7Sopenharmony_ci	{
799e5c31af7Sopenharmony_ci		resultType = m_in0.dataType;
800e5c31af7Sopenharmony_ci	}
801e5c31af7Sopenharmony_ci	else
802e5c31af7Sopenharmony_ci	{
803e5c31af7Sopenharmony_ci		int			matNdx		= isDataTypeMatrix(m_in0.dataType) ? 0 : 1;
804e5c31af7Sopenharmony_ci		DataType	matrixType	= matNdx == 0 ? m_in0.dataType : m_in1.dataType;
805e5c31af7Sopenharmony_ci		DataType	otherType	= matNdx == 0 ? m_in1.dataType : m_in0.dataType;
806e5c31af7Sopenharmony_ci
807e5c31af7Sopenharmony_ci		if (otherType == TYPE_FLOAT)
808e5c31af7Sopenharmony_ci			resultType = matrixType;
809e5c31af7Sopenharmony_ci		else
810e5c31af7Sopenharmony_ci		{
811e5c31af7Sopenharmony_ci			DE_ASSERT(isDataTypeVector(otherType));
812e5c31af7Sopenharmony_ci			resultType = otherType;
813e5c31af7Sopenharmony_ci		}
814e5c31af7Sopenharmony_ci	}
815e5c31af7Sopenharmony_ci
816e5c31af7Sopenharmony_ci	vtx << "attribute highp vec4 a_position;\n";
817e5c31af7Sopenharmony_ci	if (m_isVertexCase)
818e5c31af7Sopenharmony_ci	{
819e5c31af7Sopenharmony_ci		vtx << "varying mediump vec4 v_color;\n";
820e5c31af7Sopenharmony_ci		frag << "varying mediump vec4 v_color;\n";
821e5c31af7Sopenharmony_ci	}
822e5c31af7Sopenharmony_ci
823e5c31af7Sopenharmony_ci	// Input declarations.
824e5c31af7Sopenharmony_ci	for (int inNdx = 0; inNdx < numInputs; inNdx++)
825e5c31af7Sopenharmony_ci	{
826e5c31af7Sopenharmony_ci		const ShaderInput&	in			= inNdx > 0 ? m_in1 : m_in0;
827e5c31af7Sopenharmony_ci		const char*			precName	= getPrecisionName(in.precision);
828e5c31af7Sopenharmony_ci		const char*			typeName	= getDataTypeName(in.dataType);
829e5c31af7Sopenharmony_ci		string&				inValue		= inNdx > 0 ? inValue1 : inValue0;
830e5c31af7Sopenharmony_ci
831e5c31af7Sopenharmony_ci		if (in.inputType == INPUTTYPE_DYNAMIC)
832e5c31af7Sopenharmony_ci		{
833e5c31af7Sopenharmony_ci			vtx << "attribute " << precName << " " << typeName << " a_";
834e5c31af7Sopenharmony_ci
835e5c31af7Sopenharmony_ci			if (isDataTypeMatrix(in.dataType))
836e5c31af7Sopenharmony_ci			{
837e5c31af7Sopenharmony_ci				// a_matN, v_matN
838e5c31af7Sopenharmony_ci				vtx << typeName << ";\n";
839e5c31af7Sopenharmony_ci				if (!m_isVertexCase)
840e5c31af7Sopenharmony_ci				{
841e5c31af7Sopenharmony_ci					vtx << "varying " << precName << " " << typeName << " v_" << typeName << ";\n";
842e5c31af7Sopenharmony_ci					frag << "varying " << precName << " " << typeName << " v_" << typeName << ";\n";
843e5c31af7Sopenharmony_ci					passVars.push_back(typeName);
844e5c31af7Sopenharmony_ci				}
845e5c31af7Sopenharmony_ci
846e5c31af7Sopenharmony_ci				inValue = string(m_isVertexCase ? "a_" : "v_") + getDataTypeName(in.dataType);
847e5c31af7Sopenharmony_ci			}
848e5c31af7Sopenharmony_ci			else
849e5c31af7Sopenharmony_ci			{
850e5c31af7Sopenharmony_ci				// a_coords, v_coords
851e5c31af7Sopenharmony_ci				vtx << "coords;\n";
852e5c31af7Sopenharmony_ci				if (!m_isVertexCase)
853e5c31af7Sopenharmony_ci				{
854e5c31af7Sopenharmony_ci					vtx << "varying " << precName << " " << typeName << " v_coords;\n";
855e5c31af7Sopenharmony_ci					frag << "varying " << precName << " " << typeName << " v_coords;\n";
856e5c31af7Sopenharmony_ci					passVars.push_back("coords");
857e5c31af7Sopenharmony_ci				}
858e5c31af7Sopenharmony_ci
859e5c31af7Sopenharmony_ci				inValue = m_isVertexCase ? "a_coords" : "v_coords";
860e5c31af7Sopenharmony_ci			}
861e5c31af7Sopenharmony_ci		}
862e5c31af7Sopenharmony_ci		else if (in.inputType == INPUTTYPE_UNIFORM)
863e5c31af7Sopenharmony_ci		{
864e5c31af7Sopenharmony_ci			op << "uniform " << precName << " " << typeName << " u_in" << inNdx << ";\n";
865e5c31af7Sopenharmony_ci			inValue = string("u_in") + de::toString(inNdx);
866e5c31af7Sopenharmony_ci		}
867e5c31af7Sopenharmony_ci		else if (in.inputType == INPUTTYPE_CONST)
868e5c31af7Sopenharmony_ci		{
869e5c31af7Sopenharmony_ci			op << "const " << precName << " " << typeName << " in" << inNdx << " = ";
870e5c31af7Sopenharmony_ci
871e5c31af7Sopenharmony_ci			// Generate declaration.
872e5c31af7Sopenharmony_ci			switch (in.dataType)
873e5c31af7Sopenharmony_ci			{
874e5c31af7Sopenharmony_ci				case TYPE_FLOAT:		op << de::floatToString(s_constInFloat[inNdx], 1);					break;
875e5c31af7Sopenharmony_ci				case TYPE_FLOAT_VEC2:	writeVectorConstructor<2>(op, s_constInVec2[inNdx]);				break;
876e5c31af7Sopenharmony_ci				case TYPE_FLOAT_VEC3:	writeVectorConstructor<3>(op, s_constInVec3[inNdx]);				break;
877e5c31af7Sopenharmony_ci				case TYPE_FLOAT_VEC4:	writeVectorConstructor<4>(op, s_constInVec4[inNdx]);				break;
878e5c31af7Sopenharmony_ci				case TYPE_FLOAT_MAT2:	writeMatrixConstructor<2, 2>(op, Mat2(s_constInMat2[inNdx]));		break;
879e5c31af7Sopenharmony_ci				case TYPE_FLOAT_MAT3:	writeMatrixConstructor<3, 3>(op, Mat3(s_constInMat3[inNdx]));		break;
880e5c31af7Sopenharmony_ci				case TYPE_FLOAT_MAT4:	writeMatrixConstructor<4, 4>(op, Mat4(s_constInMat4[inNdx]));		break;
881e5c31af7Sopenharmony_ci
882e5c31af7Sopenharmony_ci				default:
883e5c31af7Sopenharmony_ci					DE_ASSERT(DE_FALSE);
884e5c31af7Sopenharmony_ci			}
885e5c31af7Sopenharmony_ci
886e5c31af7Sopenharmony_ci			op << ";\n";
887e5c31af7Sopenharmony_ci
888e5c31af7Sopenharmony_ci			inValue = string("in") + de::toString(inNdx);
889e5c31af7Sopenharmony_ci		}
890e5c31af7Sopenharmony_ci	}
891e5c31af7Sopenharmony_ci
892e5c31af7Sopenharmony_ci	vtx << "\n"
893e5c31af7Sopenharmony_ci		<< "void main (void)\n"
894e5c31af7Sopenharmony_ci		<< "{\n"
895e5c31af7Sopenharmony_ci		<< "	gl_Position = a_position;\n";
896e5c31af7Sopenharmony_ci	frag << "\n"
897e5c31af7Sopenharmony_ci		 << "void main (void)\n"
898e5c31af7Sopenharmony_ci		 << "{\n";
899e5c31af7Sopenharmony_ci
900e5c31af7Sopenharmony_ci	if (m_isVertexCase)
901e5c31af7Sopenharmony_ci	{
902e5c31af7Sopenharmony_ci		frag << "	gl_FragColor = v_color;\n";
903e5c31af7Sopenharmony_ci	}
904e5c31af7Sopenharmony_ci	else
905e5c31af7Sopenharmony_ci	{
906e5c31af7Sopenharmony_ci		for (vector<string>::const_iterator copyIter = passVars.begin(); copyIter != passVars.end(); copyIter++)
907e5c31af7Sopenharmony_ci			vtx << "	v_" << *copyIter << " = " << "a_" << *copyIter << ";\n";
908e5c31af7Sopenharmony_ci	}
909e5c31af7Sopenharmony_ci
910e5c31af7Sopenharmony_ci	// Operation.
911e5c31af7Sopenharmony_ci
912e5c31af7Sopenharmony_ci	switch (getOperationNature(m_op))
913e5c31af7Sopenharmony_ci	{
914e5c31af7Sopenharmony_ci		case OPERATIONNATURE_PURE:
915e5c31af7Sopenharmony_ci			DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
916e5c31af7Sopenharmony_ci
917e5c31af7Sopenharmony_ci			operationValue0 = inValue0;
918e5c31af7Sopenharmony_ci			operationValue1 = inValue1;
919e5c31af7Sopenharmony_ci			break;
920e5c31af7Sopenharmony_ci
921e5c31af7Sopenharmony_ci		case OPERATIONNATURE_MUTATING:
922e5c31af7Sopenharmony_ci			DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
923e5c31af7Sopenharmony_ci
924e5c31af7Sopenharmony_ci			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " tmpValue = " << inValue0 << ";\n";
925e5c31af7Sopenharmony_ci
926e5c31af7Sopenharmony_ci			operationValue0 = "tmpValue";
927e5c31af7Sopenharmony_ci			operationValue1 = inValue1;
928e5c31af7Sopenharmony_ci			break;
929e5c31af7Sopenharmony_ci
930e5c31af7Sopenharmony_ci		case OPERATIONNATURE_ASSIGNMENT:
931e5c31af7Sopenharmony_ci			DE_ASSERT(getOperationType(m_op) == OPERATIONTYPE_ASSIGNMENT);
932e5c31af7Sopenharmony_ci
933e5c31af7Sopenharmony_ci			operationValue0 = inValue0;
934e5c31af7Sopenharmony_ci			operationValue1 = inValue1;
935e5c31af7Sopenharmony_ci			break;
936e5c31af7Sopenharmony_ci
937e5c31af7Sopenharmony_ci		default:
938e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
939e5c31af7Sopenharmony_ci	}
940e5c31af7Sopenharmony_ci
941e5c31af7Sopenharmony_ci	switch (getOperationType(m_op))
942e5c31af7Sopenharmony_ci	{
943e5c31af7Sopenharmony_ci		case OPERATIONTYPE_BINARY_OPERATOR:
944e5c31af7Sopenharmony_ci			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << " " << getOperationName(m_op) << " " << operationValue1 << ";\n";
945e5c31af7Sopenharmony_ci			break;
946e5c31af7Sopenharmony_ci
947e5c31af7Sopenharmony_ci		case OPERATIONTYPE_UNARY_PREFIX_OPERATOR:
948e5c31af7Sopenharmony_ci			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << operationValue0 << ";\n";
949e5c31af7Sopenharmony_ci			break;
950e5c31af7Sopenharmony_ci
951e5c31af7Sopenharmony_ci		case OPERATIONTYPE_UNARY_POSTFIX_OPERATOR:
952e5c31af7Sopenharmony_ci			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << getOperationName(m_op) << ";\n";
953e5c31af7Sopenharmony_ci			break;
954e5c31af7Sopenharmony_ci
955e5c31af7Sopenharmony_ci		case OPERATIONTYPE_BINARY_FUNCTION:
956e5c31af7Sopenharmony_ci			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ", " << operationValue1 << ");\n";
957e5c31af7Sopenharmony_ci			break;
958e5c31af7Sopenharmony_ci
959e5c31af7Sopenharmony_ci		case OPERATIONTYPE_ASSIGNMENT:
960e5c31af7Sopenharmony_ci			op << "	" << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << ";\n";
961e5c31af7Sopenharmony_ci			op << "	res " << getOperationName(m_op) << " " << operationValue1 << ";\n";
962e5c31af7Sopenharmony_ci			break;
963e5c31af7Sopenharmony_ci
964e5c31af7Sopenharmony_ci		default:
965e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
966e5c31af7Sopenharmony_ci	}
967e5c31af7Sopenharmony_ci
968e5c31af7Sopenharmony_ci	// Reduction to vec3 (rgb). Check the used value too if it was modified.
969e5c31af7Sopenharmony_ci	op << "	" << (m_isVertexCase ? "v_color" : "gl_FragColor") << " = ";
970e5c31af7Sopenharmony_ci
971e5c31af7Sopenharmony_ci	if (isOperationValueModifying(m_op))
972e5c31af7Sopenharmony_ci		op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0) + vec4(" << genGLSLMatToVec3Reduction(resultType, "tmpValue") << ", 0.0);\n";
973e5c31af7Sopenharmony_ci	else
974e5c31af7Sopenharmony_ci		op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0);\n";
975e5c31af7Sopenharmony_ci
976e5c31af7Sopenharmony_ci	vtx << "}\n";
977e5c31af7Sopenharmony_ci	frag << "}\n";
978e5c31af7Sopenharmony_ci
979e5c31af7Sopenharmony_ci	m_vertShaderSource	= vtx.str();
980e5c31af7Sopenharmony_ci	m_fragShaderSource	= frag.str();
981e5c31af7Sopenharmony_ci
982e5c31af7Sopenharmony_ci	// \todo [2012-02-14 pyry] Compute better values for matrix tests.
983e5c31af7Sopenharmony_ci	m_userAttribTransforms.resize(4);
984e5c31af7Sopenharmony_ci	for (int attribNdx = 0; attribNdx < 4; attribNdx++)
985e5c31af7Sopenharmony_ci	{
986e5c31af7Sopenharmony_ci		m_userAttribTransforms[attribNdx] = Mat4(0.0f);
987e5c31af7Sopenharmony_ci		m_userAttribTransforms[attribNdx]((0 + attribNdx) % 4, 0) = 1.0f;
988e5c31af7Sopenharmony_ci		m_userAttribTransforms[attribNdx]((1 + attribNdx) % 4, 1) = 1.0f;
989e5c31af7Sopenharmony_ci		m_userAttribTransforms[attribNdx]((2 + attribNdx) % 4, 2) = 1.0f;
990e5c31af7Sopenharmony_ci		m_userAttribTransforms[attribNdx]((3 + attribNdx) % 4, 3) = 1.0f;
991e5c31af7Sopenharmony_ci	}
992e5c31af7Sopenharmony_ci
993e5c31af7Sopenharmony_ci	// prevent bad reference cases such as black result images by fine-tuning used matrices
994e5c31af7Sopenharmony_ci	if (getOperationTestMatrixType(m_op) != TESTMATRIXTYPE_DEFAULT)
995e5c31af7Sopenharmony_ci	{
996e5c31af7Sopenharmony_ci		for (int attribNdx = 0; attribNdx < 4; attribNdx++)
997e5c31af7Sopenharmony_ci		{
998e5c31af7Sopenharmony_ci			for (int row = 0; row < 4; row++)
999e5c31af7Sopenharmony_ci			for (int col = 0; col < 4; col++)
1000e5c31af7Sopenharmony_ci			{
1001e5c31af7Sopenharmony_ci				switch (getOperationTestMatrixType(m_op))
1002e5c31af7Sopenharmony_ci				{
1003e5c31af7Sopenharmony_ci					case TESTMATRIXTYPE_NEGATED:
1004e5c31af7Sopenharmony_ci						m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col);
1005e5c31af7Sopenharmony_ci						break;
1006e5c31af7Sopenharmony_ci					case TESTMATRIXTYPE_INCREMENTED:
1007e5c31af7Sopenharmony_ci						m_userAttribTransforms[attribNdx](row, col) += 0.3f;
1008e5c31af7Sopenharmony_ci						break;
1009e5c31af7Sopenharmony_ci					case TESTMATRIXTYPE_DECREMENTED:
1010e5c31af7Sopenharmony_ci						m_userAttribTransforms[attribNdx](row, col) -= 0.1f;
1011e5c31af7Sopenharmony_ci						break;
1012e5c31af7Sopenharmony_ci
1013e5c31af7Sopenharmony_ci					default:
1014e5c31af7Sopenharmony_ci						DE_ASSERT(DE_FALSE);
1015e5c31af7Sopenharmony_ci						break;
1016e5c31af7Sopenharmony_ci				}
1017e5c31af7Sopenharmony_ci			}
1018e5c31af7Sopenharmony_ci		}
1019e5c31af7Sopenharmony_ci	}
1020e5c31af7Sopenharmony_ci
1021e5c31af7Sopenharmony_ci	ShaderRenderCase::init();
1022e5c31af7Sopenharmony_ci}
1023e5c31af7Sopenharmony_ci
1024e5c31af7Sopenharmony_cistd::string ShaderMatrixCase::genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName)
1025e5c31af7Sopenharmony_ci{
1026e5c31af7Sopenharmony_ci	std::ostringstream op;
1027e5c31af7Sopenharmony_ci
1028e5c31af7Sopenharmony_ci	switch (matType)
1029e5c31af7Sopenharmony_ci	{
1030e5c31af7Sopenharmony_ci		case TYPE_FLOAT:		op << varName << ", "		<< varName << ", "			<< varName << "";										break;
1031e5c31af7Sopenharmony_ci		case TYPE_FLOAT_VEC2:	op << varName << ".x, "		<< varName << ".y, "		<< varName << ".x";										break;
1032e5c31af7Sopenharmony_ci		case TYPE_FLOAT_VEC3:	op << varName << "";																							break;
1033e5c31af7Sopenharmony_ci		case TYPE_FLOAT_VEC4:	op << varName << ".x, "		<< varName << ".y, "		<< varName << ".z+"			<< varName << ".w";			break;
1034e5c31af7Sopenharmony_ci		case TYPE_FLOAT_MAT2:	op << varName << "[0][0], "	<< varName << "[1][0], "	<< varName << "[0][1]+"		<< varName << "[1][1]";		break;
1035e5c31af7Sopenharmony_ci		case TYPE_FLOAT_MAT3:	op << varName << "[0]+"		<< varName << "[1]+"		<< varName << "[2]";									break;
1036e5c31af7Sopenharmony_ci		case TYPE_FLOAT_MAT4:	op << varName << "[0].xyz+"	<< varName << "[1].yzw+"	<< varName << "[2].zwx+"	<< varName << "[3].wxy";	break;
1037e5c31af7Sopenharmony_ci
1038e5c31af7Sopenharmony_ci		default:
1039e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
1040e5c31af7Sopenharmony_ci	}
1041e5c31af7Sopenharmony_ci
1042e5c31af7Sopenharmony_ci	return op.str();
1043e5c31af7Sopenharmony_ci}
1044e5c31af7Sopenharmony_ci
1045e5c31af7Sopenharmony_civoid ShaderMatrixCase::setupUniforms (int programID, const tcu::Vec4& constCoords)
1046e5c31af7Sopenharmony_ci{
1047e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_renderCtx.getFunctions();
1048e5c31af7Sopenharmony_ci
1049e5c31af7Sopenharmony_ci	DE_UNREF(constCoords);
1050e5c31af7Sopenharmony_ci
1051e5c31af7Sopenharmony_ci	for (int inNdx = 0; inNdx < 2; inNdx++)
1052e5c31af7Sopenharmony_ci	{
1053e5c31af7Sopenharmony_ci		const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1054e5c31af7Sopenharmony_ci
1055e5c31af7Sopenharmony_ci		if (in.inputType == INPUTTYPE_UNIFORM)
1056e5c31af7Sopenharmony_ci		{
1057e5c31af7Sopenharmony_ci			int loc = gl.getUniformLocation(programID, (string("u_in") + de::toString(inNdx)).c_str());
1058e5c31af7Sopenharmony_ci
1059e5c31af7Sopenharmony_ci			if (loc < 0)
1060e5c31af7Sopenharmony_ci				continue;
1061e5c31af7Sopenharmony_ci
1062e5c31af7Sopenharmony_ci			switch (in.dataType)
1063e5c31af7Sopenharmony_ci			{
1064e5c31af7Sopenharmony_ci				case TYPE_FLOAT:		gl.uniform1f(loc, s_constInFloat[inNdx]);													break;
1065e5c31af7Sopenharmony_ci				case TYPE_FLOAT_VEC2:	gl.uniform2fv(loc, 1, s_constInVec2[inNdx].getPtr());										break;
1066e5c31af7Sopenharmony_ci				case TYPE_FLOAT_VEC3:	gl.uniform3fv(loc, 1, s_constInVec3[inNdx].getPtr());										break;
1067e5c31af7Sopenharmony_ci				case TYPE_FLOAT_VEC4:	gl.uniform4fv(loc, 1, s_constInVec4[inNdx].getPtr());										break;
1068e5c31af7Sopenharmony_ci				case TYPE_FLOAT_MAT2:	gl.uniformMatrix2fv(loc, 1, GL_FALSE, s_constInMat2[inNdx].getColumnMajorData().getPtr());	break;
1069e5c31af7Sopenharmony_ci				case TYPE_FLOAT_MAT3:	gl.uniformMatrix3fv(loc, 1, GL_FALSE, s_constInMat3[inNdx].getColumnMajorData().getPtr());	break;
1070e5c31af7Sopenharmony_ci				case TYPE_FLOAT_MAT4:	gl.uniformMatrix4fv(loc, 1, GL_FALSE, s_constInMat4[inNdx].getColumnMajorData().getPtr());	break;
1071e5c31af7Sopenharmony_ci				default:
1072e5c31af7Sopenharmony_ci					DE_ASSERT(false);
1073e5c31af7Sopenharmony_ci			}
1074e5c31af7Sopenharmony_ci		}
1075e5c31af7Sopenharmony_ci	}
1076e5c31af7Sopenharmony_ci}
1077e5c31af7Sopenharmony_ci
1078e5c31af7Sopenharmony_ciShaderMatrixTests::ShaderMatrixTests (Context& context)
1079e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "matrix", "Matrix Tests")
1080e5c31af7Sopenharmony_ci{
1081e5c31af7Sopenharmony_ci}
1082e5c31af7Sopenharmony_ci
1083e5c31af7Sopenharmony_ciShaderMatrixTests::~ShaderMatrixTests (void)
1084e5c31af7Sopenharmony_ci{
1085e5c31af7Sopenharmony_ci}
1086e5c31af7Sopenharmony_ci
1087e5c31af7Sopenharmony_civoid ShaderMatrixTests::init (void)
1088e5c31af7Sopenharmony_ci{
1089e5c31af7Sopenharmony_ci	static const struct
1090e5c31af7Sopenharmony_ci	{
1091e5c31af7Sopenharmony_ci		const char*		name;
1092e5c31af7Sopenharmony_ci		const char*		desc;
1093e5c31af7Sopenharmony_ci		MatrixOp		op;
1094e5c31af7Sopenharmony_ci		bool			extendedInputTypeCases; // !< test with const and uniform types too
1095e5c31af7Sopenharmony_ci	} ops[] =
1096e5c31af7Sopenharmony_ci	{
1097e5c31af7Sopenharmony_ci		{ "add",			"Matrix addition tests",						OP_ADD,				true	},
1098e5c31af7Sopenharmony_ci		{ "sub",			"Matrix subtraction tests",						OP_SUB,				true	},
1099e5c31af7Sopenharmony_ci		{ "mul",			"Matrix multiplication tests",					OP_MUL,				true	},
1100e5c31af7Sopenharmony_ci		{ "div",			"Matrix division tests",						OP_DIV,				true	},
1101e5c31af7Sopenharmony_ci		{ "matrixcompmult",	"Matrix component-wise multiplication tests",	OP_COMP_MUL,		false	},
1102e5c31af7Sopenharmony_ci		{ "unary_addition",	"Matrix unary addition tests",					OP_UNARY_PLUS,		false	},
1103e5c31af7Sopenharmony_ci		{ "negation",		"Matrix negation tests",						OP_NEGATION,		false	},
1104e5c31af7Sopenharmony_ci		{ "pre_increment",	"Matrix prefix increment tests",				OP_PRE_INCREMENT,	false	},
1105e5c31af7Sopenharmony_ci		{ "pre_decrement",	"Matrix prefix decrement tests",				OP_PRE_DECREMENT,	false	},
1106e5c31af7Sopenharmony_ci		{ "post_increment",	"Matrix postfix increment tests",				OP_POST_INCREMENT,	false	},
1107e5c31af7Sopenharmony_ci		{ "post_decrement",	"Matrix postfix decrement tests",				OP_POST_DECREMENT,	false	},
1108e5c31af7Sopenharmony_ci		{ "add_assign",		"Matrix add into tests",						OP_ADD_INTO,		false	},
1109e5c31af7Sopenharmony_ci		{ "sub_assign",		"Matrix subtract from tests",					OP_SUBTRACT_FROM,	false	},
1110e5c31af7Sopenharmony_ci		{ "mul_assign",		"Matrix multiply into tests",					OP_MULTIPLY_INTO,	false	},
1111e5c31af7Sopenharmony_ci		{ "div_assign",		"Matrix divide into tests",						OP_DIVIDE_INTO,		false	},
1112e5c31af7Sopenharmony_ci	};
1113e5c31af7Sopenharmony_ci
1114e5c31af7Sopenharmony_ci	struct InputTypeSpec
1115e5c31af7Sopenharmony_ci	{
1116e5c31af7Sopenharmony_ci		const char*		name;
1117e5c31af7Sopenharmony_ci		const char*		desc;
1118e5c31af7Sopenharmony_ci		InputType		type;
1119e5c31af7Sopenharmony_ci	};
1120e5c31af7Sopenharmony_ci	static const InputTypeSpec extendedInputTypes[] =
1121e5c31af7Sopenharmony_ci	{
1122e5c31af7Sopenharmony_ci		{ "const",		"Constant matrix input",	INPUTTYPE_CONST		},
1123e5c31af7Sopenharmony_ci		{ "uniform",	"Uniform matrix input",		INPUTTYPE_UNIFORM	},
1124e5c31af7Sopenharmony_ci		{ "dynamic",	"Dynamic matrix input",		INPUTTYPE_DYNAMIC	}
1125e5c31af7Sopenharmony_ci	};
1126e5c31af7Sopenharmony_ci	static const InputTypeSpec reducedInputTypes[] =
1127e5c31af7Sopenharmony_ci	{
1128e5c31af7Sopenharmony_ci		{ "dynamic",	"Dynamic matrix input",		INPUTTYPE_DYNAMIC	}
1129e5c31af7Sopenharmony_ci	};
1130e5c31af7Sopenharmony_ci
1131e5c31af7Sopenharmony_ci	static const DataType matrixTypes[] =
1132e5c31af7Sopenharmony_ci	{
1133e5c31af7Sopenharmony_ci		TYPE_FLOAT_MAT2,
1134e5c31af7Sopenharmony_ci		TYPE_FLOAT_MAT3,
1135e5c31af7Sopenharmony_ci		TYPE_FLOAT_MAT4
1136e5c31af7Sopenharmony_ci	};
1137e5c31af7Sopenharmony_ci
1138e5c31af7Sopenharmony_ci	static const Precision precisions[] =
1139e5c31af7Sopenharmony_ci	{
1140e5c31af7Sopenharmony_ci		PRECISION_LOWP,
1141e5c31af7Sopenharmony_ci		PRECISION_MEDIUMP,
1142e5c31af7Sopenharmony_ci		PRECISION_HIGHP
1143e5c31af7Sopenharmony_ci	};
1144e5c31af7Sopenharmony_ci
1145e5c31af7Sopenharmony_ci	for (int opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
1146e5c31af7Sopenharmony_ci	{
1147e5c31af7Sopenharmony_ci		const InputTypeSpec*	inTypeList		= (ops[opNdx].extendedInputTypeCases) ? (extendedInputTypes) : (reducedInputTypes);
1148e5c31af7Sopenharmony_ci		const int				inTypeListSize	= (ops[opNdx].extendedInputTypeCases) ? (DE_LENGTH_OF_ARRAY(extendedInputTypes)) : (DE_LENGTH_OF_ARRAY(reducedInputTypes));
1149e5c31af7Sopenharmony_ci		const MatrixOp			op				= ops[opNdx].op;
1150e5c31af7Sopenharmony_ci		tcu::TestCaseGroup*		opGroup			= new tcu::TestCaseGroup(m_testCtx, ops[opNdx].name, ops[opNdx].desc);
1151e5c31af7Sopenharmony_ci
1152e5c31af7Sopenharmony_ci		addChild(opGroup);
1153e5c31af7Sopenharmony_ci
1154e5c31af7Sopenharmony_ci		for (int inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++)
1155e5c31af7Sopenharmony_ci		{
1156e5c31af7Sopenharmony_ci			const InputType		inputType	= inTypeList[inTypeNdx].type;
1157e5c31af7Sopenharmony_ci
1158e5c31af7Sopenharmony_ci			for (int matTypeNdx = 0; matTypeNdx < DE_LENGTH_OF_ARRAY(matrixTypes); matTypeNdx++)
1159e5c31af7Sopenharmony_ci			{
1160e5c31af7Sopenharmony_ci				DataType	matType		= matrixTypes[matTypeNdx];
1161e5c31af7Sopenharmony_ci				const char*	matTypeName	= getDataTypeName(matType);
1162e5c31af7Sopenharmony_ci
1163e5c31af7Sopenharmony_ci				for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
1164e5c31af7Sopenharmony_ci				{
1165e5c31af7Sopenharmony_ci					Precision	precision	= precisions[precNdx];
1166e5c31af7Sopenharmony_ci					const char*	precName	= getPrecisionName(precision);
1167e5c31af7Sopenharmony_ci					string		baseName	= string(inTypeList[inTypeNdx].name) + "_" + precName + "_" + matTypeName + "_";
1168e5c31af7Sopenharmony_ci					ShaderInput	matIn		(inputType, matType, precision);
1169e5c31af7Sopenharmony_ci
1170e5c31af7Sopenharmony_ci					if (isOperationMatrixScalar(op))
1171e5c31af7Sopenharmony_ci					{
1172e5c31af7Sopenharmony_ci						// Matrix-scalar \note For div cases we use uniform input.
1173e5c31af7Sopenharmony_ci						ShaderInput scalarIn(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, TYPE_FLOAT, precision);
1174e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_vertex").c_str(),		"Matrix-scalar case", matIn, scalarIn, op, true));
1175e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "float_fragment").c_str(),	"Matrix-scalar case", matIn, scalarIn, op, false));
1176e5c31af7Sopenharmony_ci					}
1177e5c31af7Sopenharmony_ci
1178e5c31af7Sopenharmony_ci					if (isOperationMatrixVector(op))
1179e5c31af7Sopenharmony_ci					{
1180e5c31af7Sopenharmony_ci						// Matrix-vector.
1181e5c31af7Sopenharmony_ci						DataType	vecType	= getDataTypeFloatVec(getDataTypeMatrixNumColumns(matType));
1182e5c31af7Sopenharmony_ci						ShaderInput vecIn	(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, vecType, precision);
1183e5c31af7Sopenharmony_ci
1184e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(vecType) + "_vertex").c_str(),	"Matrix-vector case", matIn, vecIn, op, true));
1185e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + getDataTypeName(vecType) + "_fragment").c_str(),	"Matrix-vector case", matIn, vecIn, op, false));
1186e5c31af7Sopenharmony_ci
1187e5c31af7Sopenharmony_ci						// Vector-matrix.
1188e5c31af7Sopenharmony_ci						string vecMatName = string(inTypeList[inTypeNdx].name) + "_" + precName + "_" + getDataTypeName(vecType) + "_" + matTypeName;
1189e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (vecMatName + "_vertex").c_str(),		"Vector-matrix case", vecIn, matIn, op, true));
1190e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (vecMatName + "_fragment").c_str(),	"Vector-matrix case", vecIn, matIn, op, false));
1191e5c31af7Sopenharmony_ci					}
1192e5c31af7Sopenharmony_ci
1193e5c31af7Sopenharmony_ci					if (isOperationMatrixMatrix(op))
1194e5c31af7Sopenharmony_ci					{
1195e5c31af7Sopenharmony_ci						// Matrix-matrix.
1196e5c31af7Sopenharmony_ci						ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
1197e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + matTypeName + "_vertex").c_str(),		"Matrix-matrix case", matIn, otherMatIn, op, true));
1198e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + matTypeName + "_fragment").c_str(),	"Matrix-matrix case", matIn, otherMatIn, op, false));
1199e5c31af7Sopenharmony_ci					}
1200e5c31af7Sopenharmony_ci
1201e5c31af7Sopenharmony_ci					if (isOperationUnary(op))
1202e5c31af7Sopenharmony_ci					{
1203e5c31af7Sopenharmony_ci						// op matrix
1204e5c31af7Sopenharmony_ci						ShaderInput voidInput(INPUTTYPE_LAST, TYPE_LAST, PRECISION_LAST);
1205e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "vertex").c_str(),		"Matrix case", matIn, voidInput, op, true));
1206e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "fragment").c_str(),	"Matrix case", matIn, voidInput, op, false));
1207e5c31af7Sopenharmony_ci					}
1208e5c31af7Sopenharmony_ci
1209e5c31af7Sopenharmony_ci					if (isOperationAssignment(op))
1210e5c31af7Sopenharmony_ci					{
1211e5c31af7Sopenharmony_ci						ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
1212e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "vertex").c_str(),		"Matrix assignment case", matIn, otherMatIn, op, true));
1213e5c31af7Sopenharmony_ci						opGroup->addChild(new ShaderMatrixCase(m_context, (baseName + "fragment").c_str(),	"Matrix assignment case", matIn, otherMatIn, op, false));
1214e5c31af7Sopenharmony_ci					}
1215e5c31af7Sopenharmony_ci				}
1216e5c31af7Sopenharmony_ci			}
1217e5c31af7Sopenharmony_ci		}
1218e5c31af7Sopenharmony_ci	}
1219e5c31af7Sopenharmony_ci}
1220e5c31af7Sopenharmony_ci
1221e5c31af7Sopenharmony_ci} // Functional
1222e5c31af7Sopenharmony_ci} // gles2
1223e5c31af7Sopenharmony_ci} // deqp
1224e5c31af7Sopenharmony_ci
1225e5c31af7Sopenharmony_ci#if defined(_MSC_VER) && _MSC_FULL_VER == 191125507
1226e5c31af7Sopenharmony_ci// Work around crbug.com/759402 which is a code-gen bug in VC++ 2017, version
1227e5c31af7Sopenharmony_ci// 15.3.2.
1228e5c31af7Sopenharmony_ci#pragma optimize("", off)
1229e5c31af7Sopenharmony_ci#endif
1230