1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Shader operators tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2fShaderOperatorTests.hpp"
25 #include "glsShaderRenderCase.hpp"
26 #include "gluShaderUtil.hpp"
27 #include "tcuVectorUtil.hpp"
28
29 #include "deStringUtil.hpp"
30 #include "deInt32.h"
31 #include "deMemory.h"
32
33 #include <map>
34
35 using namespace tcu;
36 using namespace glu;
37 using namespace deqp::gls;
38
39 using std::map;
40 using std::ostringstream;
41 using std::pair;
42 using std::string;
43 using std::vector;
44
45 namespace deqp
46 {
47 namespace gles2
48 {
49 namespace Functional
50 {
51
52 #if defined(abs)
53 #undef abs
54 #endif
55
56 using de::clamp;
57 using de::max;
58 using de::min;
59
60 // \note VS2013 gets confused without these
61 using tcu::exp2;
62 using tcu::log2;
63
abs(float v)64 inline float abs(float v)
65 {
66 return deFloatAbs(v);
67 }
68
logicalAnd(bool a,bool b)69 inline bool logicalAnd(bool a, bool b)
70 {
71 return (a && b);
72 }
logicalOr(bool a,bool b)73 inline bool logicalOr(bool a, bool b)
74 {
75 return (a || b);
76 }
logicalXor(bool a,bool b)77 inline bool logicalXor(bool a, bool b)
78 {
79 return (a != b);
80 }
81
82 #define DEFINE_VEC_FLOAT_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
83 template <int Size> \
84 inline Vector<float, Size> FUNC_NAME(const Vector<float, Size> &v, float s) \
85 { \
86 Vector<float, Size> res; \
87 for (int i = 0; i < Size; i++) \
88 res[i] = SCALAR_OP_NAME(v[i], s); \
89 return res; \
90 }
91
92 #define DEFINE_FLOAT_VEC_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
93 template <int Size> \
94 inline Vector<float, Size> FUNC_NAME(float s, const Vector<float, Size> &v) \
95 { \
96 Vector<float, Size> res; \
97 for (int i = 0; i < Size; i++) \
98 res[i] = SCALAR_OP_NAME(s, v[i]); \
99 return res; \
100 }
101
102 #define DEFINE_VEC_VEC_FLOAT_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
103 template <int Size> \
104 inline Vector<float, Size> FUNC_NAME(const Vector<float, Size> &v0, const Vector<float, Size> &v1, float s) \
105 { \
106 Vector<float, Size> res; \
107 for (int i = 0; i < Size; i++) \
108 res[i] = SCALAR_OP_NAME(v0[i], v1[i], s); \
109 return res; \
110 }
111
112 #define DEFINE_VEC_FLOAT_FLOAT_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
113 template <int Size> \
114 inline Vector<float, Size> FUNC_NAME(const Vector<float, Size> &v, float s0, float s1) \
115 { \
116 Vector<float, Size> res; \
117 for (int i = 0; i < Size; i++) \
118 res[i] = SCALAR_OP_NAME(v[i], s0, s1); \
119 return res; \
120 }
121
122 #define DEFINE_FLOAT_FLOAT_VEC_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
123 template <int Size> \
124 inline Vector<float, Size> FUNC_NAME(float s0, float s1, const Vector<float, Size> &v) \
125 { \
126 Vector<float, Size> res; \
127 for (int i = 0; i < Size; i++) \
128 res[i] = SCALAR_OP_NAME(s0, s1, v[i]); \
129 return res; \
130 }
131
DEFINE_VEC_FLOAT_FUNCTION(modVecFloat,mod)132 DEFINE_VEC_FLOAT_FUNCTION(modVecFloat, mod)
133 DEFINE_VEC_FLOAT_FUNCTION(minVecFloat, min)
134 DEFINE_VEC_FLOAT_FUNCTION(maxVecFloat, max)
135 DEFINE_VEC_FLOAT_FLOAT_FUNCTION(clampVecFloatFloat, clamp)
136 DEFINE_VEC_VEC_FLOAT_FUNCTION(mixVecVecFloat, mix)
137 DEFINE_FLOAT_VEC_FUNCTION(stepFloatVec, step)
138 DEFINE_FLOAT_FLOAT_VEC_FUNCTION(smoothStepFloatFloatVec, smoothStep)
139
140 #undef DEFINE_VEC_FLOAT_FUNCTION
141 #undef DEFINE_VEC_VEC_FLOAT_FUNCTION
142 #undef DEFINE_VEC_FLOAT_FLOAT_FUNCTION
143 #undef DEFINE_FLOAT_FLOAT_VEC_FUNCTION
144
145 inline float addOne(float v)
146 {
147 return v + 1.0f;
148 }
subOne(float v)149 inline float subOne(float v)
150 {
151 return v - 1.0f;
152 }
addOne(int v)153 inline int addOne(int v)
154 {
155 return v + 1;
156 }
subOne(int v)157 inline int subOne(int v)
158 {
159 return v - 1;
160 }
161
162 template <int Size>
addOne(const Vector<float,Size> & v)163 inline Vector<float, Size> addOne(const Vector<float, Size> &v)
164 {
165 return v + 1.0f;
166 }
167 template <int Size>
subOne(const Vector<float,Size> & v)168 inline Vector<float, Size> subOne(const Vector<float, Size> &v)
169 {
170 return v - 1.0f;
171 }
172 template <int Size>
addOne(const Vector<int,Size> & v)173 inline Vector<int, Size> addOne(const Vector<int, Size> &v)
174 {
175 return v + 1;
176 }
177 template <int Size>
subOne(const Vector<int,Size> & v)178 inline Vector<int, Size> subOne(const Vector<int, Size> &v)
179 {
180 return v - 1;
181 }
182
183 template <typename T>
selection(bool cond,T a,T b)184 inline T selection(bool cond, T a, T b)
185 {
186 return cond ? a : b;
187 }
188
189 template <typename T, int Size>
addVecScalar(const Vector<T,Size> & v,T s)190 inline Vector<T, Size> addVecScalar(const Vector<T, Size> &v, T s)
191 {
192 return v + s;
193 }
194 template <typename T, int Size>
subVecScalar(const Vector<T,Size> & v,T s)195 inline Vector<T, Size> subVecScalar(const Vector<T, Size> &v, T s)
196 {
197 return v - s;
198 }
199 template <typename T, int Size>
mulVecScalar(const Vector<T,Size> & v,T s)200 inline Vector<T, Size> mulVecScalar(const Vector<T, Size> &v, T s)
201 {
202 return v * s;
203 }
204 template <typename T, int Size>
divVecScalar(const Vector<T,Size> & v,T s)205 inline Vector<T, Size> divVecScalar(const Vector<T, Size> &v, T s)
206 {
207 return v / s;
208 }
209
210 template <typename T, int Size>
addScalarVec(T s,const Vector<T,Size> & v)211 inline Vector<T, Size> addScalarVec(T s, const Vector<T, Size> &v)
212 {
213 return s + v;
214 }
215 template <typename T, int Size>
subScalarVec(T s,const Vector<T,Size> & v)216 inline Vector<T, Size> subScalarVec(T s, const Vector<T, Size> &v)
217 {
218 return s - v;
219 }
220 template <typename T, int Size>
mulScalarVec(T s,const Vector<T,Size> & v)221 inline Vector<T, Size> mulScalarVec(T s, const Vector<T, Size> &v)
222 {
223 return s * v;
224 }
225 template <typename T, int Size>
divScalarVec(T s,const Vector<T,Size> & v)226 inline Vector<T, Size> divScalarVec(T s, const Vector<T, Size> &v)
227 {
228 return s / v;
229 }
230
231 // Reference functions for specific sequence operations for the sequence operator tests.
232
233 // Reference for expression "in0, in2 + in1, in1 + in0"
sequenceNoSideEffCase0(const Vec4 & in0,const Vec4 & in1,const Vec4 & in2)234 inline Vec4 sequenceNoSideEffCase0(const Vec4 &in0, const Vec4 &in1, const Vec4 &in2)
235 {
236 DE_UNREF(in2);
237 return in1 + in0;
238 }
239 // Reference for expression "in0, in2 + in1, in1 + in0"
sequenceNoSideEffCase1(float in0,int in1,float in2)240 inline int sequenceNoSideEffCase1(float in0, int in1, float in2)
241 {
242 DE_UNREF(in0);
243 DE_UNREF(in2);
244 return in1 + in1;
245 }
246 // Reference for expression "in0 && in1, in0, ivec2(vec2(in0) + in2)"
sequenceNoSideEffCase2(bool in0,bool in1,const Vec2 & in2)247 inline IVec2 sequenceNoSideEffCase2(bool in0, bool in1, const Vec2 &in2)
248 {
249 DE_UNREF(in1);
250 return IVec2((int)((float)in0 + in2.x()), (int)((float)in0 + in2.y()));
251 }
252 // Reference for expression "in0 + vec4(in1), in2, in1"
sequenceNoSideEffCase3(const Vec4 & in0,const IVec4 & in1,const BVec4 & in2)253 inline IVec4 sequenceNoSideEffCase3(const Vec4 &in0, const IVec4 &in1, const BVec4 &in2)
254 {
255 DE_UNREF(in0);
256 DE_UNREF(in2);
257 return in1;
258 }
259 // Reference for expression "in0++, in1 = in0 + in2, in2 = in1"
sequenceSideEffCase0(const Vec4 & in0,const Vec4 & in1,const Vec4 & in2)260 inline Vec4 sequenceSideEffCase0(const Vec4 &in0, const Vec4 &in1, const Vec4 &in2)
261 {
262 DE_UNREF(in1);
263 return in0 + 1.0f + in2;
264 }
265 // Reference for expression "in1++, in0 = float(in1), in1 = int(in0 + in2)"
sequenceSideEffCase1(float in0,int in1,float in2)266 inline int sequenceSideEffCase1(float in0, int in1, float in2)
267 {
268 DE_UNREF(in0);
269 return (int)(float(in1) + 1.0f + in2);
270 }
271 // Reference for expression "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)"
sequenceSideEffCase2(bool in0,bool in1,const Vec2 & in2)272 inline IVec2 sequenceSideEffCase2(bool in0, bool in1, const Vec2 &in2)
273 {
274 DE_UNREF(in1);
275 return (in2 + Vec2(1.0f) + Vec2((float)in0)).asInt();
276 }
277 // Reference for expression "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++"
sequenceSideEffCase3(const Vec4 & in0,const IVec4 & in1,const BVec4 & in2)278 inline IVec4 sequenceSideEffCase3(const Vec4 &in0, const IVec4 &in1, const BVec4 &in2)
279 {
280 return in1 + (in0 + Vec4((float)in2.x(), (float)in2.y(), (float)in2.z(), (float)in2.w())).asInt();
281 }
282
283 // ShaderEvalFunc-type wrappers for the above functions.
evalSequenceNoSideEffCase0(ShaderEvalContext & ctx)284 void evalSequenceNoSideEffCase0(ShaderEvalContext &ctx)
285 {
286 ctx.color = sequenceNoSideEffCase0(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0),
287 ctx.in[2].swizzle(0, 3, 2, 1));
288 }
evalSequenceNoSideEffCase1(ShaderEvalContext & ctx)289 void evalSequenceNoSideEffCase1(ShaderEvalContext &ctx)
290 {
291 ctx.color.x() = (float)sequenceNoSideEffCase1(ctx.in[0].z(), (int)ctx.in[1].x(), ctx.in[2].y());
292 }
evalSequenceNoSideEffCase2(ShaderEvalContext & ctx)293 void evalSequenceNoSideEffCase2(ShaderEvalContext &ctx)
294 {
295 ctx.color.yz() =
296 sequenceNoSideEffCase2(ctx.in[0].z() > 0.0f, ctx.in[1].x() > 0.0f, ctx.in[2].swizzle(2, 1)).asFloat();
297 }
evalSequenceNoSideEffCase3(ShaderEvalContext & ctx)298 void evalSequenceNoSideEffCase3(ShaderEvalContext &ctx)
299 {
300 ctx.color = sequenceNoSideEffCase3(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0).asInt(),
301 greaterThan(ctx.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f)))
302 .asFloat();
303 }
evalSequenceSideEffCase0(ShaderEvalContext & ctx)304 void evalSequenceSideEffCase0(ShaderEvalContext &ctx)
305 {
306 ctx.color = sequenceSideEffCase0(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0),
307 ctx.in[2].swizzle(0, 3, 2, 1));
308 }
evalSequenceSideEffCase1(ShaderEvalContext & ctx)309 void evalSequenceSideEffCase1(ShaderEvalContext &ctx)
310 {
311 ctx.color.x() = (float)sequenceSideEffCase1(ctx.in[0].z(), (int)ctx.in[1].x(), ctx.in[2].y());
312 }
evalSequenceSideEffCase2(ShaderEvalContext & ctx)313 void evalSequenceSideEffCase2(ShaderEvalContext &ctx)
314 {
315 ctx.color.yz() =
316 sequenceSideEffCase2(ctx.in[0].z() > 0.0f, ctx.in[1].x() > 0.0f, ctx.in[2].swizzle(2, 1)).asFloat();
317 }
evalSequenceSideEffCase3(ShaderEvalContext & ctx)318 void evalSequenceSideEffCase3(ShaderEvalContext &ctx)
319 {
320 ctx.color = sequenceSideEffCase3(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0).asInt(),
321 greaterThan(ctx.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f)))
322 .asFloat();
323 }
324
325 enum
326 {
327 MAX_INPUTS = 3
328 };
329
330 enum PrecisionMask
331 {
332 PRECMASK_NA = 0, //!< Precision not applicable (booleans)
333 PRECMASK_LOWP = (1 << PRECISION_LOWP),
334 PRECMASK_MEDIUMP = (1 << PRECISION_MEDIUMP),
335 PRECMASK_HIGHP = (1 << PRECISION_HIGHP),
336
337 PRECMASK_MEDIUMP_HIGHP = (1 << PRECISION_MEDIUMP) | (1 << PRECISION_HIGHP),
338 PRECMASK_ALL = (1 << PRECISION_LOWP) | (1 << PRECISION_MEDIUMP) | (1 << PRECISION_HIGHP)
339 };
340
341 enum ValueType
342 {
343 VALUE_NONE = 0,
344 VALUE_FLOAT = (1 << 0), // float scalar
345 VALUE_FLOAT_VEC = (1 << 1), // float vector
346 VALUE_FLOAT_GENTYPE = (1 << 2), // float scalar/vector
347 VALUE_VEC3 = (1 << 3), // vec3 only
348 VALUE_MATRIX = (1 << 4), // matrix
349 VALUE_BOOL = (1 << 5), // boolean scalar
350 VALUE_BOOL_VEC = (1 << 6), // boolean vector
351 VALUE_BOOL_GENTYPE = (1 << 7), // boolean scalar/vector
352 VALUE_INT = (1 << 8), // int scalar
353 VALUE_INT_VEC = (1 << 9), // int vector
354 VALUE_INT_GENTYPE = (1 << 10), // int scalar/vector
355
356 // Shorthands.
357 F = VALUE_FLOAT,
358 FV = VALUE_FLOAT_VEC,
359 GT = VALUE_FLOAT_GENTYPE,
360 V3 = VALUE_VEC3,
361 M = VALUE_MATRIX,
362 B = VALUE_BOOL,
363 BV = VALUE_BOOL_VEC,
364 BGT = VALUE_BOOL_GENTYPE,
365 I = VALUE_INT,
366 IV = VALUE_INT_VEC,
367 IGT = VALUE_INT_GENTYPE
368 };
369
isScalarType(ValueType type)370 static inline bool isScalarType(ValueType type)
371 {
372 return type == VALUE_FLOAT || type == VALUE_BOOL || type == VALUE_INT;
373 }
374
375 struct Value
376 {
Valuedeqp::gles2::Functional::Value377 Value(ValueType valueType_, float rangeMin_, float rangeMax_)
378 : valueType(valueType_)
379 , rangeMin(rangeMin_)
380 , rangeMax(rangeMax_)
381 {
382 }
383
384 ValueType valueType;
385 float rangeMin;
386 float rangeMax;
387 };
388
389 enum OperationType
390 {
391 FUNCTION = 0,
392 OPERATOR,
393 SIDE_EFFECT_OPERATOR // Test the side-effect (as opposed to the result) of a side-effect operator.
394 };
395
396 struct BuiltinFuncInfo
397 {
BuiltinFuncInfodeqp::gles2::Functional::BuiltinFuncInfo398 BuiltinFuncInfo(const char *caseName_, const char *shaderFuncName_, ValueType outValue_, Value input0_,
399 Value input1_, Value input2_, float resultScale_, float resultBias_, uint32_t precisionMask_,
400 ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
401 ShaderEvalFunc evalFuncVec4_, OperationType type_ = FUNCTION, bool isUnaryPrefix_ = true)
402 : caseName(caseName_)
403 , shaderFuncName(shaderFuncName_)
404 , outValue(outValue_)
405 , input0(input0_)
406 , input1(input1_)
407 , input2(input2_)
408 , resultScale(resultScale_)
409 , resultBias(resultBias_)
410 , precisionMask(precisionMask_)
411 , evalFuncScalar(evalFuncScalar_)
412 , evalFuncVec2(evalFuncVec2_)
413 , evalFuncVec3(evalFuncVec3_)
414 , evalFuncVec4(evalFuncVec4_)
415 , type(type_)
416 , isUnaryPrefix(isUnaryPrefix_)
417 {
418 }
419
420 const char *caseName; //!< Name of case.
421 const char *shaderFuncName; //!< Name in shading language.
422 ValueType outValue;
423 Value input0;
424 Value input1;
425 Value input2;
426 float resultScale;
427 float resultBias;
428 uint32_t precisionMask;
429 ShaderEvalFunc evalFuncScalar;
430 ShaderEvalFunc evalFuncVec2;
431 ShaderEvalFunc evalFuncVec3;
432 ShaderEvalFunc evalFuncVec4;
433 OperationType type;
434 bool isUnaryPrefix; //!< Whether a unary operator is a prefix operator; redundant unless unary.
435 };
436
BuiltinOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,float resultScale_,float resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)437 static inline BuiltinFuncInfo BuiltinOperInfo(const char *caseName_, const char *shaderFuncName_, ValueType outValue_,
438 Value input0_, Value input1_, Value input2_, float resultScale_,
439 float resultBias_, uint32_t precisionMask_,
440 ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_,
441 ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
442 {
443 return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
444 precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, OPERATOR);
445 }
446
447 // For postfix (unary) operators.
BuiltinPostOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,float resultScale_,float resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)448 static inline BuiltinFuncInfo BuiltinPostOperInfo(const char *caseName_, const char *shaderFuncName_,
449 ValueType outValue_, Value input0_, Value input1_, Value input2_,
450 float resultScale_, float resultBias_, uint32_t precisionMask_,
451 ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_,
452 ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
453 {
454 return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
455 precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, OPERATOR,
456 false);
457 }
458
BuiltinSideEffOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,float resultScale_,float resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)459 static inline BuiltinFuncInfo BuiltinSideEffOperInfo(const char *caseName_, const char *shaderFuncName_,
460 ValueType outValue_, Value input0_, Value input1_, Value input2_,
461 float resultScale_, float resultBias_, uint32_t precisionMask_,
462 ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_,
463 ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
464 {
465 return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
466 precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_,
467 SIDE_EFFECT_OPERATOR);
468 }
469
470 // For postfix (unary) operators, testing side-effect.
BuiltinPostSideEffOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,float resultScale_,float resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)471 static inline BuiltinFuncInfo BuiltinPostSideEffOperInfo(const char *caseName_, const char *shaderFuncName_,
472 ValueType outValue_, Value input0_, Value input1_,
473 Value input2_, float resultScale_, float resultBias_,
474 uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_,
475 ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
476 ShaderEvalFunc evalFuncVec4_)
477 {
478 return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
479 precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_,
480 SIDE_EFFECT_OPERATOR, false);
481 }
482
483 // BuiltinFuncGroup
484
485 struct BuiltinFuncGroup
486 {
BuiltinFuncGroupdeqp::gles2::Functional::BuiltinFuncGroup487 BuiltinFuncGroup(const char *name_, const char *description_) : name(name_), description(description_)
488 {
489 }
operator <<deqp::gles2::Functional::BuiltinFuncGroup490 BuiltinFuncGroup &operator<<(const BuiltinFuncInfo &info)
491 {
492 funcInfos.push_back(info);
493 return *this;
494 }
495
496 const char *name;
497 const char *description;
498 std::vector<BuiltinFuncInfo> funcInfos;
499 };
500
501 static const char *s_inSwizzles[MAX_INPUTS][4] = {{"z", "wy", "zxy", "yzwx"},
502 {"x", "yx", "yzx", "wzyx"},
503 {"y", "zy", "wyz", "xwzy"}};
504
505 static const char *s_outSwizzles[] = {"x", "yz", "xyz", "xyzw"};
506
507 // OperatorShaderEvaluator
508
509 class OperatorShaderEvaluator : public ShaderEvaluator
510 {
511 public:
OperatorShaderEvaluator(ShaderEvalFunc evalFunc,float scale,float bias)512 OperatorShaderEvaluator(ShaderEvalFunc evalFunc, float scale, float bias)
513 {
514 m_evalFunc = evalFunc;
515 m_scale = scale;
516 m_bias = bias;
517 }
518
~OperatorShaderEvaluator(void)519 virtual ~OperatorShaderEvaluator(void)
520 {
521 }
522
evaluate(ShaderEvalContext & ctx)523 virtual void evaluate(ShaderEvalContext &ctx)
524 {
525 m_evalFunc(ctx);
526 ctx.color = ctx.color * m_scale + m_bias;
527 }
528
529 private:
530 ShaderEvalFunc m_evalFunc;
531 float m_scale;
532 float m_bias;
533 };
534
535 // Concrete value.
536
537 struct ShaderValue
538 {
ShaderValuedeqp::gles2::Functional::ShaderValue539 ShaderValue(DataType type_, float rangeMin_, float rangeMax_)
540 : type(type_)
541 , rangeMin(rangeMin_)
542 , rangeMax(rangeMax_)
543 {
544 }
545
ShaderValuedeqp::gles2::Functional::ShaderValue546 ShaderValue(void) : type(TYPE_LAST), rangeMin(0.0f), rangeMax(0.0f)
547 {
548 }
549
550 DataType type;
551 float rangeMin;
552 float rangeMax;
553 };
554
555 struct ShaderDataSpec
556 {
ShaderDataSpecdeqp::gles2::Functional::ShaderDataSpec557 ShaderDataSpec(void)
558 : resultScale(1.0f)
559 , resultBias(0.0f)
560 , precision(PRECISION_LAST)
561 , output(TYPE_LAST)
562 , numInputs(0)
563 {
564 }
565
566 float resultScale;
567 float resultBias;
568 Precision precision;
569 DataType output;
570 int numInputs;
571 ShaderValue inputs[MAX_INPUTS];
572 };
573
574 // ShaderOperatorCase
575
576 class ShaderOperatorCase : public ShaderRenderCase
577 {
578 public:
579 ShaderOperatorCase(Context &context, const char *caseName, const char *description, bool isVertexCase,
580 ShaderEvalFunc evalFunc, const char *shaderOp, const ShaderDataSpec &spec);
581 virtual ~ShaderOperatorCase(void);
582
583 private:
584 ShaderOperatorCase(const ShaderOperatorCase &); // not allowed!
585 ShaderOperatorCase &operator=(const ShaderOperatorCase &); // not allowed!
586
587 OperatorShaderEvaluator m_evaluator;
588 };
589
ShaderOperatorCase(Context & context,const char * caseName,const char * description,bool isVertexCase,ShaderEvalFunc evalFunc,const char * shaderOp,const ShaderDataSpec & spec)590 ShaderOperatorCase::ShaderOperatorCase(Context &context, const char *caseName, const char *description,
591 bool isVertexCase, ShaderEvalFunc evalFunc, const char *shaderOp,
592 const ShaderDataSpec &spec)
593 : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), caseName,
594 description, isVertexCase, m_evaluator)
595 , m_evaluator(evalFunc, spec.resultScale, spec.resultBias)
596 {
597 const char *precision = spec.precision != PRECISION_LAST ? getPrecisionName(spec.precision) : DE_NULL;
598 const char *inputPrecision[MAX_INPUTS];
599
600 ostringstream vtx;
601 ostringstream frag;
602 ostringstream &op = isVertexCase ? vtx : frag;
603
604 // Compute precision for inputs.
605 for (int i = 0; i < spec.numInputs; i++)
606 {
607 bool isBoolVal = de::inRange<int>(spec.inputs[i].type, TYPE_BOOL, TYPE_BOOL_VEC4);
608 bool isIntVal = de::inRange<int>(spec.inputs[i].type, TYPE_INT, TYPE_INT_VEC4);
609 // \note Mediump interpolators are used for booleans and lowp ints.
610 Precision prec =
611 isBoolVal || (isIntVal && spec.precision == PRECISION_LOWP) ? PRECISION_MEDIUMP : spec.precision;
612 inputPrecision[i] = getPrecisionName(prec);
613 }
614
615 // Attributes.
616 vtx << "attribute highp vec4 a_position;\n";
617 for (int i = 0; i < spec.numInputs; i++)
618 vtx << "attribute " << inputPrecision[i] << " vec4 a_in" << i << ";\n";
619
620 if (isVertexCase)
621 {
622 vtx << "varying mediump vec4 v_color;\n";
623 frag << "varying mediump vec4 v_color;\n";
624 }
625 else
626 {
627 for (int i = 0; i < spec.numInputs; i++)
628 {
629 vtx << "varying " << inputPrecision[i] << " vec4 v_in" << i << ";\n";
630 frag << "varying " << inputPrecision[i] << " vec4 v_in" << i << ";\n";
631 }
632 }
633
634 vtx << "\n";
635 vtx << "void main()\n";
636 vtx << "{\n";
637 vtx << " gl_Position = a_position;\n";
638
639 frag << "\n";
640 frag << "void main()\n";
641 frag << "{\n";
642
643 // Expression inputs.
644 string prefix = isVertexCase ? "a_" : "v_";
645 for (int i = 0; i < spec.numInputs; i++)
646 {
647 DataType inType = spec.inputs[i].type;
648 int inSize = getDataTypeScalarSize(inType);
649 bool isInt = de::inRange<int>(inType, TYPE_INT, TYPE_INT_VEC4);
650 bool isBool = de::inRange<int>(inType, TYPE_BOOL, TYPE_BOOL_VEC4);
651 const char *typeName = getDataTypeName(inType);
652 const char *swizzle = s_inSwizzles[i][inSize - 1];
653
654 op << "\t";
655 if (precision && !isBool)
656 op << precision << " ";
657
658 op << typeName << " in" << i << " = ";
659
660 if (isBool)
661 {
662 if (inSize == 1)
663 op << "(";
664 else
665 op << "greaterThan(";
666 }
667 else if (isInt)
668 op << typeName << "(";
669
670 op << prefix << "in" << i << "." << swizzle;
671
672 if (isBool)
673 {
674 if (inSize == 1)
675 op << " > 0.0)";
676 else
677 op << ", vec" << inSize << "(0.0))";
678 }
679 else if (isInt)
680 op << ")";
681
682 op << ";\n";
683 }
684
685 // Result variable.
686 {
687 const char *outTypeName = getDataTypeName(spec.output);
688 bool isBoolOut = de::inRange<int>(spec.output, TYPE_BOOL, TYPE_BOOL_VEC4);
689
690 op << "\t";
691 if (precision && !isBoolOut)
692 op << precision << " ";
693 op << outTypeName << " res = " << outTypeName << "(0.0);\n\n";
694 }
695
696 // Expression.
697 op << "\t" << shaderOp << "\n\n";
698
699 // Convert to color.
700 bool isResFloatVec = de::inRange<int>(spec.output, TYPE_FLOAT, TYPE_FLOAT_VEC4);
701 int outScalarSize = getDataTypeScalarSize(spec.output);
702
703 op << "\tmediump vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n";
704 op << "\tcolor." << s_outSwizzles[outScalarSize - 1] << " = ";
705
706 if (!isResFloatVec && outScalarSize == 1)
707 op << "float(res)";
708 else if (!isResFloatVec)
709 op << "vec" << outScalarSize << "(res)";
710 else
711 op << "res";
712
713 op << ";\n";
714
715 // Scale & bias.
716 float resultScale = spec.resultScale;
717 float resultBias = spec.resultBias;
718 if ((resultScale != 1.0f) || (resultBias != 0.0f))
719 {
720 op << "\tcolor = color";
721 if (resultScale != 1.0f)
722 op << " * " << de::floatToString(resultScale, 2);
723 if (resultBias != 0.0f)
724 op << " + " << de::floatToString(resultBias, 2);
725 op << ";\n";
726 }
727
728 // ..
729 if (isVertexCase)
730 {
731 vtx << " v_color = color;\n";
732 frag << " gl_FragColor = v_color;\n";
733 }
734 else
735 {
736 for (int i = 0; i < spec.numInputs; i++)
737 vtx << " v_in" << i << " = a_in" << i << ";\n";
738 frag << " gl_FragColor = color;\n";
739 }
740
741 vtx << "}\n";
742 frag << "}\n";
743
744 m_vertShaderSource = vtx.str();
745 m_fragShaderSource = frag.str();
746
747 // Setup the user attributes.
748 m_userAttribTransforms.resize(spec.numInputs);
749 for (int inputNdx = 0; inputNdx < spec.numInputs; inputNdx++)
750 {
751 const ShaderValue &v = spec.inputs[inputNdx];
752 DE_ASSERT(v.type != TYPE_LAST);
753
754 float scale = (v.rangeMax - v.rangeMin);
755 float minBias = v.rangeMin;
756 float maxBias = v.rangeMax;
757 Mat4 attribMatrix;
758
759 for (int rowNdx = 0; rowNdx < 4; rowNdx++)
760 {
761 Vec4 row;
762
763 switch ((rowNdx + inputNdx) % 4)
764 {
765 case 0:
766 row = Vec4(scale, 0.0f, 0.0f, minBias);
767 break;
768 case 1:
769 row = Vec4(0.0f, scale, 0.0f, minBias);
770 break;
771 case 2:
772 row = Vec4(-scale, 0.0f, 0.0f, maxBias);
773 break;
774 case 3:
775 row = Vec4(0.0f, -scale, 0.0f, maxBias);
776 break;
777 default:
778 DE_ASSERT(false);
779 }
780
781 attribMatrix.setRow(rowNdx, row);
782 }
783
784 m_userAttribTransforms[inputNdx] = attribMatrix;
785 }
786 }
787
~ShaderOperatorCase(void)788 ShaderOperatorCase::~ShaderOperatorCase(void)
789 {
790 }
791
792 // ShaderOperatorTests.
793
ShaderOperatorTests(Context & context)794 ShaderOperatorTests::ShaderOperatorTests(Context &context) : TestCaseGroup(context, "operator", "Operator tests.")
795 {
796 }
797
~ShaderOperatorTests(void)798 ShaderOperatorTests::~ShaderOperatorTests(void)
799 {
800 }
801
802 // Vector math functions.
803 template <typename T>
nop(T f)804 inline T nop(T f)
805 {
806 return f;
807 }
808
809 template <typename T, int Size>
nop(const Vector<T,Size> & v)810 Vector<T, Size> nop(const Vector<T, Size> &v)
811 {
812 return v;
813 }
814
815 #define DECLARE_UNARY_GENTYPE_FUNCS(FUNC_NAME) \
816 void eval_##FUNC_NAME##_float(ShaderEvalContext &c) \
817 { \
818 c.color.x() = FUNC_NAME(c.in[0].swizzle(2)).x(); \
819 } \
820 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
821 { \
822 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1)); \
823 } \
824 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
825 { \
826 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1)); \
827 } \
828 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
829 { \
830 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0)); \
831 }
832
833 #define DECLARE_BINARY_GENTYPE_FUNCS(FUNC_NAME) \
834 void eval_##FUNC_NAME##_float(ShaderEvalContext &c) \
835 { \
836 c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0)).x(); \
837 } \
838 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
839 { \
840 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0)); \
841 } \
842 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
843 { \
844 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)); \
845 } \
846 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
847 { \
848 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); \
849 }
850
851 #define DECLARE_TERNARY_GENTYPE_FUNCS(FUNC_NAME) \
852 void eval_##FUNC_NAME##_float(ShaderEvalContext &c) \
853 { \
854 c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0), c.in[2].swizzle(1)).x(); \
855 } \
856 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
857 { \
858 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0), c.in[2].swizzle(2, 1)); \
859 } \
860 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
861 { \
862 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0), c.in[2].swizzle(3, 1, 2)); \
863 } \
864 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
865 { \
866 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0), c.in[2].swizzle(0, 3, 2, 1)); \
867 }
868
869 #define DECLARE_UNARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME) \
870 void eval_##FUNC_NAME##_float(ShaderEvalContext &c) \
871 { \
872 c.color.x() = FUNC_NAME(c.in[0].swizzle(2)); \
873 } \
874 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
875 { \
876 c.color.x() = FUNC_NAME(c.in[0].swizzle(3, 1)); \
877 } \
878 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
879 { \
880 c.color.x() = FUNC_NAME(c.in[0].swizzle(2, 0, 1)); \
881 } \
882 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
883 { \
884 c.color.x() = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0)); \
885 }
886
887 #define DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME) \
888 void eval_##FUNC_NAME##_float(ShaderEvalContext &c) \
889 { \
890 c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0)); \
891 } \
892 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
893 { \
894 c.color.x() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0)); \
895 } \
896 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
897 { \
898 c.color.x() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)); \
899 } \
900 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
901 { \
902 c.color.x() = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); \
903 }
904
905 #define DECLARE_BINARY_BOOL_FUNCS(FUNC_NAME) \
906 void eval_##FUNC_NAME##_bool(ShaderEvalContext &c) \
907 { \
908 c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f); \
909 }
910
911 #define DECLARE_UNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME) \
912 void eval_##FUNC_NAME##_bool(ShaderEvalContext &c) \
913 { \
914 c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f); \
915 } \
916 void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c) \
917 { \
918 c.color.yz() = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat(); \
919 } \
920 void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c) \
921 { \
922 c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat(); \
923 } \
924 void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c) \
925 { \
926 c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f))).asFloat(); \
927 }
928
929 #define DECLARE_TERNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME) \
930 void eval_##FUNC_NAME##_bool(ShaderEvalContext &c) \
931 { \
932 c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f, c.in[2].y() > 0.0f); \
933 } \
934 void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c) \
935 { \
936 c.color.yz() = \
937 FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)), greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f)), \
938 greaterThan(c.in[2].swizzle(2, 1), Vec2(0.0f))) \
939 .asFloat(); \
940 } \
941 void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c) \
942 { \
943 c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)), \
944 greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f)), \
945 greaterThan(c.in[2].swizzle(3, 1, 2), Vec3(0.0f))) \
946 .asFloat(); \
947 } \
948 void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c) \
949 { \
950 c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)), \
951 greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f)), \
952 greaterThan(c.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f))) \
953 .asFloat(); \
954 }
955
956 #define DECLARE_UNARY_INT_GENTYPE_FUNCS(FUNC_NAME) \
957 void eval_##FUNC_NAME##_int(ShaderEvalContext &c) \
958 { \
959 c.color.x() = (float)FUNC_NAME((int)c.in[0].z()); \
960 } \
961 void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c) \
962 { \
963 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt()).asFloat(); \
964 } \
965 void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c) \
966 { \
967 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt()).asFloat(); \
968 } \
969 void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c) \
970 { \
971 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt()).asFloat(); \
972 }
973
974 #define DECLARE_BINARY_INT_GENTYPE_FUNCS(FUNC_NAME) \
975 void eval_##FUNC_NAME##_int(ShaderEvalContext &c) \
976 { \
977 c.color.x() = (float)tcu::FUNC_NAME((int)c.in[0].z(), (int)c.in[1].x()); \
978 } \
979 void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c) \
980 { \
981 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), c.in[1].swizzle(1, 0).asInt()).asFloat(); \
982 } \
983 void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c) \
984 { \
985 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
986 } \
987 void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c) \
988 { \
989 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); \
990 }
991
992 #define DECLARE_TERNARY_INT_GENTYPE_FUNCS(FUNC_NAME) \
993 void eval_##FUNC_NAME##_int(ShaderEvalContext &c) \
994 { \
995 c.color.x() = (float)FUNC_NAME((int)c.in[0].z(), (int)c.in[1].x(), (int)c.in[2].y()); \
996 } \
997 void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c) \
998 { \
999 c.color.yz() = \
1000 FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), c.in[1].swizzle(1, 0).asInt(), c.in[2].swizzle(2, 1).asInt()) \
1001 .asFloat(); \
1002 } \
1003 void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c) \
1004 { \
1005 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), c.in[1].swizzle(1, 2, 0).asInt(), \
1006 c.in[2].swizzle(3, 1, 2).asInt()) \
1007 .asFloat(); \
1008 } \
1009 void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c) \
1010 { \
1011 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), c.in[1].swizzle(3, 2, 1, 0).asInt(), \
1012 c.in[2].swizzle(0, 3, 2, 1).asInt()) \
1013 .asFloat(); \
1014 }
1015
1016 #define DECLARE_VEC_FLOAT_FUNCS(FUNC_NAME) \
1017 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
1018 { \
1019 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].x()); \
1020 } \
1021 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
1022 { \
1023 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].x()); \
1024 } \
1025 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
1026 { \
1027 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].x()); \
1028 }
1029
1030 #define DECLARE_VEC_FLOAT_FLOAT_FUNCS(FUNC_NAME) \
1031 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
1032 { \
1033 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].x(), c.in[2].y()); \
1034 } \
1035 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
1036 { \
1037 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].x(), c.in[2].y()); \
1038 } \
1039 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
1040 { \
1041 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].x(), c.in[2].y()); \
1042 }
1043
1044 #define DECLARE_VEC_VEC_FLOAT_FUNCS(FUNC_NAME) \
1045 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
1046 { \
1047 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0), c.in[2].y()); \
1048 } \
1049 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
1050 { \
1051 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0), c.in[2].y()); \
1052 } \
1053 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
1054 { \
1055 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0), c.in[2].y()); \
1056 }
1057
1058 #define DECLARE_FLOAT_FLOAT_VEC_FUNCS(FUNC_NAME) \
1059 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
1060 { \
1061 c.color.yz() = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(2, 1)); \
1062 } \
1063 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
1064 { \
1065 c.color.xyz() = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(3, 1, 2)); \
1066 } \
1067 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
1068 { \
1069 c.color = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(0, 3, 2, 1)); \
1070 }
1071
1072 #define DECLARE_FLOAT_VEC_FUNCS(FUNC_NAME) \
1073 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
1074 { \
1075 c.color.yz() = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(1, 0)); \
1076 } \
1077 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
1078 { \
1079 c.color.xyz() = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(1, 2, 0)); \
1080 } \
1081 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
1082 { \
1083 c.color = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0)); \
1084 }
1085
1086 #define DECLARE_IVEC_INT_FUNCS(FUNC_NAME) \
1087 void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c) \
1088 { \
1089 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), (int)c.in[1].x()).asFloat(); \
1090 } \
1091 void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c) \
1092 { \
1093 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), (int)c.in[1].x()).asFloat(); \
1094 } \
1095 void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c) \
1096 { \
1097 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), (int)c.in[1].x()).asFloat(); \
1098 }
1099
1100 #define DECLARE_INT_IVEC_FUNCS(FUNC_NAME) \
1101 void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c) \
1102 { \
1103 c.color.yz() = FUNC_NAME((int)c.in[0].z(), c.in[1].swizzle(1, 0).asInt()).asFloat(); \
1104 } \
1105 void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c) \
1106 { \
1107 c.color.xyz() = FUNC_NAME((int)c.in[0].z(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
1108 } \
1109 void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c) \
1110 { \
1111 c.color = FUNC_NAME((int)c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); \
1112 }
1113
1114 // Operators.
1115
1116 DECLARE_UNARY_GENTYPE_FUNCS(nop)
DECLARE_UNARY_GENTYPE_FUNCS(negate)1117 DECLARE_UNARY_GENTYPE_FUNCS(negate)
1118 DECLARE_UNARY_GENTYPE_FUNCS(addOne)
1119 DECLARE_UNARY_GENTYPE_FUNCS(subOne)
1120 DECLARE_BINARY_GENTYPE_FUNCS(add)
1121 DECLARE_BINARY_GENTYPE_FUNCS(sub)
1122 DECLARE_BINARY_GENTYPE_FUNCS(mul)
1123 DECLARE_BINARY_GENTYPE_FUNCS(div)
1124
1125 void eval_selection_float(ShaderEvalContext &c)
1126 {
1127 c.color.x() = selection(c.in[0].z() > 0.0f, c.in[1].x(), c.in[2].y());
1128 }
eval_selection_vec2(ShaderEvalContext & c)1129 void eval_selection_vec2(ShaderEvalContext &c)
1130 {
1131 c.color.yz() = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 0), c.in[2].swizzle(2, 1));
1132 }
eval_selection_vec3(ShaderEvalContext & c)1133 void eval_selection_vec3(ShaderEvalContext &c)
1134 {
1135 c.color.xyz() = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 2, 0), c.in[2].swizzle(3, 1, 2));
1136 }
eval_selection_vec4(ShaderEvalContext & c)1137 void eval_selection_vec4(ShaderEvalContext &c)
1138 {
1139 c.color = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(3, 2, 1, 0), c.in[2].swizzle(0, 3, 2, 1));
1140 }
1141
1142 DECLARE_UNARY_INT_GENTYPE_FUNCS(nop)
DECLARE_UNARY_INT_GENTYPE_FUNCS(negate)1143 DECLARE_UNARY_INT_GENTYPE_FUNCS(negate)
1144 DECLARE_UNARY_INT_GENTYPE_FUNCS(addOne)
1145 DECLARE_UNARY_INT_GENTYPE_FUNCS(subOne)
1146 DECLARE_BINARY_INT_GENTYPE_FUNCS(add)
1147 DECLARE_BINARY_INT_GENTYPE_FUNCS(sub)
1148 DECLARE_BINARY_INT_GENTYPE_FUNCS(mul)
1149 DECLARE_BINARY_INT_GENTYPE_FUNCS(div)
1150
1151 void eval_selection_int(ShaderEvalContext &c)
1152 {
1153 c.color.x() = (float)selection(c.in[0].z() > 0.0f, (int)c.in[1].x(), (int)c.in[2].y());
1154 }
eval_selection_ivec2(ShaderEvalContext & c)1155 void eval_selection_ivec2(ShaderEvalContext &c)
1156 {
1157 c.color.yz() =
1158 selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 0).asInt(), c.in[2].swizzle(2, 1).asInt()).asFloat();
1159 }
eval_selection_ivec3(ShaderEvalContext & c)1160 void eval_selection_ivec3(ShaderEvalContext &c)
1161 {
1162 c.color.xyz() =
1163 selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 2, 0).asInt(), c.in[2].swizzle(3, 1, 2).asInt()).asFloat();
1164 }
eval_selection_ivec4(ShaderEvalContext & c)1165 void eval_selection_ivec4(ShaderEvalContext &c)
1166 {
1167 c.color = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(3, 2, 1, 0).asInt(), c.in[2].swizzle(0, 3, 2, 1).asInt())
1168 .asFloat();
1169 }
1170
1171 DECLARE_UNARY_BOOL_GENTYPE_FUNCS(boolNot)
DECLARE_BINARY_BOOL_FUNCS(logicalAnd)1172 DECLARE_BINARY_BOOL_FUNCS(logicalAnd)
1173 DECLARE_BINARY_BOOL_FUNCS(logicalOr)
1174 DECLARE_BINARY_BOOL_FUNCS(logicalXor)
1175
1176 void eval_selection_bool(ShaderEvalContext &c)
1177 {
1178 c.color.x() = (float)selection(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f, c.in[2].y() > 0.0f);
1179 }
eval_selection_bvec2(ShaderEvalContext & c)1180 void eval_selection_bvec2(ShaderEvalContext &c)
1181 {
1182 c.color.yz() = selection(c.in[0].z() > 0.0f, greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f, 0.0f)),
1183 greaterThan(c.in[2].swizzle(2, 1), Vec2(0.0f, 0.0f)))
1184 .asFloat();
1185 }
eval_selection_bvec3(ShaderEvalContext & c)1186 void eval_selection_bvec3(ShaderEvalContext &c)
1187 {
1188 c.color.xyz() = selection(c.in[0].z() > 0.0f, greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f, 0.0f, 0.0f)),
1189 greaterThan(c.in[2].swizzle(3, 1, 2), Vec3(0.0f, 0.0f, 0.0f)))
1190 .asFloat();
1191 }
eval_selection_bvec4(ShaderEvalContext & c)1192 void eval_selection_bvec4(ShaderEvalContext &c)
1193 {
1194 c.color = selection(c.in[0].z() > 0.0f, greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f, 0.0f, 0.0f, 0.0f)),
1195 greaterThan(c.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f)))
1196 .asFloat();
1197 }
1198
1199 DECLARE_VEC_FLOAT_FUNCS(addVecScalar)
DECLARE_VEC_FLOAT_FUNCS(subVecScalar)1200 DECLARE_VEC_FLOAT_FUNCS(subVecScalar)
1201 DECLARE_VEC_FLOAT_FUNCS(mulVecScalar)
1202 DECLARE_VEC_FLOAT_FUNCS(divVecScalar)
1203
1204 DECLARE_FLOAT_VEC_FUNCS(addScalarVec)
1205 DECLARE_FLOAT_VEC_FUNCS(subScalarVec)
1206 DECLARE_FLOAT_VEC_FUNCS(mulScalarVec)
1207 DECLARE_FLOAT_VEC_FUNCS(divScalarVec)
1208
1209 DECLARE_IVEC_INT_FUNCS(addVecScalar)
1210 DECLARE_IVEC_INT_FUNCS(subVecScalar)
1211 DECLARE_IVEC_INT_FUNCS(mulVecScalar)
1212 DECLARE_IVEC_INT_FUNCS(divVecScalar)
1213
1214 DECLARE_INT_IVEC_FUNCS(addScalarVec)
1215 DECLARE_INT_IVEC_FUNCS(subScalarVec)
1216 DECLARE_INT_IVEC_FUNCS(mulScalarVec)
1217 DECLARE_INT_IVEC_FUNCS(divScalarVec)
1218
1219 // Built-in functions.
1220
1221 DECLARE_UNARY_GENTYPE_FUNCS(radians)
1222 DECLARE_UNARY_GENTYPE_FUNCS(degrees)
1223 DECLARE_UNARY_GENTYPE_FUNCS(sin)
1224 DECLARE_UNARY_GENTYPE_FUNCS(cos)
1225 DECLARE_UNARY_GENTYPE_FUNCS(tan)
1226 DECLARE_UNARY_GENTYPE_FUNCS(asin)
1227 DECLARE_UNARY_GENTYPE_FUNCS(acos)
1228 DECLARE_UNARY_GENTYPE_FUNCS(atan)
1229 DECLARE_BINARY_GENTYPE_FUNCS(atan2)
1230
1231 DECLARE_BINARY_GENTYPE_FUNCS(pow)
1232 DECLARE_UNARY_GENTYPE_FUNCS(exp)
1233 DECLARE_UNARY_GENTYPE_FUNCS(log)
1234 DECLARE_UNARY_GENTYPE_FUNCS(exp2)
1235 DECLARE_UNARY_GENTYPE_FUNCS(log2)
1236 DECLARE_UNARY_GENTYPE_FUNCS(sqrt)
1237 DECLARE_UNARY_GENTYPE_FUNCS(inverseSqrt)
1238
1239 DECLARE_UNARY_GENTYPE_FUNCS(abs)
1240 DECLARE_UNARY_GENTYPE_FUNCS(sign)
1241 DECLARE_UNARY_GENTYPE_FUNCS(floor)
1242 DECLARE_UNARY_GENTYPE_FUNCS(ceil)
1243 DECLARE_UNARY_GENTYPE_FUNCS(fract)
1244 DECLARE_BINARY_GENTYPE_FUNCS(mod)
1245 DECLARE_VEC_FLOAT_FUNCS(modVecFloat)
1246 DECLARE_BINARY_GENTYPE_FUNCS(min)
1247 DECLARE_VEC_FLOAT_FUNCS(minVecFloat)
1248 DECLARE_BINARY_GENTYPE_FUNCS(max)
1249 DECLARE_VEC_FLOAT_FUNCS(maxVecFloat)
1250 DECLARE_TERNARY_GENTYPE_FUNCS(clamp)
1251 DECLARE_VEC_FLOAT_FLOAT_FUNCS(clampVecFloatFloat)
1252 DECLARE_TERNARY_GENTYPE_FUNCS(mix)
1253 DECLARE_VEC_VEC_FLOAT_FUNCS(mixVecVecFloat)
1254 DECLARE_BINARY_GENTYPE_FUNCS(step)
1255 DECLARE_FLOAT_VEC_FUNCS(stepFloatVec)
1256 DECLARE_TERNARY_GENTYPE_FUNCS(smoothStep)
1257 DECLARE_FLOAT_FLOAT_VEC_FUNCS(smoothStepFloatFloatVec)
1258
1259 DECLARE_UNARY_SCALAR_GENTYPE_FUNCS(length)
1260 DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(distance)
1261 DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(dot)
1262 void eval_cross_vec3(ShaderEvalContext &c)
1263 {
1264 c.color.xyz() = cross(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0));
1265 }
1266
1267 DECLARE_UNARY_GENTYPE_FUNCS(normalize)
DECLARE_TERNARY_GENTYPE_FUNCS(faceForward)1268 DECLARE_TERNARY_GENTYPE_FUNCS(faceForward)
1269 DECLARE_BINARY_GENTYPE_FUNCS(reflect)
1270
1271 void eval_refract_float(ShaderEvalContext &c)
1272 {
1273 c.color.x() = refract(c.in[0].z(), c.in[1].x(), c.in[2].y());
1274 }
eval_refract_vec2(ShaderEvalContext & c)1275 void eval_refract_vec2(ShaderEvalContext &c)
1276 {
1277 c.color.yz() = refract(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0), c.in[2].y());
1278 }
eval_refract_vec3(ShaderEvalContext & c)1279 void eval_refract_vec3(ShaderEvalContext &c)
1280 {
1281 c.color.xyz() = refract(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0), c.in[2].y());
1282 }
eval_refract_vec4(ShaderEvalContext & c)1283 void eval_refract_vec4(ShaderEvalContext &c)
1284 {
1285 c.color = refract(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0), c.in[2].y());
1286 }
1287
1288 // Compare functions.
1289
1290 #define DECLARE_FLOAT_COMPARE_FUNCS(FUNC_NAME) \
1291 void eval_##FUNC_NAME##_float(ShaderEvalContext &c) \
1292 { \
1293 c.color.x() = (float)FUNC_NAME(c.in[0].z(), c.in[1].x()); \
1294 } \
1295 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
1296 { \
1297 c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0)); \
1298 } \
1299 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
1300 { \
1301 c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)); \
1302 } \
1303 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
1304 { \
1305 c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); \
1306 }
1307
1308 #define DECLARE_FLOAT_CWISE_COMPARE_FUNCS(FUNC_NAME) \
1309 void eval_##FUNC_NAME##_float(ShaderEvalContext &c) \
1310 { \
1311 c.color.x() = (float)FUNC_NAME(c.in[0].z(), c.in[1].x()); \
1312 } \
1313 void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c) \
1314 { \
1315 c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0)).asFloat(); \
1316 } \
1317 void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c) \
1318 { \
1319 c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)).asFloat(); \
1320 } \
1321 void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c) \
1322 { \
1323 c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)).asFloat(); \
1324 }
1325
1326 #define DECLARE_INT_COMPARE_FUNCS(FUNC_NAME) \
1327 void eval_##FUNC_NAME##_int(ShaderEvalContext &c) \
1328 { \
1329 c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x())); \
1330 } \
1331 void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c) \
1332 { \
1333 c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].swizzle(3, 1)), chopToInt(c.in[1].swizzle(1, 0))); \
1334 } \
1335 void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c) \
1336 { \
1337 c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].swizzle(2, 0, 1)), chopToInt(c.in[1].swizzle(1, 2, 0))); \
1338 } \
1339 void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c) \
1340 { \
1341 c.color.x() = \
1342 (float)FUNC_NAME(chopToInt(c.in[0].swizzle(1, 2, 3, 0)), chopToInt(c.in[1].swizzle(3, 2, 1, 0))); \
1343 }
1344
1345 #define DECLARE_INT_CWISE_COMPARE_FUNCS(FUNC_NAME) \
1346 void eval_##FUNC_NAME##_int(ShaderEvalContext &c) \
1347 { \
1348 c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x())); \
1349 } \
1350 void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c) \
1351 { \
1352 c.color.yz() = FUNC_NAME(chopToInt(c.in[0].swizzle(3, 1)), chopToInt(c.in[1].swizzle(1, 0))).asFloat(); \
1353 } \
1354 void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c) \
1355 { \
1356 c.color.xyz() = FUNC_NAME(chopToInt(c.in[0].swizzle(2, 0, 1)), chopToInt(c.in[1].swizzle(1, 2, 0))).asFloat(); \
1357 } \
1358 void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c) \
1359 { \
1360 c.color = FUNC_NAME(chopToInt(c.in[0].swizzle(1, 2, 3, 0)), chopToInt(c.in[1].swizzle(3, 2, 1, 0))).asFloat(); \
1361 }
1362
1363 #define DECLARE_BOOL_COMPARE_FUNCS(FUNC_NAME) \
1364 void eval_##FUNC_NAME##_bool(ShaderEvalContext &c) \
1365 { \
1366 c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f); \
1367 } \
1368 void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c) \
1369 { \
1370 c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)), \
1371 greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f))); \
1372 } \
1373 void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c) \
1374 { \
1375 c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)), \
1376 greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f))); \
1377 } \
1378 void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c) \
1379 { \
1380 c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)), \
1381 greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f))); \
1382 }
1383
1384 #define DECLARE_BOOL_CWISE_COMPARE_FUNCS(FUNC_NAME) \
1385 void eval_##FUNC_NAME##_bool(ShaderEvalContext &c) \
1386 { \
1387 c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f); \
1388 } \
1389 void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c) \
1390 { \
1391 c.color.yz() = \
1392 FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)), greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f))) \
1393 .asFloat(); \
1394 } \
1395 void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c) \
1396 { \
1397 c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)), \
1398 greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f))) \
1399 .asFloat(); \
1400 } \
1401 void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c) \
1402 { \
1403 c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)), \
1404 greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f))) \
1405 .asFloat(); \
1406 }
1407
1408 DECLARE_FLOAT_COMPARE_FUNCS(allEqual)
DECLARE_FLOAT_COMPARE_FUNCS(anyNotEqual)1409 DECLARE_FLOAT_COMPARE_FUNCS(anyNotEqual)
1410 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThan)
1411 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThanEqual)
1412 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThan)
1413 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThanEqual)
1414 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(equal)
1415 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(notEqual)
1416
1417 DECLARE_INT_COMPARE_FUNCS(allEqual)
1418 DECLARE_INT_COMPARE_FUNCS(anyNotEqual)
1419 DECLARE_INT_CWISE_COMPARE_FUNCS(lessThan)
1420 DECLARE_INT_CWISE_COMPARE_FUNCS(lessThanEqual)
1421 DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThan)
1422 DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThanEqual)
1423 DECLARE_INT_CWISE_COMPARE_FUNCS(equal)
1424 DECLARE_INT_CWISE_COMPARE_FUNCS(notEqual)
1425
1426 DECLARE_BOOL_COMPARE_FUNCS(allEqual)
1427 DECLARE_BOOL_COMPARE_FUNCS(anyNotEqual)
1428 DECLARE_BOOL_CWISE_COMPARE_FUNCS(equal)
1429 DECLARE_BOOL_CWISE_COMPARE_FUNCS(notEqual)
1430
1431 // Boolean functions.
1432
1433 #define DECLARE_UNARY_SCALAR_BVEC_FUNCS(GLSL_NAME, FUNC_NAME) \
1434 void eval_##GLSL_NAME##_bvec2(ShaderEvalContext &c) \
1435 { \
1436 c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)))); \
1437 } \
1438 void eval_##GLSL_NAME##_bvec3(ShaderEvalContext &c) \
1439 { \
1440 c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)))); \
1441 } \
1442 void eval_##GLSL_NAME##_bvec4(ShaderEvalContext &c) \
1443 { \
1444 c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)))); \
1445 }
1446
1447 #define DECLARE_UNARY_BVEC_BVEC_FUNCS(GLSL_NAME, FUNC_NAME) \
1448 void eval_##GLSL_NAME##_bvec2(ShaderEvalContext &c) \
1449 { \
1450 c.color.yz() = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat(); \
1451 } \
1452 void eval_##GLSL_NAME##_bvec3(ShaderEvalContext &c) \
1453 { \
1454 c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat(); \
1455 } \
1456 void eval_##GLSL_NAME##_bvec4(ShaderEvalContext &c) \
1457 { \
1458 c.color.xyzw() = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f))).asFloat(); \
1459 }
1460
1461 DECLARE_UNARY_SCALAR_BVEC_FUNCS(any, boolAny)
1462 DECLARE_UNARY_SCALAR_BVEC_FUNCS(all, boolAll)
1463
1464 void ShaderOperatorTests::init(void)
1465 {
1466 // Requisites:
1467 // - input types (const, uniform, dynamic, mixture)
1468 // - data types (bool, int, float, vecs, mats)
1469 // -
1470 // - complex expressions (\todo [petri] move to expressions?)
1471 // * early-exit from side effects
1472 // * precedence
1473
1474 // unary plus, minus
1475 // add, sub
1476 // mul (larger range)
1477 // div (div-by-zero)
1478 // incr, decr (int only)
1479 // relational
1480 // equality
1481 // logical
1482 // selection
1483 // assignment
1484 // arithmetic assignment
1485
1486 // parenthesis
1487 // sequence
1488 // subscript, function call, field selector/swizzler
1489
1490 // precedence
1491 // data types (float, int, bool, vecs, matrices)
1492
1493 // TestCaseGroup* group = new TestCaseGroup(m_testCtx, "additive", "Additive operator tests.");
1494 // addChild(group);
1495
1496 // * * *
1497
1498 // Built-in functions
1499 // - precision, data types
1500
1501 #define BOOL_FUNCS(FUNC_NAME) eval_##FUNC_NAME##_bool, DE_NULL, DE_NULL, DE_NULL
1502
1503 #define FLOAT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
1504 #define INT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
1505 #define BOOL_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
1506
1507 #define FLOAT_GENTYPE_FUNCS(FUNC_NAME) \
1508 eval_##FUNC_NAME##_float, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
1509 #define INT_GENTYPE_FUNCS(FUNC_NAME) \
1510 eval_##FUNC_NAME##_int, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
1511 #define BOOL_GENTYPE_FUNCS(FUNC_NAME) \
1512 eval_##FUNC_NAME##_bool, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
1513
1514 Value notUsed = Value(VALUE_NONE, 0.0f, 0.0f);
1515
1516 std::vector<BuiltinFuncGroup> funcInfoGroups;
1517
1518 // Unary operators.
1519 funcInfoGroups.push_back(
1520 BuiltinFuncGroup("unary_operator", "Unary operator tests")
1521 << BuiltinOperInfo("plus", "+", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL,
1522 FLOAT_GENTYPE_FUNCS(nop))
1523 << BuiltinOperInfo("plus", "+", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL,
1524 INT_GENTYPE_FUNCS(nop))
1525 << BuiltinOperInfo("minus", "-", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL,
1526 FLOAT_GENTYPE_FUNCS(negate))
1527 << BuiltinOperInfo("minus", "-", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL,
1528 INT_GENTYPE_FUNCS(negate))
1529 << BuiltinOperInfo("not", "!", B, Value(B, -1.0f, 1.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_NA,
1530 eval_boolNot_bool, DE_NULL, DE_NULL, DE_NULL)
1531
1532 // Pre/post incr/decr side effect cases.
1533 << BuiltinSideEffOperInfo("pre_increment_effect", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
1534 0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
1535 << BuiltinSideEffOperInfo("pre_increment_effect", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed, 0.1f,
1536 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
1537 << BuiltinSideEffOperInfo("pre_decrement_effect", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
1538 1.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
1539 << BuiltinSideEffOperInfo("pre_decrement_effect", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed, 0.1f,
1540 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
1541 << BuiltinPostSideEffOperInfo("post_increment_effect", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
1542 0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
1543 << BuiltinPostSideEffOperInfo("post_increment_effect", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed,
1544 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
1545 << BuiltinPostSideEffOperInfo("post_decrement_effect", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
1546 1.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
1547 << BuiltinPostSideEffOperInfo("post_decrement_effect", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed,
1548 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
1549
1550 // Pre/post incr/decr result cases.
1551 << BuiltinOperInfo("pre_increment_result", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.0f,
1552 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
1553 << BuiltinOperInfo("pre_increment_result", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed, 0.1f, 0.5f,
1554 PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
1555 << BuiltinOperInfo("pre_decrement_result", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 1.0f,
1556 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
1557 << BuiltinOperInfo("pre_decrement_result", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed, 0.1f, 0.5f,
1558 PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
1559 << BuiltinPostOperInfo("post_increment_result", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f,
1560 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(nop))
1561 << BuiltinPostOperInfo("post_increment_result", "++", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f,
1562 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(nop))
1563 << BuiltinPostOperInfo("post_decrement_result", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f,
1564 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(nop))
1565 << BuiltinPostOperInfo("post_decrement_result", "--", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f,
1566 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(nop)));
1567
1568 // Binary operators.
1569 funcInfoGroups.push_back(
1570 BuiltinFuncGroup("binary_operator", "Binary operator tests")
1571 // Arithmetic operators.
1572 << BuiltinOperInfo("add", "+", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1573 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(add))
1574 << BuiltinOperInfo("add", "+", IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed, 0.1f, 0.5f,
1575 PRECMASK_ALL, INT_GENTYPE_FUNCS(add))
1576 << BuiltinOperInfo("add", "+", FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1577 PRECMASK_ALL, FLOAT_VEC_FUNCS(addVecScalar))
1578 << BuiltinOperInfo("add", "+", IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f, 0.5f,
1579 PRECMASK_ALL, INT_VEC_FUNCS(addVecScalar))
1580 << BuiltinOperInfo("add", "+", FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1581 PRECMASK_ALL, FLOAT_VEC_FUNCS(addScalarVec))
1582 << BuiltinOperInfo("add", "+", IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed, 0.1f, 0.5f,
1583 PRECMASK_ALL, INT_VEC_FUNCS(addScalarVec))
1584 << BuiltinOperInfo("sub", "-", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1585 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(sub))
1586 << BuiltinOperInfo("sub", "-", IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed, 0.1f, 0.5f,
1587 PRECMASK_ALL, INT_GENTYPE_FUNCS(sub))
1588 << BuiltinOperInfo("sub", "-", FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1589 PRECMASK_ALL, FLOAT_VEC_FUNCS(subVecScalar))
1590 << BuiltinOperInfo("sub", "-", IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f, 0.5f,
1591 PRECMASK_ALL, INT_VEC_FUNCS(subVecScalar))
1592 << BuiltinOperInfo("sub", "-", FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1593 PRECMASK_ALL, FLOAT_VEC_FUNCS(subScalarVec))
1594 << BuiltinOperInfo("sub", "-", IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed, 0.1f, 0.5f,
1595 PRECMASK_ALL, INT_VEC_FUNCS(subScalarVec))
1596 << BuiltinOperInfo("mul", "*", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1597 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(mul))
1598 << BuiltinOperInfo("mul", "*", IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed, 0.1f, 0.5f,
1599 PRECMASK_ALL, INT_GENTYPE_FUNCS(mul))
1600 << BuiltinOperInfo("mul", "*", FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1601 PRECMASK_ALL, FLOAT_VEC_FUNCS(mulVecScalar))
1602 << BuiltinOperInfo("mul", "*", IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f, 0.5f,
1603 PRECMASK_ALL, INT_VEC_FUNCS(mulVecScalar))
1604 << BuiltinOperInfo("mul", "*", FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1605 PRECMASK_ALL, FLOAT_VEC_FUNCS(mulScalarVec))
1606 << BuiltinOperInfo("mul", "*", IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed, 0.1f, 0.5f,
1607 PRECMASK_ALL, INT_VEC_FUNCS(mulScalarVec))
1608 << BuiltinOperInfo("div", "/", GT, Value(GT, -1.0f, 1.0f), Value(GT, -2.0f, -0.5f), notUsed, 1.0f, 0.0f,
1609 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(div))
1610 << BuiltinOperInfo("div", "/", IGT, Value(IGT, 24.0f, 24.0f), Value(IGT, -4.0f, -1.0f), notUsed, 0.04f, 1.0f,
1611 PRECMASK_ALL, INT_GENTYPE_FUNCS(div))
1612 << BuiltinOperInfo("div", "/", FV, Value(FV, -1.0f, 1.0f), Value(F, -2.0f, -0.5f), notUsed, 1.0f, 0.0f,
1613 PRECMASK_ALL, FLOAT_VEC_FUNCS(divVecScalar))
1614 << BuiltinOperInfo("div", "/", IV, Value(IV, 24.0f, 24.0f), Value(I, -4.0f, -1.0f), notUsed, 0.04f, 1.0f,
1615 PRECMASK_ALL, INT_VEC_FUNCS(divVecScalar))
1616 << BuiltinOperInfo("div", "/", FV, Value(F, -1.0f, 1.0f), Value(FV, -2.0f, -0.5f), notUsed, 1.0f, 0.0f,
1617 PRECMASK_ALL, FLOAT_VEC_FUNCS(divScalarVec))
1618 << BuiltinOperInfo("div", "/", IV, Value(I, 24.0f, 24.0f), Value(IV, -4.0f, -1.0f), notUsed, 0.04f, 1.0f,
1619 PRECMASK_ALL, INT_VEC_FUNCS(divScalarVec))
1620
1621 // Arithmetic assignment side effect cases.
1622 << BuiltinSideEffOperInfo("add_assign_effect", "+=", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f),
1623 notUsed, 0.25f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(add))
1624 << BuiltinSideEffOperInfo("add_assign_effect", "+=", IGT, Value(IGT, -5.0f, 5.0f), Value(IGT, -5.0f, 5.0f),
1625 notUsed, 0.05f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(add))
1626 << BuiltinSideEffOperInfo("add_assign_effect", "+=", FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed,
1627 0.25f, 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(addVecScalar))
1628 << BuiltinSideEffOperInfo("add_assign_effect", "+=", IV, Value(IV, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed,
1629 0.05f, 0.5f, PRECMASK_ALL, INT_VEC_FUNCS(addVecScalar))
1630 << BuiltinSideEffOperInfo("sub_assign_effect", "-=", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f),
1631 notUsed, 0.25f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(sub))
1632 << BuiltinSideEffOperInfo("sub_assign_effect", "-=", IGT, Value(IGT, -5.0f, 5.0f), Value(IGT, -5.0f, 5.0f),
1633 notUsed, 0.05f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(sub))
1634 << BuiltinSideEffOperInfo("sub_assign_effect", "-=", FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed,
1635 0.25f, 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(subVecScalar))
1636 << BuiltinSideEffOperInfo("sub_assign_effect", "-=", IV, Value(IV, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed,
1637 0.05f, 0.5f, PRECMASK_ALL, INT_VEC_FUNCS(subVecScalar))
1638 << BuiltinSideEffOperInfo("mul_assign_effect", "*=", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f),
1639 notUsed, 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(mul))
1640 << BuiltinSideEffOperInfo("mul_assign_effect", "*=", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -4.0f, 4.0f),
1641 notUsed, 0.03f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(mul))
1642 << BuiltinSideEffOperInfo("mul_assign_effect", "*=", FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed,
1643 0.5f, 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mulVecScalar))
1644 << BuiltinSideEffOperInfo("mul_assign_effect", "*=", IV, Value(IV, -4.0f, 4.0f), Value(I, -4.0f, 4.0f), notUsed,
1645 0.03f, 0.5f, PRECMASK_ALL, INT_VEC_FUNCS(mulVecScalar))
1646 << BuiltinSideEffOperInfo("div_assign_effect", "/=", GT, Value(GT, -1.0f, 1.0f), Value(GT, -2.0f, -0.5f),
1647 notUsed, 0.25f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(div))
1648 << BuiltinSideEffOperInfo("div_assign_effect", "/=", IGT, Value(IGT, 24.0f, 24.0f), Value(IGT, -4.0f, -1.0f),
1649 notUsed, 0.04f, 1.0f, PRECMASK_ALL, INT_GENTYPE_FUNCS(div))
1650 << BuiltinSideEffOperInfo("div_assign_effect", "/=", FV, Value(FV, -1.0f, 1.0f), Value(F, -2.0f, -0.5f),
1651 notUsed, 0.25f, 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(divVecScalar))
1652 << BuiltinSideEffOperInfo("div_assign_effect", "/=", IV, Value(IV, 24.0f, 24.0f), Value(I, -4.0f, -1.0f),
1653 notUsed, 0.04f, 1.0f, PRECMASK_ALL, INT_VEC_FUNCS(divVecScalar))
1654
1655 // Arithmetic assignment result cases.
1656 << BuiltinOperInfo("add_assign_result", "+=", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed,
1657 0.25f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(add))
1658 << BuiltinOperInfo("add_assign_result", "+=", IGT, Value(IGT, -5.0f, 5.0f), Value(IGT, -5.0f, 5.0f), notUsed,
1659 0.05f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(add))
1660 << BuiltinOperInfo("add_assign_result", "+=", FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 0.25f,
1661 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(addVecScalar))
1662 << BuiltinOperInfo("add_assign_result", "+=", IV, Value(IV, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 0.05f,
1663 0.5f, PRECMASK_ALL, INT_VEC_FUNCS(addVecScalar))
1664 << BuiltinOperInfo("sub_assign_result", "-=", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed,
1665 0.25f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(sub))
1666 << BuiltinOperInfo("sub_assign_result", "-=", IGT, Value(IGT, -5.0f, 5.0f), Value(IGT, -5.0f, 5.0f), notUsed,
1667 0.05f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(sub))
1668 << BuiltinOperInfo("sub_assign_result", "-=", FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 0.25f,
1669 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(subVecScalar))
1670 << BuiltinOperInfo("sub_assign_result", "-=", IV, Value(IV, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 0.05f,
1671 0.5f, PRECMASK_ALL, INT_VEC_FUNCS(subVecScalar))
1672 << BuiltinOperInfo("mul_assign_result", "*=", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 0.5f,
1673 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(mul))
1674 << BuiltinOperInfo("mul_assign_result", "*=", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -4.0f, 4.0f), notUsed,
1675 0.03f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(mul))
1676 << BuiltinOperInfo("mul_assign_result", "*=", FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 0.5f,
1677 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mulVecScalar))
1678 << BuiltinOperInfo("mul_assign_result", "*=", IV, Value(IV, -4.0f, 4.0f), Value(I, -4.0f, 4.0f), notUsed, 0.03f,
1679 0.5f, PRECMASK_ALL, INT_VEC_FUNCS(mulVecScalar))
1680 << BuiltinOperInfo("div_assign_result", "/=", GT, Value(GT, -1.0f, 1.0f), Value(GT, -2.0f, -0.5f), notUsed,
1681 0.25f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(div))
1682 << BuiltinOperInfo("div_assign_result", "/=", IGT, Value(IGT, 24.0f, 24.0f), Value(IGT, -4.0f, -1.0f), notUsed,
1683 0.04f, 1.0f, PRECMASK_ALL, INT_GENTYPE_FUNCS(div))
1684 << BuiltinOperInfo("div_assign_result", "/=", FV, Value(FV, -1.0f, 1.0f), Value(F, -2.0f, -0.5f), notUsed,
1685 0.25f, 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(divVecScalar))
1686 << BuiltinOperInfo("div_assign_result", "/=", IV, Value(IV, 24.0f, 24.0f), Value(I, -4.0f, -1.0f), notUsed,
1687 0.04f, 1.0f, PRECMASK_ALL, INT_VEC_FUNCS(divVecScalar))
1688
1689 // Scalar relational operators.
1690 << BuiltinOperInfo("less", "<", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1691 PRECMASK_ALL, eval_lessThan_float, DE_NULL, DE_NULL, DE_NULL)
1692 << BuiltinOperInfo("less", "<", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
1693 PRECMASK_ALL, eval_lessThan_int, DE_NULL, DE_NULL, DE_NULL)
1694 << BuiltinOperInfo("less_or_equal", "<=", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1695 PRECMASK_ALL, eval_lessThanEqual_float, DE_NULL, DE_NULL, DE_NULL)
1696 << BuiltinOperInfo("less_or_equal", "<=", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
1697 PRECMASK_ALL, eval_lessThanEqual_int, DE_NULL, DE_NULL, DE_NULL)
1698 << BuiltinOperInfo("greater", ">", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1699 PRECMASK_ALL, eval_greaterThan_float, DE_NULL, DE_NULL, DE_NULL)
1700 << BuiltinOperInfo("greater", ">", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
1701 PRECMASK_ALL, eval_greaterThan_int, DE_NULL, DE_NULL, DE_NULL)
1702 << BuiltinOperInfo("greater_or_equal", ">=", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
1703 0.0f, PRECMASK_ALL, eval_greaterThanEqual_float, DE_NULL, DE_NULL, DE_NULL)
1704 << BuiltinOperInfo("greater_or_equal", ">=", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f,
1705 0.0f, PRECMASK_ALL, eval_greaterThanEqual_int, DE_NULL, DE_NULL, DE_NULL)
1706
1707 // Equality comparison operators.
1708 << BuiltinOperInfo("equal", "==", B, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1709 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(allEqual))
1710 << BuiltinOperInfo("equal", "==", B, Value(IGT, -5.5f, 4.7f), Value(IGT, -4.9f, 5.8f), notUsed, 1.0f, 0.0f,
1711 PRECMASK_ALL, INT_GENTYPE_FUNCS(allEqual))
1712 << BuiltinOperInfo("equal", "==", B, Value(BGT, -2.1f, 2.1f), Value(BGT, -1.1f, 3.0f), notUsed, 1.0f, 0.0f,
1713 PRECMASK_NA, BOOL_GENTYPE_FUNCS(allEqual))
1714 << BuiltinOperInfo("not_equal", "!=", B, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1715 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(anyNotEqual))
1716 << BuiltinOperInfo("not_equal", "!=", B, Value(IGT, -5.5f, 4.7f), Value(IGT, -4.9f, 5.8f), notUsed, 1.0f, 0.0f,
1717 PRECMASK_ALL, INT_GENTYPE_FUNCS(anyNotEqual))
1718 << BuiltinOperInfo("not_equal", "!=", B, Value(BGT, -2.1f, 2.1f), Value(BGT, -1.1f, 3.0f), notUsed, 1.0f, 0.0f,
1719 PRECMASK_NA, BOOL_GENTYPE_FUNCS(anyNotEqual))
1720
1721 // Logical operators.
1722 << BuiltinOperInfo("logical_and", "&&", B, Value(B, -1.0f, 1.0f), Value(B, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1723 PRECMASK_NA, BOOL_FUNCS(logicalAnd))
1724 << BuiltinOperInfo("logical_or", "||", B, Value(B, -1.0f, 1.0f), Value(B, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1725 PRECMASK_NA, BOOL_FUNCS(logicalOr))
1726 << BuiltinOperInfo("logical_xor", "^^", B, Value(B, -1.0f, 1.0f), Value(B, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1727 PRECMASK_NA, BOOL_FUNCS(logicalXor)));
1728
1729 // 8.1 Angle and Trigonometry Functions.
1730 funcInfoGroups.push_back(BuiltinFuncGroup("angle_and_trigonometry", "Angle and trigonometry function tests.")
1731 << BuiltinFuncInfo("radians", "radians", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed,
1732 25.0f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(radians))
1733 << BuiltinFuncInfo("degrees", "degrees", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed,
1734 0.04f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(degrees))
1735 << BuiltinFuncInfo("sin", "sin", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f, 0.5f,
1736 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(sin))
1737 << BuiltinFuncInfo("sin", "sin", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f, 0.5f,
1738 PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(sin))
1739 << BuiltinFuncInfo("cos", "cos", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f, 0.5f,
1740 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(cos))
1741 << BuiltinFuncInfo("cos", "cos", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f, 0.5f,
1742 PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(cos))
1743 << BuiltinFuncInfo("tan", "tan", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f, 0.5f,
1744 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(tan))
1745 << BuiltinFuncInfo("tan", "tan", GT, Value(GT, -1.5f, 5.5f), notUsed, notUsed, 0.5f, 0.5f,
1746 PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(tan))
1747 << BuiltinFuncInfo("asin", "asin", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 1.0f,
1748 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(asin))
1749 << BuiltinFuncInfo("acos", "acos", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 1.0f,
1750 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(acos))
1751 << BuiltinFuncInfo("atan", "atan", GT, Value(GT, -4.0f, 4.0f), notUsed, notUsed, 0.5f,
1752 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(atan))
1753 << BuiltinFuncInfo("atan2", "atan", GT, Value(GT, -4.0f, 4.0f), Value(GT, 0.5f, 2.0f),
1754 notUsed, 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP,
1755 FLOAT_GENTYPE_FUNCS(atan2)));
1756
1757 // 8.2 Exponential Functions.
1758 funcInfoGroups.push_back(BuiltinFuncGroup("exponential", "Exponential function tests")
1759 << BuiltinFuncInfo("pow", "pow", GT, Value(GT, 0.1f, 8.0f), Value(GT, -4.0f, 2.0f),
1760 notUsed, 1.0f, 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(pow))
1761 << BuiltinFuncInfo("exp", "exp", GT, Value(GT, -6.0f, 3.0f), notUsed, notUsed, 0.5f, 0.0f,
1762 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(exp))
1763 << BuiltinFuncInfo("log", "log", GT, Value(GT, 0.1f, 10.0f), notUsed, notUsed, 0.5f, 0.3f,
1764 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(log))
1765 << BuiltinFuncInfo("exp2", "exp2", GT, Value(GT, -7.0f, 2.0f), notUsed, notUsed, 1.0f,
1766 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(exp2))
1767 << BuiltinFuncInfo("log2", "log2", GT, Value(GT, 0.1f, 10.0f), notUsed, notUsed, 1.0f,
1768 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(log2))
1769 << BuiltinFuncInfo("sqrt", "sqrt", GT, Value(GT, 0.0f, 10.0f), notUsed, notUsed, 0.3f,
1770 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(sqrt))
1771 << BuiltinFuncInfo("inversesqrt", "inversesqrt", GT, Value(GT, 0.5f, 10.0f), notUsed,
1772 notUsed, 1.0f, 0.0f, PRECMASK_MEDIUMP_HIGHP,
1773 FLOAT_GENTYPE_FUNCS(inverseSqrt)));
1774
1775 // 8.3 Common Functions.
1776 funcInfoGroups.push_back(
1777 BuiltinFuncGroup("common_functions", "Common function tests.")
1778 << BuiltinFuncInfo("abs", "abs", GT, Value(GT, -2.0f, 2.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL,
1779 FLOAT_GENTYPE_FUNCS(abs))
1780 << BuiltinFuncInfo("sign", "sign", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.3f, 0.5f, PRECMASK_ALL,
1781 FLOAT_GENTYPE_FUNCS(sign))
1782 << BuiltinFuncInfo("floor", "floor", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.7f, PRECMASK_ALL,
1783 FLOAT_GENTYPE_FUNCS(floor))
1784 << BuiltinFuncInfo("ceil", "ceil", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.5f, PRECMASK_ALL,
1785 FLOAT_GENTYPE_FUNCS(ceil))
1786 << BuiltinFuncInfo("fract", "fract", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.8f, 0.1f, PRECMASK_ALL,
1787 FLOAT_GENTYPE_FUNCS(fract))
1788 << BuiltinFuncInfo("mod", "mod", GT, Value(GT, -2.0f, 2.0f), Value(GT, 0.9f, 6.0f), notUsed, 0.5f, 0.5f,
1789 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(mod))
1790 << BuiltinFuncInfo("mod", "mod", GT, Value(FV, -2.0f, 2.0f), Value(F, 0.9f, 6.0f), notUsed, 0.5f, 0.5f,
1791 PRECMASK_MEDIUMP_HIGHP, FLOAT_VEC_FUNCS(modVecFloat))
1792 << BuiltinFuncInfo("min", "min", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 0.5f, 0.5f,
1793 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(min))
1794 << BuiltinFuncInfo("min", "min", GT, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 0.5f, 0.5f,
1795 PRECMASK_ALL, FLOAT_VEC_FUNCS(minVecFloat))
1796 << BuiltinFuncInfo("max", "max", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 0.5f, 0.5f,
1797 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(max))
1798 << BuiltinFuncInfo("max", "max", GT, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 0.5f, 0.5f,
1799 PRECMASK_ALL, FLOAT_VEC_FUNCS(maxVecFloat))
1800 << BuiltinFuncInfo("clamp", "clamp", GT, Value(GT, -1.0f, 1.0f), Value(GT, -0.5f, 0.5f), Value(GT, 0.5f, 1.0f),
1801 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(clamp))
1802 << BuiltinFuncInfo("clamp", "clamp", GT, Value(FV, -1.0f, 1.0f), Value(F, -0.5f, 0.5f), Value(F, 0.5f, 1.0f),
1803 0.5f, 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(clampVecFloatFloat))
1804 << BuiltinFuncInfo("mix", "mix", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), Value(GT, 0.0f, 1.0f),
1805 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(mix))
1806 << BuiltinFuncInfo("mix", "mix", GT, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), Value(F, 0.0f, 1.0f), 0.5f,
1807 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mixVecVecFloat))
1808 << BuiltinFuncInfo("step", "step", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 0.0f), notUsed, 0.5f, 0.25f,
1809 PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(step))
1810 << BuiltinFuncInfo("step", "step", GT, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 0.0f), notUsed, 0.5f, 0.25f,
1811 PRECMASK_ALL, FLOAT_VEC_FUNCS(stepFloatVec))
1812 << BuiltinFuncInfo("smoothstep", "smoothstep", GT, Value(GT, -0.5f, 0.0f), Value(GT, 0.1f, 1.0f),
1813 Value(GT, -1.0f, 1.0f), 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(smoothStep))
1814 << BuiltinFuncInfo("smoothstep", "smoothstep", GT, Value(F, -0.5f, 0.0f), Value(F, 0.1f, 1.0f),
1815 Value(FV, -1.0f, 1.0f), 0.5f, 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(smoothStepFloatFloatVec)));
1816
1817 // 8.4 Geometric Functions.
1818 funcInfoGroups.push_back(
1819 BuiltinFuncGroup("geometric", "Geometric function tests.")
1820 << BuiltinFuncInfo("length", "length", F, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f,
1821 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(length))
1822 << BuiltinFuncInfo("distance", "distance", F, Value(GT, -5.0f, 5.0f), Value(GT, -5.0f, 5.0f), notUsed, 0.1f,
1823 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(distance))
1824 << BuiltinFuncInfo("dot", "dot", F, Value(GT, -5.0f, 5.0f), Value(GT, -5.0f, 5.0f), notUsed, 0.1f, 0.5f,
1825 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(dot))
1826 << BuiltinFuncInfo("cross", "cross", V3, Value(GT, -5.0f, 5.0f), Value(GT, -5.0f, 5.0f), notUsed, 0.1f, 0.5f,
1827 PRECMASK_MEDIUMP_HIGHP, DE_NULL, DE_NULL, eval_cross_vec3, DE_NULL)
1828 << BuiltinFuncInfo("normalize", "normalize", GT, Value(GT, 0.1f, 4.0f), notUsed, notUsed, 0.5f, 0.5f,
1829 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(normalize))
1830 << BuiltinFuncInfo("faceforward", "faceforward", GT, Value(GT, -5.0f, 5.0f), Value(GT, -5.0f, 5.0f),
1831 Value(GT, -1.0f, 1.0f), 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(faceForward))
1832 << BuiltinFuncInfo("reflect", "reflect", GT, Value(GT, -0.8f, -0.5f), Value(GT, 0.5f, 0.8f), notUsed, 0.5f,
1833 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(reflect))
1834 << BuiltinFuncInfo("refract", "refract", GT, Value(GT, -0.8f, 1.2f), Value(GT, -1.1f, 0.5f),
1835 Value(F, 0.2f, 1.5f), 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(refract)));
1836
1837 // 8.5 Matrix Functions.
1838 // separate matrix tests?
1839 // funcInfoGroups.push_back(
1840 // BuiltinFuncGroup("matrix", "Matrix function tests.")
1841 // << BuiltinFuncInfo("matrixCompMult", "matrixCompMult", M, ... )
1842 // );
1843
1844 // 8.6 Vector Relational Functions.
1845 funcInfoGroups.push_back(
1846 BuiltinFuncGroup("float_compare", "Floating point comparison tests.")
1847 << BuiltinFuncInfo("lessThan", "lessThan", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f,
1848 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(lessThan))
1849 << BuiltinFuncInfo("lessThanEqual", "lessThanEqual", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f),
1850 notUsed, 1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(lessThanEqual))
1851 << BuiltinFuncInfo("greaterThan", "greaterThan", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
1852 1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(greaterThan))
1853 << BuiltinFuncInfo("greaterThanEqual", "greaterThanEqual", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f),
1854 notUsed, 1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(greaterThanEqual))
1855 << BuiltinFuncInfo("equal", "equal", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
1856 PRECMASK_ALL, FLOAT_VEC_FUNCS(equal))
1857 << BuiltinFuncInfo("notEqual", "notEqual", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f,
1858 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(notEqual)));
1859
1860 funcInfoGroups.push_back(
1861 BuiltinFuncGroup("int_compare", "Integer comparison tests.")
1862 << BuiltinFuncInfo("lessThan", "lessThan", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed, 1.0f,
1863 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(lessThan))
1864 << BuiltinFuncInfo("lessThanEqual", "lessThanEqual", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f),
1865 notUsed, 1.0f, 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(lessThanEqual))
1866 << BuiltinFuncInfo("greaterThan", "greaterThan", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed,
1867 1.0f, 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(greaterThan))
1868 << BuiltinFuncInfo("greaterThanEqual", "greaterThanEqual", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f),
1869 notUsed, 1.0f, 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(greaterThanEqual))
1870 << BuiltinFuncInfo("equal", "equal", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
1871 PRECMASK_ALL, INT_VEC_FUNCS(equal))
1872 << BuiltinFuncInfo("notEqual", "notEqual", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed, 1.0f,
1873 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(notEqual)));
1874
1875 funcInfoGroups.push_back(BuiltinFuncGroup("bool_compare", "Boolean comparison tests.")
1876 << BuiltinFuncInfo("equal", "equal", BV, Value(BV, -5.2f, 4.9f), Value(BV, -5.0f, 5.0f),
1877 notUsed, 1.0f, 0.0f, PRECMASK_NA, BOOL_VEC_FUNCS(equal))
1878 << BuiltinFuncInfo("notEqual", "notEqual", BV, Value(BV, -5.2f, 4.9f),
1879 Value(BV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_NA,
1880 BOOL_VEC_FUNCS(notEqual))
1881 << BuiltinFuncInfo("any", "any", B, Value(BV, -1.0f, 0.3f), notUsed, notUsed, 1.0f, 0.0f,
1882 PRECMASK_NA, BOOL_VEC_FUNCS(any))
1883 << BuiltinFuncInfo("all", "all", B, Value(BV, -0.3f, 1.0f), notUsed, notUsed, 1.0f, 0.0f,
1884 PRECMASK_NA, BOOL_VEC_FUNCS(all))
1885 << BuiltinFuncInfo("not", "not", BV, Value(BV, -1.0f, 1.0f), notUsed, notUsed, 1.0f, 0.0f,
1886 PRECMASK_NA, BOOL_VEC_FUNCS(boolNot)));
1887
1888 // 8.7 Texture Lookup Functions
1889 // texture2D (sampler, vec2)
1890 // texture2D (sampler, vec2, bias)
1891 // texture2DProj (sampler, vec3)
1892 // texture2DProj (sampler, vec3, bias)
1893 // texture2DProj (sampler, vec4)
1894 // texture2DProj (sampler, vec4, bias)
1895 // texture2DLod (sampler, vec2, lod)
1896 // texture2DProjLod (sampler, vec3, lod)
1897 // texture2DProjLod (sampler, vec4, lod)
1898 // textureCube (sampler, vec3)
1899 // textureCube (sampler, vec3, bias)
1900 // textureCubeLod (sampler, vec3, lod)
1901
1902 static const ShaderType s_shaderTypes[] = {SHADERTYPE_VERTEX, SHADERTYPE_FRAGMENT};
1903
1904 static const DataType s_floatTypes[] = {TYPE_FLOAT, TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4};
1905
1906 static const DataType s_intTypes[] = {TYPE_INT, TYPE_INT_VEC2, TYPE_INT_VEC3, TYPE_INT_VEC4};
1907
1908 static const DataType s_boolTypes[] = {TYPE_BOOL, TYPE_BOOL_VEC2, TYPE_BOOL_VEC3, TYPE_BOOL_VEC4};
1909
1910 for (int outerGroupNdx = 0; outerGroupNdx < (int)funcInfoGroups.size(); outerGroupNdx++)
1911 {
1912 // Create outer group.
1913 const BuiltinFuncGroup &outerGroupInfo = funcInfoGroups[outerGroupNdx];
1914 TestCaseGroup *outerGroup = new TestCaseGroup(m_context, outerGroupInfo.name, outerGroupInfo.description);
1915 addChild(outerGroup);
1916
1917 // Only create new group if name differs from previous one.
1918 TestCaseGroup *innerGroup = DE_NULL;
1919
1920 for (int funcInfoNdx = 0; funcInfoNdx < (int)outerGroupInfo.funcInfos.size(); funcInfoNdx++)
1921 {
1922 const BuiltinFuncInfo &funcInfo = outerGroupInfo.funcInfos[funcInfoNdx];
1923 const char *shaderFuncName = funcInfo.shaderFuncName;
1924 bool isBoolCase = (funcInfo.precisionMask == PRECMASK_NA);
1925 bool isIntCase = (funcInfo.input0.valueType & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
1926 bool isFloatCase = !isBoolCase && !isIntCase; // \todo [petri] Better check.
1927 bool isBoolOut = (funcInfo.outValue & (VALUE_BOOL | VALUE_BOOL_VEC | VALUE_BOOL_GENTYPE)) != 0;
1928 bool isIntOut = (funcInfo.outValue & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
1929 bool isFloatOut = !isBoolOut && !isIntOut;
1930
1931 if (!innerGroup || (string(innerGroup->getName()) != funcInfo.caseName))
1932 {
1933 string groupDesc = string("Built-in function ") + shaderFuncName + "() tests.";
1934 innerGroup = new TestCaseGroup(m_context, funcInfo.caseName, groupDesc.c_str());
1935 outerGroup->addChild(innerGroup);
1936 }
1937
1938 for (int inScalarSize = 1; inScalarSize <= 4; inScalarSize++)
1939 {
1940 int outScalarSize = ((funcInfo.outValue == VALUE_FLOAT) || (funcInfo.outValue == VALUE_BOOL)) ?
1941 1 :
1942 inScalarSize; // \todo [petri] Int.
1943 DataType outDataType = isFloatOut ? s_floatTypes[outScalarSize - 1] :
1944 isIntOut ? s_intTypes[outScalarSize - 1] :
1945 isBoolOut ? s_boolTypes[outScalarSize - 1] :
1946 TYPE_LAST;
1947
1948 ShaderEvalFunc evalFunc = DE_NULL;
1949 if (inScalarSize == 1)
1950 evalFunc = funcInfo.evalFuncScalar;
1951 else if (inScalarSize == 2)
1952 evalFunc = funcInfo.evalFuncVec2;
1953 else if (inScalarSize == 3)
1954 evalFunc = funcInfo.evalFuncVec3;
1955 else if (inScalarSize == 4)
1956 evalFunc = funcInfo.evalFuncVec4;
1957 else
1958 DE_ASSERT(false);
1959
1960 // Skip if no valid eval func.
1961 // \todo [petri] Better check for V3 only etc. cases?
1962 if (evalFunc == DE_NULL)
1963 continue;
1964
1965 for (int precision = 0; precision < PRECISION_LAST; precision++)
1966 {
1967 if ((funcInfo.precisionMask & (1 << precision)) ||
1968 (funcInfo.precisionMask == PRECMASK_NA &&
1969 precision == PRECISION_MEDIUMP)) // use mediump interpolators for booleans
1970 {
1971 const char *precisionStr = getPrecisionName((Precision)precision);
1972 string precisionPrefix = isBoolCase ? "" : (string(precisionStr) + "_");
1973
1974 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1975 {
1976 ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
1977 ShaderDataSpec shaderSpec;
1978 const char *shaderTypeName = getShaderTypeName(shaderType);
1979 bool isVertexCase = (ShaderType)shaderType == SHADERTYPE_VERTEX;
1980 bool isUnaryOp = (funcInfo.input1.valueType == VALUE_NONE);
1981
1982 // \note Data type names will be added to description and name in a following loop.
1983 string desc = string("Built-in function ") + shaderFuncName + "(";
1984 string name = precisionPrefix;
1985
1986 // Generate shader op.
1987 string shaderOp = string("res = ");
1988
1989 // Setup shader data info.
1990 shaderSpec.numInputs = 0;
1991 shaderSpec.precision = isBoolCase ? PRECISION_LAST : (Precision)precision;
1992 shaderSpec.output = outDataType;
1993 shaderSpec.resultScale = funcInfo.resultScale;
1994 shaderSpec.resultBias = funcInfo.resultBias;
1995
1996 if (funcInfo.type == OPERATOR)
1997 {
1998 if (isUnaryOp && funcInfo.isUnaryPrefix)
1999 shaderOp += shaderFuncName;
2000 }
2001 else if (funcInfo.type == FUNCTION)
2002 shaderOp += string(shaderFuncName) + "(";
2003 else // SIDE_EFFECT_OPERATOR
2004 shaderOp += "in0;\n\t";
2005
2006 for (int inputNdx = 0; inputNdx < MAX_INPUTS; inputNdx++)
2007 {
2008 const Value &v = (inputNdx == 0) ? funcInfo.input0 :
2009 (inputNdx == 1) ? funcInfo.input1 :
2010 funcInfo.input2;
2011 const Value &prevV = (inputNdx == 1) ? funcInfo.input0 :
2012 (inputNdx == 2) ? funcInfo.input1 :
2013 funcInfo.input2;
2014
2015 if (v.valueType == VALUE_NONE)
2016 continue; // Skip unused input.
2017
2018 int curInScalarSize = isScalarType(v.valueType) ? 1 : inScalarSize;
2019 DataType curInDataType = isFloatCase ? s_floatTypes[curInScalarSize - 1] :
2020 isIntCase ? s_intTypes[curInScalarSize - 1] :
2021 isBoolCase ? s_boolTypes[curInScalarSize - 1] :
2022 TYPE_LAST;
2023
2024 // Write input type(s) to case description and name.
2025
2026 if (inputNdx > 0)
2027 desc += ", ";
2028
2029 desc += getDataTypeName(curInDataType);
2030
2031 if (inputNdx == 0 ||
2032 isScalarType(prevV.valueType) !=
2033 isScalarType(
2034 v.valueType)) // \note Only write input type to case name if different from previous input type (avoid overly long names).
2035 name += string("") + getDataTypeName(curInDataType) + "_";
2036
2037 // Generate op input source.
2038
2039 if (funcInfo.type == OPERATOR || funcInfo.type == FUNCTION)
2040 {
2041 if (inputNdx != 0)
2042 {
2043 if (funcInfo.type == OPERATOR && !isUnaryOp)
2044 shaderOp += " " + string(shaderFuncName) + " ";
2045 else
2046 shaderOp += ", ";
2047 }
2048
2049 shaderOp += "in" + de::toString(inputNdx);
2050
2051 if (funcInfo.type == OPERATOR && isUnaryOp && !funcInfo.isUnaryPrefix)
2052 shaderOp += string(shaderFuncName);
2053 }
2054 else
2055 {
2056 DE_ASSERT(funcInfo.type == SIDE_EFFECT_OPERATOR);
2057
2058 if (inputNdx != 0 || (isUnaryOp && funcInfo.isUnaryPrefix))
2059 shaderOp += string("") + (isUnaryOp ? "" : " ") + shaderFuncName +
2060 (isUnaryOp ? "" : " ");
2061
2062 shaderOp +=
2063 inputNdx == 0 ?
2064 "res" :
2065 "in" +
2066 de::toString(
2067 inputNdx); // \note in0 has already been assigned to res, so start from in1.
2068
2069 if (isUnaryOp && !funcInfo.isUnaryPrefix)
2070 shaderOp += shaderFuncName;
2071 }
2072
2073 // Fill in shader info.
2074 shaderSpec.inputs[shaderSpec.numInputs++] =
2075 ShaderValue(curInDataType, v.rangeMin, v.rangeMax);
2076 }
2077
2078 if (funcInfo.type == FUNCTION)
2079 shaderOp += ")";
2080
2081 shaderOp += ";";
2082
2083 desc += ").";
2084 name += shaderTypeName;
2085
2086 // Create the test case.
2087 innerGroup->addChild(new ShaderOperatorCase(m_context, name.c_str(), desc.c_str(),
2088 isVertexCase, evalFunc, shaderOp.c_str(),
2089 shaderSpec));
2090 }
2091 }
2092 }
2093 }
2094 }
2095 }
2096
2097 // The ?: selection operator.
2098
2099 static const struct
2100 {
2101 DataType type; // The type of "Y" and "Z" operands in "X ? Y : Z" (X is always bool).
2102 ShaderEvalFunc evalFunc;
2103 } s_selectionInfo[] = {{TYPE_FLOAT, eval_selection_float}, {TYPE_FLOAT_VEC2, eval_selection_vec2},
2104 {TYPE_FLOAT_VEC3, eval_selection_vec3}, {TYPE_FLOAT_VEC4, eval_selection_vec4},
2105 {TYPE_INT, eval_selection_int}, {TYPE_INT_VEC2, eval_selection_ivec2},
2106 {TYPE_INT_VEC3, eval_selection_ivec3}, {TYPE_INT_VEC4, eval_selection_ivec4},
2107 {TYPE_BOOL, eval_selection_bool}, {TYPE_BOOL_VEC2, eval_selection_bvec2},
2108 {TYPE_BOOL_VEC3, eval_selection_bvec3}, {TYPE_BOOL_VEC4, eval_selection_bvec4}};
2109
2110 TestCaseGroup *selectionGroup = new TestCaseGroup(m_context, "selection", "Selection operator tests");
2111 addChild(selectionGroup);
2112
2113 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_selectionInfo); typeNdx++)
2114 {
2115 DataType curType = s_selectionInfo[typeNdx].type;
2116 ShaderEvalFunc evalFunc = s_selectionInfo[typeNdx].evalFunc;
2117 bool isBoolCase = isDataTypeBoolOrBVec(curType);
2118 bool isFloatCase = isDataTypeFloatOrVec(curType);
2119 bool isIntCase = isDataTypeIntOrIVec(curType);
2120 const char *dataTypeStr = getDataTypeName(curType);
2121
2122 DE_ASSERT(isBoolCase || isFloatCase || isIntCase);
2123 DE_UNREF(isIntCase);
2124
2125 for (int precision = 0; precision < (int)PRECISION_LAST; precision++)
2126 {
2127 if (isBoolCase && precision != PRECISION_MEDIUMP) // Use mediump interpolators for booleans.
2128 continue;
2129
2130 const char *precisionStr = getPrecisionName((Precision)precision);
2131 string precisionPrefix = isBoolCase ? "" : (string(precisionStr) + "_");
2132
2133 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
2134 {
2135 ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
2136 ShaderDataSpec shaderSpec;
2137 const char *shaderTypeName = getShaderTypeName(shaderType);
2138 bool isVertexCase = (ShaderType)shaderType == SHADERTYPE_VERTEX;
2139
2140 string name = precisionPrefix + dataTypeStr + "_" + shaderTypeName;
2141
2142 shaderSpec.numInputs = 3;
2143 shaderSpec.precision = isBoolCase ? PRECISION_LAST : (Precision)precision;
2144 shaderSpec.output = curType;
2145 shaderSpec.resultScale = isBoolCase ? 1.0f : isFloatCase ? 0.5f : 0.1f;
2146 shaderSpec.resultBias = isBoolCase ? 0.0f : isFloatCase ? 0.5f : 0.5f;
2147
2148 float rangeMin = isBoolCase ? -1.0f : isFloatCase ? -1.0f : -5.0f;
2149 float rangeMax = isBoolCase ? 1.0f : isFloatCase ? 1.0f : 5.0f;
2150
2151 shaderSpec.inputs[0] = ShaderValue(TYPE_BOOL, -1.0f, 1.0f);
2152 shaderSpec.inputs[1] = ShaderValue(curType, rangeMin, rangeMax);
2153 shaderSpec.inputs[2] = ShaderValue(curType, rangeMin, rangeMax);
2154
2155 selectionGroup->addChild(new ShaderOperatorCase(m_context, name.c_str(), "", isVertexCase, evalFunc,
2156 "res = in0 ? in1 : in2;", shaderSpec));
2157 }
2158 }
2159 }
2160
2161 // The sequence operator (comma).
2162
2163 TestCaseGroup *sequenceGroup = new TestCaseGroup(m_context, "sequence", "Sequence operator tests");
2164 addChild(sequenceGroup);
2165
2166 TestCaseGroup *sequenceNoSideEffGroup =
2167 new TestCaseGroup(m_context, "no_side_effects", "Sequence tests without side-effects");
2168 TestCaseGroup *sequenceSideEffGroup =
2169 new TestCaseGroup(m_context, "side_effects", "Sequence tests with side-effects");
2170 sequenceGroup->addChild(sequenceNoSideEffGroup);
2171 sequenceGroup->addChild(sequenceSideEffGroup);
2172
2173 static const struct
2174 {
2175 bool containsSideEffects;
2176 const char *caseName;
2177 const char *expressionStr;
2178 int numInputs;
2179 DataType inputTypes[MAX_INPUTS];
2180 DataType resultType;
2181 ShaderEvalFunc evalFunc;
2182 } s_sequenceCases[] = {{false,
2183 "vec4",
2184 "in0, in2 + in1, in1 + in0",
2185 3,
2186 {TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4},
2187 TYPE_FLOAT_VEC4,
2188 evalSequenceNoSideEffCase0},
2189 {false,
2190 "float_int",
2191 "in0 + in2, in1 + in1",
2192 3,
2193 {TYPE_FLOAT, TYPE_INT, TYPE_FLOAT},
2194 TYPE_INT,
2195 evalSequenceNoSideEffCase1},
2196 {false,
2197 "bool_vec2",
2198 "in0 && in1, in0, ivec2(vec2(in0) + in2)",
2199 3,
2200 {TYPE_BOOL, TYPE_BOOL, TYPE_FLOAT_VEC2},
2201 TYPE_INT_VEC2,
2202 evalSequenceNoSideEffCase2},
2203 {false,
2204 "vec4_ivec4_bvec4",
2205 "in0 + vec4(in1), in2, in1",
2206 3,
2207 {TYPE_FLOAT_VEC4, TYPE_INT_VEC4, TYPE_BOOL_VEC4},
2208 TYPE_INT_VEC4,
2209 evalSequenceNoSideEffCase3},
2210
2211 {true,
2212 "vec4",
2213 "in0++, in1 = in0 + in2, in2 = in1",
2214 3,
2215 {TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4},
2216 TYPE_FLOAT_VEC4,
2217 evalSequenceSideEffCase0},
2218 {true,
2219 "float_int",
2220 "in1++, in0 = float(in1), in1 = int(in0 + in2)",
2221 3,
2222 {TYPE_FLOAT, TYPE_INT, TYPE_FLOAT},
2223 TYPE_INT,
2224 evalSequenceSideEffCase1},
2225 {true,
2226 "bool_vec2",
2227 "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)",
2228 3,
2229 {TYPE_BOOL, TYPE_BOOL, TYPE_FLOAT_VEC2},
2230 TYPE_INT_VEC2,
2231 evalSequenceSideEffCase2},
2232 {true,
2233 "vec4_ivec4_bvec4",
2234 "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++",
2235 3,
2236 {TYPE_FLOAT_VEC4, TYPE_INT_VEC4, TYPE_BOOL_VEC4},
2237 TYPE_INT_VEC4,
2238 evalSequenceSideEffCase3}};
2239
2240 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_sequenceCases); caseNdx++)
2241 {
2242 for (int precision = 0; precision < (int)PRECISION_LAST; precision++)
2243 {
2244 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
2245 {
2246 ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
2247 ShaderDataSpec shaderSpec;
2248 const char *shaderTypeName = getShaderTypeName(shaderType);
2249 bool isVertexCase = (ShaderType)shaderType == SHADERTYPE_VERTEX;
2250
2251 string name = string("") + getPrecisionName((Precision)precision) + "_" +
2252 s_sequenceCases[caseNdx].caseName + "_" + shaderTypeName;
2253
2254 shaderSpec.numInputs = s_sequenceCases[caseNdx].numInputs;
2255 shaderSpec.precision = (Precision)precision;
2256 shaderSpec.output = s_sequenceCases[caseNdx].resultType;
2257 shaderSpec.resultScale = 0.5f;
2258 shaderSpec.resultBias = 0.0f;
2259
2260 for (int inputNdx = 0; inputNdx < s_sequenceCases[caseNdx].numInputs; inputNdx++)
2261 {
2262 DataType type = s_sequenceCases[caseNdx].inputTypes[inputNdx];
2263 float rangeMin = isDataTypeFloatOrVec(type) ? -0.5f : isDataTypeIntOrIVec(type) ? -2.0f : -1.0f;
2264 float rangeMax = isDataTypeFloatOrVec(type) ? 0.5f : isDataTypeIntOrIVec(type) ? 2.0f : 1.0f;
2265
2266 shaderSpec.inputs[inputNdx] = ShaderValue(type, rangeMin, rangeMax);
2267 }
2268
2269 string expression = string("") + "res = (" + s_sequenceCases[caseNdx].expressionStr + ");";
2270
2271 TestCaseGroup *group =
2272 s_sequenceCases[caseNdx].containsSideEffects ? sequenceSideEffGroup : sequenceNoSideEffGroup;
2273 group->addChild(new ShaderOperatorCase(m_context, name.c_str(), "", isVertexCase,
2274 s_sequenceCases[caseNdx].evalFunc, expression.c_str(),
2275 shaderSpec));
2276 }
2277 }
2278 }
2279
2280 // Regression tests for sequence operator.
2281 // http://khronos.org/registry/webgl/sdk/tests/conformance/glsl/bugs/sequence-operator-evaluation-order.html
2282 {
2283 class Case : public ShaderRenderCase
2284 {
evalFunc(ShaderEvalContext & c)2285 static void evalFunc(ShaderEvalContext &c)
2286 {
2287 c.color = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); // green
2288 }
2289
2290 public:
Case(Context & context,const char * name,const char * description,const char * fragShaderSource)2291 Case(Context &context, const char *name, const char *description, const char *fragShaderSource)
2292 : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name,
2293 description, false, &evalFunc)
2294 {
2295 m_vertShaderSource = "attribute vec4 a_position;\n"
2296 "void main()\n"
2297 "{\n"
2298 " gl_Position = a_position;\n"
2299 "}\n";
2300 m_fragShaderSource = fragShaderSource;
2301 }
2302 };
2303
2304 // ESSL 1.00 section 5.9, about sequence operator:
2305 // "All expressions are evaluated, in order, from left to right"
2306 // Also use a ternary operator where the third operand has side effects to make sure
2307 // only the second operand is evaluated.
2308 sequenceSideEffGroup->addChild(new Case(m_context, "affect_ternary",
2309 "Expression where first operand of a sequence operator has side "
2310 "effects which affect the second operand that is a ternary operator",
2311 ("precision mediump float;\n"
2312 "bool correct = true;\n"
2313 "uniform float u_zero;\n"
2314 "float wrong() {\n"
2315 " correct = false;\n"
2316 " return 0.0;\n"
2317 "}\n"
2318 "void main() {\n"
2319 " float a = u_zero - 0.5; // Result should be -0.5.\n"
2320 " float green = (a++, a > 0.0 ? 1.0 : wrong());\n"
2321 " gl_FragColor = vec4(0.0, correct ? green : 0.0, 0.0, 1.0);\n"
2322 "}\n")));
2323
2324 sequenceSideEffGroup->addChild(
2325 new Case(m_context, "affect_and",
2326 "Expression where first operand of a sequence operator has side effects which affect the second "
2327 "operand that is an and operator",
2328 ("precision mediump float;\n"
2329 "uniform bool u_false;\n"
2330 "bool sideEffectA = false;\n"
2331 "bool funcA() {\n"
2332 " sideEffectA = true;\n"
2333 " return true;\n"
2334 "}\n"
2335 "bool sideEffectB = false;\n"
2336 "bool funcB() {\n"
2337 " sideEffectB = true;\n"
2338 " return true;\n"
2339 "}\n"
2340 "void main() {\n"
2341 " bool b = (funcA(), u_false == sideEffectA && funcB());\n"
2342 " gl_FragColor = (!b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2343 "}\n")));
2344
2345 sequenceSideEffGroup->addChild(
2346 new Case(m_context, "affect_or",
2347 "Expression where first operand of a sequence operator has side effects which affect the second "
2348 "operand that is an or operator",
2349 ("precision mediump float;\n"
2350 "uniform bool u_false;\n"
2351 "bool sideEffectA = false;\n"
2352 "bool funcA() {\n"
2353 " sideEffectA = true;\n"
2354 " return false;\n"
2355 "}\n"
2356 "bool sideEffectB = false;\n"
2357 "bool funcB() {\n"
2358 " sideEffectB = true;\n"
2359 " return false;\n"
2360 "}\n"
2361 "void main() {\n"
2362 " bool b = (funcA(), (u_false == !sideEffectA) || funcB());\n"
2363 " gl_FragColor = (b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
2364 "}\n")));
2365 }
2366 }
2367
2368 } // namespace Functional
2369 } // namespace gles2
2370 } // namespace deqp
2371