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