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