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