xref: /aosp_15_r20/external/deqp/modules/gles2/functional/es2fShaderOperatorTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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