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