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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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::__anon6963bb650111::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 }
1381 }
1382
1383 // ShaderMatrixInstance
1384
1385 class ShaderMatrixInstance : public ShaderRenderCaseInstance
1386 {
1387 public:
1388 ShaderMatrixInstance (Context& context,
1389 bool isVertex,
1390 const ShaderEvaluator& evaluator,
1391 const ShaderInput in0,
1392 const ShaderInput in1,
1393 const MatrixOp m_op);
1394 virtual ~ShaderMatrixInstance (void);
1395
1396 protected:
1397 virtual void setupUniforms (const tcu::Vec4&);
1398
1399 private:
1400 void addMatrixUniform (deUint32 bindingLocation, DataType dataType, const float* dataPtr);
1401
1402 const ShaderInput m_in0;
1403 const ShaderInput m_in1;
1404 const MatrixOp m_op;
1405 };
1406
ShaderMatrixInstance(Context & context,bool isVertex,const ShaderEvaluator & evaluator,const ShaderInput in0,const ShaderInput in1,const MatrixOp op)1407 ShaderMatrixInstance::ShaderMatrixInstance (Context& context,
1408 bool isVertex,
1409 const ShaderEvaluator& evaluator,
1410 const ShaderInput in0,
1411 const ShaderInput in1,
1412 const MatrixOp op)
1413 : ShaderRenderCaseInstance (context, isVertex, evaluator, DE_NULL, DE_NULL, IMAGE_BACKING_MODE_REGULAR, isVertex && op == OP_INVERSE ? 64 : GRID_SIZE_DEFAULTS)
1414 , m_in0 (in0)
1415 , m_in1 (in1)
1416 , m_op (op)
1417 {
1418 m_userAttribTransforms.resize(4);
1419 for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1420 {
1421 m_userAttribTransforms[attribNdx] = Mat4(0.0f);
1422 m_userAttribTransforms[attribNdx]( 0, 3) = (op == OP_INVERSE ? -0.5f : 0.2f); // prevent matrix*vec from going into zero (assuming vec.w != 0).
1423 m_userAttribTransforms[attribNdx]( 1, 3) = (op == OP_INVERSE ? -1.3f : 0.1f); // Modified input for OP_INVERSE case, as determinant of final input
1424 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.
1425 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.
1426 m_userAttribTransforms[attribNdx]((0 + attribNdx) % 4, 0) = 1.0f;
1427 m_userAttribTransforms[attribNdx]((1 + attribNdx) % 4, 1) = 1.0f;
1428 m_userAttribTransforms[attribNdx]((2 + attribNdx) % 4, 2) = 1.0f;
1429 m_userAttribTransforms[attribNdx]((3 + attribNdx) % 4, 3) = 1.0f;
1430 }
1431
1432 // prevent bad reference cases such as black result images by fine-tuning used matrices
1433 if (getOperationTestMatrixType(m_op) != TESTMATRIXTYPE_DEFAULT)
1434 {
1435 for (int attribNdx = 0; attribNdx < 4; attribNdx++)
1436 {
1437 for (int row = 0; row < 4; row++)
1438 for (int col = 0; col < 4; col++)
1439 {
1440 switch (getOperationTestMatrixType(m_op))
1441 {
1442 case TESTMATRIXTYPE_NEGATED:
1443 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col);
1444 break;
1445 case TESTMATRIXTYPE_INCREMENTED:
1446 m_userAttribTransforms[attribNdx](row, col) += 0.3f;
1447 break;
1448 case TESTMATRIXTYPE_DECREMENTED:
1449 m_userAttribTransforms[attribNdx](row, col) -= 0.3f;
1450 break;
1451 case TESTMATRIXTYPE_NEGATED_INCREMENTED:
1452 m_userAttribTransforms[attribNdx](row, col) = -m_userAttribTransforms[attribNdx](row, col) + 0.3f;
1453 break;
1454 case TESTMATRIXTYPE_INCREMENTED_LESS:
1455 m_userAttribTransforms[attribNdx](row, col) -= 0.1f;
1456 break;
1457
1458 default:
1459 DE_ASSERT(DE_FALSE);
1460 break;
1461 }
1462 }
1463 }
1464 }
1465
1466 int numInputs = isOperationBinary(m_op) ? 2 : 1;
1467
1468 for (int inNdx = 0; inNdx < numInputs; inNdx++)
1469 {
1470 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1471
1472 if (in.inputType == INPUTTYPE_DYNAMIC && isDataTypeMatrix(in.dataType))
1473 {
1474 useAttribute(4u + inNdx, getAttributeType(in.dataType));
1475 }
1476 }
1477
1478 }
1479
~ShaderMatrixInstance(void)1480 ShaderMatrixInstance::~ShaderMatrixInstance (void)
1481 {
1482 }
1483
addMatrixUniform(deUint32 bindingLocation,DataType dataType,const float * dataPtr)1484 void ShaderMatrixInstance::addMatrixUniform(deUint32 bindingLocation, DataType dataType, const float *dataPtr)
1485 {
1486 Mat4 result;
1487 const size_t matrixSize = sizeof(float) * 4 * 4;
1488
1489 switch(dataType)
1490 {
1491 case TYPE_FLOAT_MAT2:
1492 {
1493 Mat2 matrix = Mat2(dataPtr);
1494 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1495 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1496 break;
1497 }
1498 case TYPE_FLOAT_MAT2X3:
1499 {
1500 Mat2x3 matrix = Mat2x3(dataPtr);
1501 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1502 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1503 break;
1504 }
1505 case TYPE_FLOAT_MAT2X4:
1506 {
1507 Mat2x4 matrix = Mat2x4(dataPtr);
1508 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1509 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1510 break;
1511 }
1512 case TYPE_FLOAT_MAT3X2:
1513 {
1514 Mat3x2 matrix = Mat3x2(dataPtr);
1515 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1516 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1517 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1518 break;
1519 }
1520 case TYPE_FLOAT_MAT3:
1521 {
1522 Mat3 matrix = Mat3(dataPtr);
1523 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1524 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1525 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1526 break;
1527 }
1528 case TYPE_FLOAT_MAT3X4:
1529 {
1530 Mat3x4 matrix = Mat3x4(dataPtr);
1531 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1532 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1533 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1534 break;
1535 }
1536 case TYPE_FLOAT_MAT4X2:
1537 {
1538 Mat4x2 matrix = Mat4x2(dataPtr);
1539 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1540 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1541 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1542 result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1543 break;
1544 }
1545 case TYPE_FLOAT_MAT4X3:
1546 {
1547 Mat4x3 matrix = Mat4x3(dataPtr);
1548 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1549 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1550 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1551 result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1552 break;
1553 }
1554 case TYPE_FLOAT_MAT4:
1555 {
1556 Mat4 matrix = Mat4(dataPtr);
1557 result.setColumn(0, matrix.getColumn(0).toWidth<4>());
1558 result.setColumn(1, matrix.getColumn(1).toWidth<4>());
1559 result.setColumn(2, matrix.getColumn(2).toWidth<4>());
1560 result.setColumn(3, matrix.getColumn(3).toWidth<4>());
1561 break;
1562 }
1563 default:
1564 DE_ASSERT(false);
1565 break;
1566 }
1567
1568 addUniform(bindingLocation, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, matrixSize, result.getColumnMajorData().getPtr());
1569 }
1570
setupUniforms(const tcu::Vec4 &)1571 void ShaderMatrixInstance::setupUniforms (const tcu::Vec4&)
1572 {
1573 const int numInputs = isOperationBinary(m_op) ? 2 : 1;
1574 deUint32 uniformBinding = 0;
1575
1576 for (int inNdx = 0; inNdx < numInputs; inNdx++)
1577 {
1578 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1579
1580 if (in.inputType == INPUTTYPE_UNIFORM)
1581 {
1582 switch (in.dataType)
1583 {
1584 case TYPE_FLOAT: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(float), &s_constInFloat[inNdx]); break;
1585 case TYPE_FLOAT_VEC2: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec2[inNdx]); break;
1586 case TYPE_FLOAT_VEC3: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec3[inNdx]); break;
1587 case TYPE_FLOAT_VEC4: addUniform(uniformBinding, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, s_constInVec4[inNdx]); break;
1588 // \note GLES3 supports transpose in matrix upload.
1589 case TYPE_FLOAT_MAT2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x2[inNdx]); break;
1590 case TYPE_FLOAT_MAT2X3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x3[inNdx]); break;
1591 case TYPE_FLOAT_MAT2X4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat2x4[inNdx]); break;
1592 case TYPE_FLOAT_MAT3X2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x2[inNdx]); break;
1593 case TYPE_FLOAT_MAT3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x3[inNdx]); break;
1594 case TYPE_FLOAT_MAT3X4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat3x4[inNdx]); break;
1595 case TYPE_FLOAT_MAT4X2: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x2[inNdx]); break;
1596 case TYPE_FLOAT_MAT4X3: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x3[inNdx]); break;
1597 case TYPE_FLOAT_MAT4: addMatrixUniform(uniformBinding, in.dataType, s_constInMat4x4[inNdx]); break;
1598 default:
1599 DE_ASSERT(false);
1600 }
1601 uniformBinding++;
1602 }
1603 }
1604 }
1605
1606 // ShaderMatrixCase
1607
1608 class ShaderMatrixCase : public ShaderRenderCase
1609 {
1610 public:
1611 ShaderMatrixCase (tcu::TestContext& testCtx,
1612 const std::string& name,
1613 const std::string& desc,
1614 const ShaderInput& in0,
1615 const ShaderInput& in1,
1616 const MatrixOp op,
1617 bool isVertexCase);
1618 ~ShaderMatrixCase (void);
1619
1620 virtual TestInstance* createInstance (Context& context) const;
1621
1622 protected:
1623 void setupShader (void);
1624 std::string genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName);
1625
1626 private:
1627 const ShaderInput m_in0;
1628 const ShaderInput m_in1;
1629 const MatrixOp m_op;
1630 };
1631
ShaderMatrixCase(tcu::TestContext & testCtx,const std::string & name,const std::string & desc,const ShaderInput & in0,const ShaderInput & in1,MatrixOp op,bool isVertexCase)1632 ShaderMatrixCase::ShaderMatrixCase (tcu::TestContext& testCtx,
1633 const std::string& name,
1634 const std::string& desc,
1635 const ShaderInput& in0,
1636 const ShaderInput& in1,
1637 MatrixOp op,
1638 bool isVertexCase)
1639 : ShaderRenderCase (testCtx,
1640 name,
1641 desc,
1642 isVertexCase,
1643 new MatrixShaderEvaluator(getEvalFunc(in0, in1, op), in0.inputType, in1.inputType),
1644 DE_NULL /* uniform setup */,
1645 DE_NULL /* attribute setup */)
1646 , m_in0 (in0)
1647 , m_in1 (in1)
1648 , m_op (op)
1649 {
1650 setupShader();
1651 }
1652
~ShaderMatrixCase(void)1653 ShaderMatrixCase::~ShaderMatrixCase (void)
1654 {
1655 }
1656
createInstance(Context & context) const1657 TestInstance* ShaderMatrixCase::createInstance (Context& context) const
1658 {
1659 return new ShaderMatrixInstance(context, m_isVertexCase, *m_evaluator, m_in0, m_in1, m_op);
1660 }
1661
setupShader(void)1662 void ShaderMatrixCase::setupShader (void)
1663 {
1664 std::ostringstream vtx;
1665 std::ostringstream frag;
1666 std::ostringstream& op = m_isVertexCase ? vtx : frag;
1667
1668 bool isInDynMat0 = isDataTypeMatrix(m_in0.dataType) && m_in0.inputType == INPUTTYPE_DYNAMIC;
1669 bool isInDynMat1 = isDataTypeMatrix(m_in1.dataType) && m_in1.inputType == INPUTTYPE_DYNAMIC;
1670 string inValue0;
1671 string inValue1;
1672 DataType resultType = TYPE_LAST;
1673 Precision resultPrec = m_in0.precision;
1674 vector<string> passVars;
1675 int numInputs = (isOperationBinary(m_op)) ? (2) : (1);
1676
1677 std::string operationValue0;
1678 std::string operationValue1;
1679
1680 DE_ASSERT(!isInDynMat0 || !isInDynMat1); // Only single dynamic matrix input is allowed.
1681 DE_UNREF(isInDynMat0 && isInDynMat1);
1682
1683 // Compute result type.
1684 if (m_op == OP_MUL && isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1685 {
1686 resultType = getDataTypeMatrix(getDataTypeMatrixNumColumns(m_in1.dataType), getDataTypeMatrixNumRows(m_in0.dataType));
1687 }
1688 else if (m_op == OP_OUTER_PRODUCT)
1689 {
1690 resultType = getDataTypeMatrix(getDataTypeScalarSize(m_in1.dataType), getDataTypeScalarSize(m_in0.dataType));
1691 }
1692 else if (m_op == OP_TRANSPOSE)
1693 {
1694 resultType = getDataTypeMatrix(getDataTypeMatrixNumRows(m_in0.dataType), getDataTypeMatrixNumColumns(m_in0.dataType));
1695 }
1696 else if (m_op == OP_INVERSE)
1697 {
1698 resultType = m_in0.dataType;
1699 }
1700 else if (m_op == OP_DETERMINANT)
1701 {
1702 resultType = TYPE_FLOAT;
1703 }
1704 else if (getOperationType(m_op) == OPERATIONTYPE_UNARY_PREFIX_OPERATOR ||
1705 getOperationType(m_op) == OPERATIONTYPE_UNARY_POSTFIX_OPERATOR)
1706 {
1707 resultType = m_in0.dataType;
1708 }
1709 else if (isDataTypeMatrix(m_in0.dataType) && isDataTypeMatrix(m_in1.dataType))
1710 {
1711 DE_ASSERT(m_in0.dataType == m_in1.dataType);
1712 resultType = m_in0.dataType;
1713 }
1714 else if (isDataTypeMatrix(m_in0.dataType) || isDataTypeMatrix(m_in1.dataType))
1715 {
1716 int matNdx = isDataTypeMatrix(m_in0.dataType) ? 0 : 1;
1717 DataType matrixType = matNdx == 0 ? m_in0.dataType : m_in1.dataType;
1718 DataType otherType = matNdx == 0 ? m_in1.dataType : m_in0.dataType;
1719
1720 if (otherType == TYPE_FLOAT)
1721 resultType = matrixType;
1722 else
1723 {
1724 DE_ASSERT(isDataTypeVector(otherType));
1725 resultType = getDataTypeFloatVec(matNdx == 0 ? getDataTypeMatrixNumRows(matrixType) : getDataTypeMatrixNumColumns(matrixType));
1726 }
1727 }
1728 else
1729 {
1730 DE_ASSERT(DE_FALSE);
1731 }
1732
1733 static const std::string header =
1734 "#version 310 es\n";
1735
1736 vtx << header;
1737 frag << header;
1738
1739 vtx << "layout(location = 0) in highp vec4 a_position;\n";
1740 frag << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1741 if (m_isVertexCase)
1742 {
1743 vtx << "layout(location = 0) out mediump vec4 v_color;\n";
1744 frag << "layout(location = 0) in mediump vec4 v_color;\n";
1745 }
1746
1747 // Input declarations.
1748 deUint32 uniformBinding = 0;
1749 deUint32 padding = 0;
1750 for (int inNdx = 0; inNdx < numInputs; inNdx++)
1751 {
1752 const ShaderInput& in = inNdx > 0 ? m_in1 : m_in0;
1753 const char* precName = getPrecisionName(in.precision);
1754 const char* typeName = getDataTypeName(in.dataType);
1755 string& inValue = inNdx > 0 ? inValue1 : inValue0;
1756
1757 if (in.inputType == INPUTTYPE_DYNAMIC)
1758 {
1759 if (isDataTypeMatrix(in.dataType))
1760 {
1761 vtx << "layout(location = " << 4 + inNdx + padding << ") in " << precName << " " << typeName << " a_";
1762 // a_matN, v_matN
1763 vtx << typeName << ";\n";
1764 if (!m_isVertexCase)
1765 {
1766 vtx << "layout(location = " << 1 + inNdx + padding << ") out " << precName << " " << typeName << " v_" << typeName << ";\n";
1767 frag << "layout(location = " << 1 + inNdx + padding << ") in " << precName << " " << typeName << " v_" << typeName << ";\n";
1768 passVars.push_back(typeName);
1769 }
1770
1771 inValue = string(m_isVertexCase ? "a_" : "v_") + getDataTypeName(in.dataType);
1772 padding += getDataTypeMatrixNumColumns(in.dataType);
1773 }
1774 else
1775 {
1776 // a_coords, v_coords
1777 vtx << "layout(location = 1) in " << precName << " " << typeName << " a_coords;\n";
1778 if (!m_isVertexCase)
1779 {
1780 vtx << "layout(location = " << 1 + padding << ") out " << precName << " " << typeName << " v_coords;\n";
1781 frag << "layout(location = " << 1 + padding << ") in " << precName << " " << typeName << " v_coords;\n";
1782 passVars.push_back("coords");
1783 }
1784
1785 inValue = m_isVertexCase ? "a_coords" : "v_coords";
1786 }
1787 }
1788 else if (in.inputType == INPUTTYPE_UNIFORM)
1789 {
1790 op << "layout(std140, set = 0, binding = " << uniformBinding++ << ") uniform buffer"<< inNdx <<" { " << precName << " " << typeName << " u_in" << inNdx << "; };\n";
1791 inValue = string("u_in") + de::toString(inNdx);
1792 }
1793 else if (in.inputType == INPUTTYPE_CONST)
1794 {
1795 op << "const " << precName << " " << typeName << " in" << inNdx << " = ";
1796
1797 // Generate declaration.
1798 switch (in.dataType)
1799 {
1800 case TYPE_FLOAT: op << de::floatToString(s_constInFloat[inNdx], 1); break;
1801 case TYPE_FLOAT_VEC2: writeVectorConstructor<2>(op, s_constInVec2[inNdx]); break;
1802 case TYPE_FLOAT_VEC3: writeVectorConstructor<3>(op, s_constInVec3[inNdx]); break;
1803 case TYPE_FLOAT_VEC4: writeVectorConstructor<4>(op, s_constInVec4[inNdx]); break;
1804 case TYPE_FLOAT_MAT2: writeMatrixConstructor<2, 2>(op, Mat2(s_constInMat2x2[inNdx])); break;
1805 case TYPE_FLOAT_MAT2X3: writeMatrixConstructor<2, 3>(op, Mat2x3(s_constInMat2x3[inNdx])); break;
1806 case TYPE_FLOAT_MAT2X4: writeMatrixConstructor<2, 4>(op, Mat2x4(s_constInMat2x4[inNdx])); break;
1807 case TYPE_FLOAT_MAT3X2: writeMatrixConstructor<3, 2>(op, Mat3x2(s_constInMat3x2[inNdx])); break;
1808 case TYPE_FLOAT_MAT3: writeMatrixConstructor<3, 3>(op, Mat3(s_constInMat3x3[inNdx])); break;
1809 case TYPE_FLOAT_MAT3X4: writeMatrixConstructor<3, 4>(op, Mat3x4(s_constInMat3x4[inNdx])); break;
1810 case TYPE_FLOAT_MAT4X2: writeMatrixConstructor<4, 2>(op, Mat4x2(s_constInMat4x2[inNdx])); break;
1811 case TYPE_FLOAT_MAT4X3: writeMatrixConstructor<4, 3>(op, Mat4x3(s_constInMat4x3[inNdx])); break;
1812 case TYPE_FLOAT_MAT4: writeMatrixConstructor<4, 4>(op, Mat4(s_constInMat4x4[inNdx])); break;
1813
1814 default:
1815 DE_ASSERT(DE_FALSE);
1816 }
1817
1818 op << ";\n";
1819
1820 inValue = string("in") + de::toString(inNdx);
1821 }
1822 }
1823
1824 vtx << "\n"
1825 << "void main (void)\n"
1826 << "{\n"
1827 << " gl_Position = a_position;\n";
1828 frag << "\n"
1829 << "void main (void)\n"
1830 << "{\n";
1831
1832 if (m_isVertexCase)
1833 frag << " dEQP_FragColor = v_color;\n";
1834 else
1835 {
1836 for (vector<string>::const_iterator copyIter = passVars.begin(); copyIter != passVars.end(); copyIter++)
1837 vtx << " v_" << *copyIter << " = " << "a_" << *copyIter << ";\n";
1838 }
1839
1840 // Operation.
1841
1842 switch (getOperationNature(m_op))
1843 {
1844 case OPERATIONNATURE_PURE:
1845 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1846
1847 operationValue0 = inValue0;
1848 operationValue1 = inValue1;
1849 break;
1850
1851 case OPERATIONNATURE_MUTATING:
1852 DE_ASSERT(getOperationType(m_op) != OPERATIONTYPE_ASSIGNMENT);
1853
1854 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " tmpValue = " << inValue0 << ";\n";
1855
1856 operationValue0 = "tmpValue";
1857 operationValue1 = inValue1;
1858 break;
1859
1860 case OPERATIONNATURE_ASSIGNMENT:
1861 DE_ASSERT(getOperationType(m_op) == OPERATIONTYPE_ASSIGNMENT);
1862
1863 operationValue0 = inValue0;
1864 operationValue1 = inValue1;
1865 break;
1866
1867 default:
1868 DE_ASSERT(DE_FALSE);
1869 }
1870
1871 switch (getOperationType(m_op))
1872 {
1873 case OPERATIONTYPE_BINARY_OPERATOR:
1874 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << " " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1875 break;
1876
1877 case OPERATIONTYPE_UNARY_PREFIX_OPERATOR:
1878 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << operationValue0 << ";\n";
1879 break;
1880
1881 case OPERATIONTYPE_UNARY_POSTFIX_OPERATOR:
1882 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << getOperationName(m_op) << ";\n";
1883 break;
1884
1885 case OPERATIONTYPE_BINARY_FUNCTION:
1886 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ", " << operationValue1 << ");\n";
1887 break;
1888
1889 case OPERATIONTYPE_UNARY_FUNCTION:
1890 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << getOperationName(m_op) << "(" << operationValue0 << ");\n";
1891 break;
1892
1893 case OPERATIONTYPE_ASSIGNMENT:
1894 op << " " << getPrecisionName(resultPrec) << " " << getDataTypeName(resultType) << " res = " << operationValue0 << ";\n";
1895 op << " res " << getOperationName(m_op) << " " << operationValue1 << ";\n";
1896 break;
1897
1898 default:
1899 DE_ASSERT(DE_FALSE);
1900 }
1901
1902 // Reduction to vec3 (rgb). Check the used value too if it was modified
1903 op << " " << (m_isVertexCase ? "v_color" : "dEQP_FragColor") << " = ";
1904
1905 if (isOperationValueModifying(m_op))
1906 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0) + vec4(" << genGLSLMatToVec3Reduction(resultType, "tmpValue") << ", 0.0);\n";
1907 else
1908 op << "vec4(" << genGLSLMatToVec3Reduction(resultType, "res") << ", 1.0);\n";
1909
1910 vtx << "}\n";
1911 frag << "}\n";
1912
1913 m_vertShaderSource = vtx.str();
1914 m_fragShaderSource = frag.str();
1915 }
1916
genGLSLMatToVec3Reduction(const glu::DataType & matType,const char * varName)1917 std::string ShaderMatrixCase::genGLSLMatToVec3Reduction (const glu::DataType& matType, const char* varName)
1918 {
1919 std::ostringstream op;
1920
1921 switch (matType)
1922 {
1923 case TYPE_FLOAT: op << varName << ", " << varName << ", " << varName << ""; break;
1924 case TYPE_FLOAT_VEC2: op << varName << ".x, " << varName << ".y, " << varName << ".x"; break;
1925 case TYPE_FLOAT_VEC3: op << varName << ""; break;
1926 case TYPE_FLOAT_VEC4: op << varName << ".x, " << varName << ".y, " << varName << ".z+" << varName << ".w"; break;
1927 case TYPE_FLOAT_MAT2: op << varName << "[0][0], " << varName << "[1][0], " << varName << "[0][1]+" << varName << "[1][1]"; break;
1928 case TYPE_FLOAT_MAT2X3: op << varName << "[0] + " << varName << "[1]"; break;
1929 case TYPE_FLOAT_MAT2X4: op << varName << "[0].xyz + " << varName << "[1].yzw"; break;
1930 case TYPE_FLOAT_MAT3X2: op << varName << "[0][0]+" << varName << "[0][1], " << varName << "[1][0]+" << varName << "[1][1], " << varName << "[2][0]+" << varName << "[2][1]"; break;
1931 case TYPE_FLOAT_MAT3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2]"; break;
1932 case TYPE_FLOAT_MAT3X4: op << varName << "[0].xyz + " << varName << "[1].yzw + " << varName << "[2].zwx"; break;
1933 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;
1934 case TYPE_FLOAT_MAT4X3: op << varName << "[0] + " << varName << "[1] + " << varName << "[2] + " << varName << "[3]"; break;
1935 case TYPE_FLOAT_MAT4: op << varName << "[0].xyz+" << varName << "[1].yzw+" << varName << "[2].zwx+" << varName << "[3].wxy"; break;
1936
1937 default:
1938 DE_ASSERT(DE_FALSE);
1939 }
1940
1941 return op.str();
1942 }
1943
1944 class ShaderMatrixTests : public tcu::TestCaseGroup
1945 {
1946 public:
1947 ShaderMatrixTests (tcu::TestContext& testCtx);
1948 virtual ~ShaderMatrixTests (void);
1949
1950 virtual void init (void);
1951
1952 private:
1953 ShaderMatrixTests (const ShaderMatrixTests&); // not allowed!
1954 ShaderMatrixTests& operator= (const ShaderMatrixTests&); // not allowed!
1955 };
1956
ShaderMatrixTests(tcu::TestContext & testCtx)1957 ShaderMatrixTests::ShaderMatrixTests (tcu::TestContext& testCtx)
1958 : TestCaseGroup(testCtx, "matrix", "Matrix Tests")
1959 {
1960 }
1961
~ShaderMatrixTests(void)1962 ShaderMatrixTests::~ShaderMatrixTests (void)
1963 {
1964 }
1965
init(void)1966 void ShaderMatrixTests::init (void)
1967 {
1968 static const struct
1969 {
1970 const char* name;
1971 const char* desc;
1972 const MatrixOp op;
1973 const bool extendedInputTypeCases; // !< test with const and uniform types too
1974 const bool createInputTypeGroup; // !< create group for input types
1975 } ops[] =
1976 {
1977 { "add", "Matrix addition tests", OP_ADD, true, true },
1978 { "sub", "Matrix subtraction tests", OP_SUB, true, true },
1979 { "mul", "Matrix multiplication tests", OP_MUL, true, true },
1980 { "div", "Matrix division tests", OP_DIV, true, true },
1981 { "matrixcompmult", "Matrix component-wise multiplication tests", OP_COMP_MUL, false, true },
1982 { "outerproduct", "Matrix outerProduct() tests", OP_OUTER_PRODUCT, false, true },
1983 { "transpose", "Matrix transpose() tests", OP_TRANSPOSE, false, true },
1984 { "determinant", "Matrix determinant() tests", OP_DETERMINANT, false, true },
1985 { "inverse", "Matrix inverse() tests", OP_INVERSE, false, true },
1986 { "unary_addition", "Matrix unary addition tests", OP_UNARY_PLUS, false, false },
1987 { "negation", "Matrix negation tests", OP_NEGATION, false, false },
1988 { "pre_increment", "Matrix prefix increment tests", OP_PRE_INCREMENT, false, false },
1989 { "pre_decrement", "Matrix prefix decrement tests", OP_PRE_DECREMENT, false, false },
1990 { "post_increment", "Matrix postfix increment tests", OP_POST_INCREMENT, false, false },
1991 { "post_decrement", "Matrix postfix decrement tests", OP_POST_DECREMENT, false, false },
1992 { "add_assign", "Matrix add into tests", OP_ADD_INTO, false, false },
1993 { "sub_assign", "Matrix subtract from tests", OP_SUBTRACT_FROM, false, false },
1994 { "mul_assign", "Matrix multiply into tests", OP_MULTIPLY_INTO, false, false },
1995 { "div_assign", "Matrix divide into tests", OP_DIVIDE_INTO, false, false },
1996 };
1997
1998 struct InputTypeSpec
1999 {
2000 const char* name;
2001 const char* desc;
2002 const InputType type;
2003 };
2004 static const InputTypeSpec extendedInputTypes[] =
2005 {
2006 { "const", "Constant matrix input", INPUTTYPE_CONST },
2007 { "uniform", "Uniform matrix input", INPUTTYPE_UNIFORM },
2008 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC }
2009 };
2010 static const InputTypeSpec reducedInputTypes[] =
2011 {
2012 { "dynamic", "Dynamic matrix input", INPUTTYPE_DYNAMIC }
2013 };
2014
2015 static const DataType matrixTypes[] =
2016 {
2017 TYPE_FLOAT_MAT2,
2018 TYPE_FLOAT_MAT2X3,
2019 TYPE_FLOAT_MAT2X4,
2020 TYPE_FLOAT_MAT3X2,
2021 TYPE_FLOAT_MAT3,
2022 TYPE_FLOAT_MAT3X4,
2023 TYPE_FLOAT_MAT4X2,
2024 TYPE_FLOAT_MAT4X3,
2025 TYPE_FLOAT_MAT4
2026 };
2027
2028 static const Precision precisions[] =
2029 {
2030 PRECISION_MEDIUMP,
2031 PRECISION_HIGHP
2032 };
2033
2034 for (int opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
2035 {
2036 const InputTypeSpec* inTypeList = (ops[opNdx].extendedInputTypeCases) ? (extendedInputTypes) : (reducedInputTypes);
2037 const int inTypeListSize = (ops[opNdx].extendedInputTypeCases) ? (DE_LENGTH_OF_ARRAY(extendedInputTypes)) : (DE_LENGTH_OF_ARRAY(reducedInputTypes));
2038 const MatrixOp op = ops[opNdx].op;
2039 tcu::TestCaseGroup* opGroup = new tcu::TestCaseGroup(m_testCtx, ops[opNdx].name, ops[opNdx].desc);
2040
2041 addChild(opGroup);
2042
2043 for (int inTypeNdx = 0; inTypeNdx < inTypeListSize; inTypeNdx++)
2044 {
2045 const InputType inputType = inTypeList[inTypeNdx].type;
2046 tcu::TestCaseGroup* inGroup;
2047
2048 if (ops[opNdx].createInputTypeGroup)
2049 {
2050 inGroup = new tcu::TestCaseGroup(m_testCtx, inTypeList[inTypeNdx].name, inTypeList[inTypeNdx].desc);
2051 opGroup->addChild(inGroup);
2052 }
2053 else
2054 inGroup = opGroup;
2055
2056 for (int matTypeNdx = 0; matTypeNdx < DE_LENGTH_OF_ARRAY(matrixTypes); matTypeNdx++)
2057 {
2058 DataType matType = matrixTypes[matTypeNdx];
2059 int numCols = getDataTypeMatrixNumColumns(matType);
2060 int numRows = getDataTypeMatrixNumRows(matType);
2061 const char* matTypeName = getDataTypeName(matType);
2062
2063 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
2064 {
2065 Precision precision = precisions[precNdx];
2066 const char* precName = getPrecisionName(precision);
2067 string baseName = string(precName) + "_" + matTypeName + "_";
2068 ShaderInput matIn (inputType, matType, precision);
2069
2070 if (isOperationMatrixScalar(op))
2071 {
2072 // Matrix-scalar \note For div cases we use uniform input.
2073 ShaderInput scalarIn(op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, TYPE_FLOAT, precision);
2074 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Matrix-scalar case", matIn, scalarIn, op, true));
2075 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Matrix-scalar case", matIn, scalarIn, op, false));
2076 }
2077
2078 if (isOperationMatrixVector(op))
2079 {
2080 // Matrix-vector.
2081 DataType colVecType = getDataTypeFloatVec(numCols);
2082 ShaderInput colVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, colVecType, precision);
2083
2084 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_vertex").c_str(), "Matrix-vector case", matIn, colVecIn, op, true));
2085 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(colVecType) + "_fragment").c_str(), "Matrix-vector case", matIn, colVecIn, op, false));
2086
2087 // Vector-matrix.
2088 DataType rowVecType = getDataTypeFloatVec(numRows);
2089 ShaderInput rowVecIn (op == OP_DIV ? INPUTTYPE_UNIFORM : INPUTTYPE_DYNAMIC, rowVecType, precision);
2090 string vecMatName = string(precName) + "_" + getDataTypeName(rowVecType) + "_" + matTypeName;
2091
2092 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_vertex").c_str(), "Vector-matrix case", rowVecIn, matIn, op, true));
2093 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (vecMatName + "_fragment").c_str(), "Vector-matrix case", rowVecIn, matIn, op, false));
2094 }
2095
2096 if (isOperationArithmeticMatrixMatrix(op))
2097 {
2098 // Arithmetic matrix-matrix multiplication.
2099 for (int otherCols = 2; otherCols <= 4; otherCols++)
2100 {
2101 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, getDataTypeMatrix(otherCols, numCols /* rows */), precision);
2102 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true));
2103 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + getDataTypeName(otherMatIn.dataType) + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false));
2104 }
2105 }
2106 else if (isOperationComponentwiseMatrixMatrix(op))
2107 {
2108 // Component-wise.
2109 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2110 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_vertex").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, true));
2111 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + matTypeName + "_fragment").c_str(), "Matrix-matrix case", matIn, otherMatIn, op, false));
2112 }
2113
2114 if (isOperationVectorVector(op))
2115 {
2116 ShaderInput vec1In(inputType, getDataTypeFloatVec(numRows), precision);
2117 ShaderInput vec2In((inputType == INPUTTYPE_DYNAMIC) ? (INPUTTYPE_UNIFORM) : (inputType), getDataTypeFloatVec(numCols), precision);
2118
2119 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Vector-vector case", vec1In, vec2In, op, true));
2120 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Vector-vector case", vec1In, vec2In, op, false));
2121 }
2122
2123 if ((isOperationUnaryAnyMatrix(op)) ||
2124 (isOperationUnarySymmetricMatrix(op) && numCols == numRows))
2125 {
2126 ShaderInput voidInput(INPUTTYPE_LAST, TYPE_LAST, PRECISION_LAST);
2127 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Matrix case", matIn, voidInput, op, true));
2128 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Matrix case", matIn, voidInput, op, false));
2129 }
2130
2131 if ((isOperationAssignmentAnyMatrix(op)) ||
2132 (isOperationAssignmentSymmetricMatrix(op) && numCols == numRows))
2133 {
2134 ShaderInput otherMatIn(inputType == INPUTTYPE_DYNAMIC ? INPUTTYPE_UNIFORM : inputType, matType, precision);
2135 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_vertex").c_str(), "Matrix assignment case", matIn, otherMatIn, op, true));
2136 inGroup->addChild(new ShaderMatrixCase(m_testCtx, (baseName + "float_fragment").c_str(), "Matrix assignment case", matIn, otherMatIn, op, false));
2137 }
2138 }
2139 }
2140 }
2141 }
2142 }
2143
2144 } // anonymous
2145
createMatrixTests(tcu::TestContext & testCtx)2146 tcu::TestCaseGroup* createMatrixTests (tcu::TestContext& testCtx)
2147 {
2148 return new ShaderMatrixTests(testCtx);
2149 }
2150
2151 } // sr
2152 } // vkt
2153