Add new framebuffer fetch extension tests am: 2a609fb223
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / functional / es2fShaderOperatorTests.cpp
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::pair;
41 using std::vector;
42 using std::string;
43 using std::ostringstream;
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::min;
57 using de::max;
58 using de::clamp;
59
60 // \note VS2013 gets confused without these
61 using tcu::exp2;
62 using tcu::log2;
63
64 inline float abs                (float v)                       { return deFloatAbs(v); }
65
66 inline bool logicalAnd  (bool a, bool b)        { return (a && b); }
67 inline bool logicalOr   (bool a, bool b)        { return (a || b); }
68 inline bool logicalXor  (bool a, bool b)        { return (a != b); }
69
70 #define DEFINE_VEC_FLOAT_FUNCTION(FUNC_NAME, SCALAR_OP_NAME)                                    \
71 template<int Size>                                                                                                                              \
72 inline Vector<float, Size> FUNC_NAME (const Vector<float, Size>& v, float s)    \
73 {                                                                                                                                                               \
74         Vector<float, Size> res;                                                                                                        \
75         for (int i = 0; i < Size; i++)                                                                                          \
76                 res[i] = SCALAR_OP_NAME(v[i], s);                                                                               \
77         return res;                                                                                                                                     \
78 }
79
80 #define DEFINE_FLOAT_VEC_FUNCTION(FUNC_NAME, SCALAR_OP_NAME)                                    \
81 template<int Size>                                                                                                                              \
82 inline Vector<float, Size> FUNC_NAME (float s, const Vector<float, Size>& v)    \
83 {                                                                                                                                                               \
84         Vector<float, Size> res;                                                                                                        \
85         for (int i = 0; i < Size; i++)                                                                                          \
86                 res[i] = SCALAR_OP_NAME(s, v[i]);                                                                               \
87         return res;                                                                                                                                     \
88 }
89
90 #define DEFINE_VEC_VEC_FLOAT_FUNCTION(FUNC_NAME, SCALAR_OP_NAME)                                                                                                \
91 template<int Size>                                                                                                                                                                                              \
92 inline Vector<float, Size> FUNC_NAME (const Vector<float, Size>& v0, const Vector<float, Size>& v1, float s)    \
93 {                                                                                                                                                                                                                               \
94         Vector<float, Size> res;                                                                                                                                                                        \
95         for (int i = 0; i < Size; i++)                                                                                                                                                          \
96                 res[i] = SCALAR_OP_NAME(v0[i], v1[i], s);                                                                                                                               \
97         return res;                                                                                                                                                                                                     \
98 }
99
100 #define DEFINE_VEC_FLOAT_FLOAT_FUNCTION(FUNC_NAME, SCALAR_OP_NAME)                                                      \
101 template<int Size>                                                                                                                                                      \
102 inline Vector<float, Size> FUNC_NAME (const Vector<float, Size>& v, float s0, float s1)         \
103 {                                                                                                                                                                                       \
104         Vector<float, Size> res;                                                                                                                                \
105         for (int i = 0; i < Size; i++)                                                                                                                  \
106                 res[i] = SCALAR_OP_NAME(v[i], s0, s1);                                                                                          \
107         return res;                                                                                                                                                             \
108 }
109
110 #define DEFINE_FLOAT_FLOAT_VEC_FUNCTION(FUNC_NAME, SCALAR_OP_NAME)                                                      \
111 template<int Size>                                                                                                                                                      \
112 inline Vector<float, Size> FUNC_NAME (float s0, float s1, const Vector<float, Size>& v)         \
113 {                                                                                                                                                                                       \
114         Vector<float, Size> res;                                                                                                                                \
115         for (int i = 0; i < Size; i++)                                                                                                                  \
116                 res[i] = SCALAR_OP_NAME(s0, s1, v[i]);                                                                                          \
117         return res;                                                                                                                                                             \
118 }
119
120 DEFINE_VEC_FLOAT_FUNCTION               (modVecFloat,                           mod)
121 DEFINE_VEC_FLOAT_FUNCTION               (minVecFloat,                           min)
122 DEFINE_VEC_FLOAT_FUNCTION               (maxVecFloat,                           max)
123 DEFINE_VEC_FLOAT_FLOAT_FUNCTION (clampVecFloatFloat,            clamp)
124 DEFINE_VEC_VEC_FLOAT_FUNCTION   (mixVecVecFloat,                        mix)
125 DEFINE_FLOAT_VEC_FUNCTION               (stepFloatVec,                          step)
126 DEFINE_FLOAT_FLOAT_VEC_FUNCTION (smoothStepFloatFloatVec,       smoothStep)
127
128 #undef DEFINE_VEC_FLOAT_FUNCTION
129 #undef DEFINE_VEC_VEC_FLOAT_FUNCTION
130 #undef DEFINE_VEC_FLOAT_FLOAT_FUNCTION
131 #undef DEFINE_FLOAT_FLOAT_VEC_FUNCTION
132
133 inline float    addOne (float v)        { return v + 1.0f; };
134 inline float    subOne (float v)        { return v - 1.0f; };
135 inline int              addOne (int v)          { return v + 1; };
136 inline int              subOne (int v)          { return v - 1; };
137
138 template<int Size> inline Vector<float, Size>   addOne (const Vector<float, Size>& v)   { return v + 1.0f; };
139 template<int Size> inline Vector<float, Size>   subOne (const Vector<float, Size>& v)   { return v - 1.0f; };
140 template<int Size> inline Vector<int, Size>             addOne (const Vector<int, Size>& v)             { return v + 1; };
141 template<int Size> inline Vector<int, Size>             subOne (const Vector<int, Size>& v)             { return v - 1; };
142
143 template<typename T> inline T selection (bool cond, T a, T b)   { return cond ? a : b; };
144
145 template<typename T, int Size> inline Vector<T, Size> addVecScalar      (const Vector<T, Size>& v, T s) { return v + s; };
146 template<typename T, int Size> inline Vector<T, Size> subVecScalar      (const Vector<T, Size>& v, T s) { return v - s; };
147 template<typename T, int Size> inline Vector<T, Size> mulVecScalar      (const Vector<T, Size>& v, T s) { return v * s; };
148 template<typename T, int Size> inline Vector<T, Size> divVecScalar      (const Vector<T, Size>& v, T s) { return v / s; };
149
150 template<typename T, int Size> inline Vector<T, Size> addScalarVec      (T s, const Vector<T, Size>& v) { return s + v; };
151 template<typename T, int Size> inline Vector<T, Size> subScalarVec      (T s, const Vector<T, Size>& v) { return s - v; };
152 template<typename T, int Size> inline Vector<T, Size> mulScalarVec      (T s, const Vector<T, Size>& v) { return s * v; };
153 template<typename T, int Size> inline Vector<T, Size> divScalarVec      (T s, const Vector<T, Size>& v) { return s / v; };
154
155 // Reference functions for specific sequence operations for the sequence operator tests.
156
157 // Reference for expression "in0, in2 + in1, in1 + in0"
158 inline Vec4             sequenceNoSideEffCase0 (const Vec4& in0, const Vec4& in1, const Vec4& in2)              { DE_UNREF(in2); return in1 + in0; }
159 // Reference for expression "in0, in2 + in1, in1 + in0"
160 inline int              sequenceNoSideEffCase1 (float in0, int in1, float in2)                                                  { DE_UNREF(in0); DE_UNREF(in2); return in1 + in1; }
161 // Reference for expression "in0 && in1, in0, ivec2(vec2(in0) + in2)"
162 inline IVec2    sequenceNoSideEffCase2 (bool in0, bool in1, const Vec2& in2)                                    { DE_UNREF(in1); return IVec2((int)((float)in0 + in2.x()), (int)((float)in0 + in2.y())); }
163 // Reference for expression "in0 + vec4(in1), in2, in1"
164 inline IVec4    sequenceNoSideEffCase3 (const Vec4& in0, const IVec4& in1, const BVec4& in2)    { DE_UNREF(in0); DE_UNREF(in2); return in1; }
165 // Reference for expression "in0++, in1 = in0 + in2, in2 = in1"
166 inline Vec4             sequenceSideEffCase0 (const Vec4& in0, const Vec4& in1, const Vec4& in2)                { DE_UNREF(in1); return in0 + 1.0f + in2; }
167 // Reference for expression "in1++, in0 = float(in1), in1 = int(in0 + in2)"
168 inline int              sequenceSideEffCase1 (float in0, int in1, float in2)                                                    { DE_UNREF(in0); return (int)(float(in1) + 1.0f + in2); }
169 // Reference for expression "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)"
170 inline IVec2    sequenceSideEffCase2 (bool in0, bool in1, const Vec2& in2)                                              { DE_UNREF(in1); return (in2 + Vec2(1.0f) + Vec2((float)in0)).asInt(); }
171 // Reference for expression "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++"
172 inline IVec4    sequenceSideEffCase3 (const Vec4& in0, const IVec4& in1, const BVec4& in2)              { return in1 + (in0 + Vec4((float)in2.x(), (float)in2.y(), (float)in2.z(), (float)in2.w())).asInt(); }
173
174 // ShaderEvalFunc-type wrappers for the above functions.
175 void evalSequenceNoSideEffCase0 (ShaderEvalContext& ctx) { ctx.color            = sequenceNoSideEffCase0(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0), ctx.in[2].swizzle(0, 3, 2, 1)); }
176 void evalSequenceNoSideEffCase1 (ShaderEvalContext& ctx) { ctx.color.x()        = (float)sequenceNoSideEffCase1(ctx.in[0].z(), (int)ctx.in[1].x(), ctx.in[2].y()); }
177 void evalSequenceNoSideEffCase2 (ShaderEvalContext& ctx) { ctx.color.yz()       = sequenceNoSideEffCase2(ctx.in[0].z() > 0.0f, ctx.in[1].x() > 0.0f, ctx.in[2].swizzle(2, 1)).asFloat(); }
178 void evalSequenceNoSideEffCase3 (ShaderEvalContext& ctx) { ctx.color            = sequenceNoSideEffCase3(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0).asInt(), greaterThan(ctx.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f))).asFloat(); }
179 void evalSequenceSideEffCase0   (ShaderEvalContext& ctx) { ctx.color            = sequenceSideEffCase0(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0), ctx.in[2].swizzle(0, 3, 2, 1)); }
180 void evalSequenceSideEffCase1   (ShaderEvalContext& ctx) { ctx.color.x()        = (float)sequenceSideEffCase1(ctx.in[0].z(), (int)ctx.in[1].x(), ctx.in[2].y()); }
181 void evalSequenceSideEffCase2   (ShaderEvalContext& ctx) { ctx.color.yz()       = sequenceSideEffCase2(ctx.in[0].z() > 0.0f, ctx.in[1].x() > 0.0f, ctx.in[2].swizzle(2, 1)).asFloat(); }
182 void evalSequenceSideEffCase3   (ShaderEvalContext& ctx) { ctx.color            = sequenceSideEffCase3(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0).asInt(), greaterThan(ctx.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f))).asFloat(); }
183
184 enum
185 {
186         MAX_INPUTS = 3
187 };
188
189 enum PrecisionMask
190 {
191         PRECMASK_NA                             = 0,                                            //!< Precision not applicable (booleans)
192         PRECMASK_LOWP                   = (1<<PRECISION_LOWP),
193         PRECMASK_MEDIUMP                = (1<<PRECISION_MEDIUMP),
194         PRECMASK_HIGHP                  = (1<<PRECISION_HIGHP),
195
196         PRECMASK_MEDIUMP_HIGHP  = (1<<PRECISION_MEDIUMP) | (1<<PRECISION_HIGHP),
197         PRECMASK_ALL                    = (1<<PRECISION_LOWP) | (1<<PRECISION_MEDIUMP) | (1<<PRECISION_HIGHP)
198 };
199
200 enum ValueType
201 {
202         VALUE_NONE                      = 0,
203         VALUE_FLOAT                     = (1<<0),       // float scalar
204         VALUE_FLOAT_VEC         = (1<<1),       // float vector
205         VALUE_FLOAT_GENTYPE     = (1<<2),       // float scalar/vector
206         VALUE_VEC3                      = (1<<3),       // vec3 only
207         VALUE_MATRIX            = (1<<4),       // matrix
208         VALUE_BOOL                      = (1<<5),       // boolean scalar
209         VALUE_BOOL_VEC          = (1<<6),       // boolean vector
210         VALUE_BOOL_GENTYPE      = (1<<7),       // boolean scalar/vector
211         VALUE_INT                       = (1<<8),       // int scalar
212         VALUE_INT_VEC           = (1<<9),       // int vector
213         VALUE_INT_GENTYPE       = (1<<10),      // int scalar/vector
214
215         // Shorthands.
216         F                               = VALUE_FLOAT,
217         FV                              = VALUE_FLOAT_VEC,
218         GT                              = VALUE_FLOAT_GENTYPE,
219         V3                              = VALUE_VEC3,
220         M                               = VALUE_MATRIX,
221         B                               = VALUE_BOOL,
222         BV                              = VALUE_BOOL_VEC,
223         BGT                             = VALUE_BOOL_GENTYPE,
224         I                               = VALUE_INT,
225         IV                              = VALUE_INT_VEC,
226         IGT                             = VALUE_INT_GENTYPE
227 };
228
229 static inline bool isScalarType (ValueType type)
230 {
231         return type == VALUE_FLOAT || type == VALUE_BOOL || type == VALUE_INT;
232 }
233
234 struct Value
235 {
236         Value (ValueType valueType_, float rangeMin_, float rangeMax_)
237                 : valueType     (valueType_)
238                 , rangeMin      (rangeMin_)
239                 , rangeMax      (rangeMax_)
240         {
241         }
242
243         ValueType       valueType;
244         float           rangeMin;
245         float           rangeMax;
246 };
247
248 enum OperationType
249 {
250         FUNCTION = 0,
251         OPERATOR,
252         SIDE_EFFECT_OPERATOR // Test the side-effect (as opposed to the result) of a side-effect operator.
253 };
254
255 struct BuiltinFuncInfo
256 {
257         BuiltinFuncInfo (const char* caseName_, const char* shaderFuncName_, ValueType outValue_, Value input0_, Value input1_, Value input2_, float resultScale_, float resultBias_, deUint32 precisionMask_, ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_, OperationType type_=FUNCTION, bool isUnaryPrefix_=true)
258                 : caseName                      (caseName_)
259                 , shaderFuncName        (shaderFuncName_)
260                 , outValue                      (outValue_)
261                 , input0                        (input0_)
262                 , input1                        (input1_)
263                 , input2                        (input2_)
264                 , resultScale           (resultScale_)
265                 , resultBias            (resultBias_)
266                 , precisionMask         (precisionMask_)
267                 , evalFuncScalar        (evalFuncScalar_)
268                 , evalFuncVec2          (evalFuncVec2_)
269                 , evalFuncVec3          (evalFuncVec3_)
270                 , evalFuncVec4          (evalFuncVec4_)
271                 , type                          (type_)
272                 , isUnaryPrefix         (isUnaryPrefix_)
273         {
274         }
275
276         const char*             caseName;                       //!< Name of case.
277         const char*             shaderFuncName;         //!< Name in shading language.
278         ValueType               outValue;
279         Value                   input0;
280         Value                   input1;
281         Value                   input2;
282         float                   resultScale;
283         float                   resultBias;
284         deUint32                precisionMask;
285         ShaderEvalFunc  evalFuncScalar;
286         ShaderEvalFunc  evalFuncVec2;
287         ShaderEvalFunc  evalFuncVec3;
288         ShaderEvalFunc  evalFuncVec4;
289         OperationType   type;
290         bool                    isUnaryPrefix;          //!< Whether a unary operator is a prefix operator; redundant unless unary.
291 };
292
293 static inline BuiltinFuncInfo BuiltinOperInfo (const char* caseName_, const char* shaderFuncName_, ValueType outValue_, Value input0_, Value input1_, Value input2_, float resultScale_, float resultBias_, deUint32 precisionMask_, ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
294 {
295         return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, OPERATOR);
296 }
297
298 // For postfix (unary) operators.
299 static inline BuiltinFuncInfo BuiltinPostOperInfo (const char* caseName_, const char* shaderFuncName_, ValueType outValue_, Value input0_, Value input1_, Value input2_, float resultScale_, float resultBias_, deUint32 precisionMask_, ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
300 {
301         return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, OPERATOR, false);
302 }
303
304 static inline BuiltinFuncInfo BuiltinSideEffOperInfo (const char* caseName_, const char* shaderFuncName_, ValueType outValue_, Value input0_, Value input1_, Value input2_, float resultScale_, float resultBias_, deUint32 precisionMask_, ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
305 {
306         return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, SIDE_EFFECT_OPERATOR);
307 }
308
309 // For postfix (unary) operators, testing side-effect.
310 static inline BuiltinFuncInfo BuiltinPostSideEffOperInfo (const char* caseName_, const char* shaderFuncName_, ValueType outValue_, Value input0_, Value input1_, Value input2_, float resultScale_, float resultBias_, deUint32 precisionMask_, ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
311 {
312         return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, SIDE_EFFECT_OPERATOR, false);
313 }
314
315 // BuiltinFuncGroup
316
317 struct BuiltinFuncGroup
318 {
319                                                 BuiltinFuncGroup        (const char* name_, const char* description_) : name(name_), description(description_) {}
320         BuiltinFuncGroup&       operator<<                      (const BuiltinFuncInfo& info) { funcInfos.push_back(info); return *this; }
321
322         const char*                                             name;
323         const char*                                             description;
324         std::vector<BuiltinFuncInfo>    funcInfos;
325 };
326
327 static const char* s_inSwizzles[MAX_INPUTS][4] =
328 {
329         { "z", "wy", "zxy", "yzwx" },
330         { "x", "yx", "yzx", "wzyx" },
331         { "y", "zy", "wyz", "xwzy" }
332 };
333
334 static const char* s_outSwizzles[]      = { "x", "yz", "xyz", "xyzw" };
335
336 // OperatorShaderEvaluator
337
338 class OperatorShaderEvaluator : public ShaderEvaluator
339 {
340 public:
341         OperatorShaderEvaluator (ShaderEvalFunc evalFunc, float scale, float bias)
342         {
343                 m_evalFunc      = evalFunc;
344                 m_scale         = scale;
345                 m_bias          = bias;
346         }
347
348         virtual ~OperatorShaderEvaluator (void)
349         {
350         }
351
352         virtual void evaluate (ShaderEvalContext& ctx)
353         {
354                 m_evalFunc(ctx);
355                 ctx.color = ctx.color * m_scale + m_bias;
356         }
357
358 private:
359         ShaderEvalFunc  m_evalFunc;
360         float                   m_scale;
361         float                   m_bias;
362 };
363
364 // Concrete value.
365
366 struct ShaderValue
367 {
368         ShaderValue (DataType type_, float rangeMin_, float rangeMax_)
369                 : type          (type_)
370                 , rangeMin      (rangeMin_)
371                 , rangeMax      (rangeMax_)
372         {
373         }
374
375         ShaderValue (void)
376                 : type          (TYPE_LAST)
377                 , rangeMin      (0.0f)
378                 , rangeMax      (0.0f)
379         {
380         }
381
382         DataType        type;
383         float           rangeMin;
384         float           rangeMax;
385 };
386
387 struct ShaderDataSpec
388 {
389         ShaderDataSpec (void)
390                 : resultScale   (1.0f)
391                 , resultBias    (0.0f)
392                 , precision             (PRECISION_LAST)
393                 , output                (TYPE_LAST)
394                 , numInputs             (0)
395         {
396         }
397
398         float                   resultScale;
399         float                   resultBias;
400         Precision               precision;
401         DataType                output;
402         int                             numInputs;
403         ShaderValue             inputs[MAX_INPUTS];
404 };
405
406 // ShaderOperatorCase
407
408 class ShaderOperatorCase : public ShaderRenderCase
409 {
410 public:
411                                                                 ShaderOperatorCase              (Context& context, const char* caseName, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, const char* shaderOp, const ShaderDataSpec& spec);
412         virtual                                         ~ShaderOperatorCase             (void);
413
414 private:
415                                                                 ShaderOperatorCase              (const ShaderOperatorCase&);    // not allowed!
416         ShaderOperatorCase&                     operator=                               (const ShaderOperatorCase&);    // not allowed!
417
418         OperatorShaderEvaluator         m_evaluator;
419 };
420
421 ShaderOperatorCase::ShaderOperatorCase (Context& context, const char* caseName, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, const char* shaderOp, const ShaderDataSpec& spec)
422         : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), caseName, description, isVertexCase, m_evaluator)
423         , m_evaluator(evalFunc, spec.resultScale, spec.resultBias)
424 {
425         const char*             precision       = spec.precision != PRECISION_LAST ? getPrecisionName(spec.precision) : DE_NULL;
426         const char*             inputPrecision[MAX_INPUTS];
427
428         ostringstream   vtx;
429         ostringstream   frag;
430         ostringstream&  op                      = isVertexCase ? vtx : frag;
431
432         // Compute precision for inputs.
433         for (int i = 0; i < spec.numInputs; i++)
434         {
435                 bool            isBoolVal       = de::inRange<int>(spec.inputs[i].type, TYPE_BOOL, TYPE_BOOL_VEC4);
436                 bool            isIntVal        = de::inRange<int>(spec.inputs[i].type, TYPE_INT, TYPE_INT_VEC4);
437                 // \note Mediump interpolators are used for booleans and lowp ints.
438                 Precision       prec            = isBoolVal || (isIntVal && spec.precision == PRECISION_LOWP) ? PRECISION_MEDIUMP : spec.precision;
439                 inputPrecision[i] = getPrecisionName(prec);
440         }
441
442         // Attributes.
443         vtx << "attribute highp vec4 a_position;\n";
444         for (int i = 0; i < spec.numInputs; i++)
445                 vtx << "attribute " << inputPrecision[i] << " vec4 a_in" << i << ";\n";
446
447         if (isVertexCase)
448         {
449                 vtx << "varying mediump vec4 v_color;\n";
450                 frag << "varying mediump vec4 v_color;\n";
451         }
452         else
453         {
454                 for (int i = 0; i < spec.numInputs; i++)
455                 {
456                         vtx << "varying " << inputPrecision[i] << " vec4 v_in" << i << ";\n";
457                         frag << "varying " << inputPrecision[i] << " vec4 v_in" << i << ";\n";
458                 }
459         }
460
461         vtx << "\n";
462         vtx << "void main()\n";
463         vtx << "{\n";
464         vtx << "        gl_Position = a_position;\n";
465
466         frag << "\n";
467         frag << "void main()\n";
468         frag << "{\n";
469
470         // Expression inputs.
471         string prefix = isVertexCase ? "a_" : "v_";
472         for (int i = 0; i < spec.numInputs; i++)
473         {
474                 DataType                inType          = spec.inputs[i].type;
475                 int                             inSize          = getDataTypeScalarSize(inType);
476                 bool                    isInt           = de::inRange<int>(inType, TYPE_INT, TYPE_INT_VEC4);
477                 bool                    isBool          = de::inRange<int>(inType, TYPE_BOOL, TYPE_BOOL_VEC4);
478                 const char*             typeName        = getDataTypeName(inType);
479                 const char*             swizzle         = s_inSwizzles[i][inSize-1];
480
481                 op << "\t";
482                 if (precision && !isBool) op << precision << " ";
483
484                 op << typeName << " in" << i << " = ";
485
486                 if (isBool)
487                 {
488                         if (inSize == 1)        op << "(";
489                         else                            op << "greaterThan(";
490                 }
491                 else if (isInt)
492                         op << typeName << "(";
493
494                 op << prefix << "in" << i << "." << swizzle;
495
496                 if (isBool)
497                 {
498                         if (inSize == 1)        op << " > 0.0)";
499                         else                            op << ", vec" << inSize << "(0.0))";
500                 }
501                 else if (isInt)
502                         op << ")";
503
504                 op << ";\n";
505         }
506
507         // Result variable.
508         {
509                 const char* outTypeName = getDataTypeName(spec.output);
510                 bool            isBoolOut       = de::inRange<int>(spec.output, TYPE_BOOL, TYPE_BOOL_VEC4);
511
512                 op << "\t";
513                 if (precision && !isBoolOut) op << precision << " ";
514                 op << outTypeName << " res = " << outTypeName << "(0.0);\n\n";
515         }
516
517         // Expression.
518         op << "\t" << shaderOp << "\n\n";
519
520         // Convert to color.
521         bool    isResFloatVec   = de::inRange<int>(spec.output, TYPE_FLOAT, TYPE_FLOAT_VEC4);
522         int             outScalarSize   = getDataTypeScalarSize(spec.output);
523
524         op << "\tmediump vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n";
525         op << "\tcolor." << s_outSwizzles[outScalarSize-1] << " = ";
526
527         if (!isResFloatVec && outScalarSize == 1)
528                 op << "float(res)";
529         else if (!isResFloatVec)
530                 op << "vec" << outScalarSize << "(res)";
531         else
532                 op << "res";
533
534         op << ";\n";
535
536         // Scale & bias.
537         float   resultScale             = spec.resultScale;
538         float   resultBias              = spec.resultBias;
539         if ((resultScale != 1.0f) || (resultBias != 0.0f))
540         {
541                 op << "\tcolor = color";
542                 if (resultScale != 1.0f) op << " * " << de::floatToString(resultScale, 2);
543                 if (resultBias != 0.0f)  op << " + " << de::floatToString(resultBias, 2);
544                 op << ";\n";
545         }
546
547         // ..
548         if (isVertexCase)
549         {
550                 vtx << "        v_color = color;\n";
551                 frag << "       gl_FragColor = v_color;\n";
552         }
553         else
554         {
555                 for (int i = 0; i < spec.numInputs; i++)
556                 vtx << "        v_in" << i << " = a_in" << i << ";\n";
557                 frag << "       gl_FragColor = color;\n";
558         }
559
560         vtx << "}\n";
561         frag << "}\n";
562
563         m_vertShaderSource = vtx.str();
564         m_fragShaderSource = frag.str();
565
566         // Setup the user attributes.
567         m_userAttribTransforms.resize(spec.numInputs);
568         for (int inputNdx = 0; inputNdx < spec.numInputs; inputNdx++)
569         {
570                 const ShaderValue& v = spec.inputs[inputNdx];
571                 DE_ASSERT(v.type != TYPE_LAST);
572
573                 float scale             = (v.rangeMax - v.rangeMin);
574                 float minBias   = v.rangeMin;
575                 float maxBias   = v.rangeMax;
576                 Mat4  attribMatrix;
577
578                 for (int rowNdx = 0; rowNdx < 4; rowNdx++)
579                 {
580                         Vec4 row;
581
582                         switch ((rowNdx + inputNdx) % 4)
583                         {
584                                 case 0: row = Vec4(scale, 0.0f, 0.0f, minBias);         break;
585                                 case 1: row = Vec4(0.0f, scale, 0.0f, minBias);         break;
586                                 case 2: row = Vec4(-scale, 0.0f, 0.0f, maxBias);        break;
587                                 case 3: row = Vec4(0.0f, -scale, 0.0f, maxBias);        break;
588                                 default: DE_ASSERT(false);
589                         }
590
591                         attribMatrix.setRow(rowNdx, row);
592                 }
593
594                 m_userAttribTransforms[inputNdx] = attribMatrix;
595         }
596 }
597
598 ShaderOperatorCase::~ShaderOperatorCase (void)
599 {
600 }
601
602 // ShaderOperatorTests.
603
604 ShaderOperatorTests::ShaderOperatorTests(Context& context)
605         : TestCaseGroup(context, "operator", "Operator tests.")
606 {
607 }
608
609 ShaderOperatorTests::~ShaderOperatorTests (void)
610 {
611 }
612
613 // Vector math functions.
614 template<typename T> inline T nop (T f) { return f; }
615
616 template <typename T, int Size>
617 Vector<T, Size> nop (const Vector<T, Size>& v) { return v; }
618
619 #define DECLARE_UNARY_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                                  \
620         void eval_##FUNC_NAME##_float   (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(2)).x(); }                  \
621         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1)); }           \
622         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1)); }        \
623         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0)); }
624
625 #define DECLARE_BINARY_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                 \
626         void eval_##FUNC_NAME##_float   (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(2),          c.in[1].swizzle(0)).x(); }                     \
627         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1),       c.in[1].swizzle(1, 0)); }                      \
628         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1),    c.in[1].swizzle(1, 2, 0)); }           \
629         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); }
630
631 #define DECLARE_TERNARY_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                                                                        \
632         void eval_##FUNC_NAME##_float   (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(2),          c.in[1].swizzle(0),          c.in[2].swizzle(1)).x(); }                \
633         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1),       c.in[1].swizzle(1, 0),       c.in[2].swizzle(2, 1)); }                 \
634         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { 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)); }              \
635         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { 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)); }
636
637 #define DECLARE_UNARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                   \
638         void eval_##FUNC_NAME##_float   (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(2)); }                      \
639         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(3, 1)); }           \
640         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(2, 0, 1)); }        \
641         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0)); }
642
643 #define DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                                                                                  \
644         void eval_##FUNC_NAME##_float   (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(2),          c.in[1].swizzle(0)); }                         \
645         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(3, 1),       c.in[1].swizzle(1, 0)); }                      \
646         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(2, 0, 1),    c.in[1].swizzle(1, 2, 0)); }           \
647         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color.x()    = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); }
648
649 #define DECLARE_BINARY_BOOL_FUNCS(FUNC_NAME)                                                                                                                                            \
650         void eval_##FUNC_NAME##_bool    (ShaderEvalContext& c) { c.color.x()    = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f); }
651
652 #define DECLARE_UNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                     \
653         void eval_##FUNC_NAME##_bool    (ShaderEvalContext& c) { c.color.x()    = (float)FUNC_NAME(c.in[0].z() > 0.0f); }                                                                               \
654         void eval_##FUNC_NAME##_bvec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat(); }                \
655         void eval_##FUNC_NAME##_bvec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat(); }             \
656         void eval_##FUNC_NAME##_bvec4   (ShaderEvalContext& c) { c.color                = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f))).asFloat(); }
657
658 #define DECLARE_TERNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                                                                                                                                                                                                                                   \
659         void eval_##FUNC_NAME##_bool    (ShaderEvalContext& c) { c.color.x()    = (float)FUNC_NAME(c.in[0].z() > 0.0f,                            c.in[1].x() > 0.0f,                                   c.in[2].y() > 0.0f); }                                                                                          \
660         void eval_##FUNC_NAME##_bvec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)),       greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f)),       greaterThan(c.in[2].swizzle(2, 1), Vec2(0.0f))).asFloat(); }            \
661         void eval_##FUNC_NAME##_bvec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)),    greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f)),    greaterThan(c.in[2].swizzle(3, 1, 2), Vec3(0.0f))).asFloat(); }         \
662         void eval_##FUNC_NAME##_bvec4   (ShaderEvalContext& c) { c.color                = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)), greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f)), greaterThan(c.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f))).asFloat(); }
663
664 #define DECLARE_UNARY_INT_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                                                              \
665         void eval_##FUNC_NAME##_int             (ShaderEvalContext& c) { c.color.x()    = (float)FUNC_NAME((int)c.in[0].z()); }                                         \
666         void eval_##FUNC_NAME##_ivec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1).asInt()).asFloat(); }         \
667         void eval_##FUNC_NAME##_ivec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt()).asFloat(); }      \
668         void eval_##FUNC_NAME##_ivec4   (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt()).asFloat(); }
669
670 #define DECLARE_BINARY_INT_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                                                             \
671         void eval_##FUNC_NAME##_int             (ShaderEvalContext& c) { c.color.x()    = (float)tcu::FUNC_NAME((int)c.in[0].z(),                               (int)c.in[1].x()); }                                            \
672         void eval_##FUNC_NAME##_ivec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(),                      c.in[1].swizzle(1, 0).asInt()).asFloat(); }             \
673         void eval_##FUNC_NAME##_ivec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(),           c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); }  \
674         void eval_##FUNC_NAME##_ivec4   (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(),        c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); }
675
676 #define DECLARE_TERNARY_INT_GENTYPE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                                                                                                                            \
677         void eval_##FUNC_NAME##_int             (ShaderEvalContext& c) { c.color.x()    = (float)FUNC_NAME((int)c.in[0].z(),                 (int)c.in[1].x(),                (int)c.in[2].y()); }                                                              \
678         void eval_##FUNC_NAME##_ivec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(),       c.in[1].swizzle(1, 0).asInt(),       c.in[2].swizzle(2, 1).asInt()).asFloat(); }               \
679         void eval_##FUNC_NAME##_ivec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(),    c.in[1].swizzle(1, 2, 0).asInt(),    c.in[2].swizzle(3, 1, 2).asInt()).asFloat(); }    \
680         void eval_##FUNC_NAME##_ivec4   (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), c.in[1].swizzle(3, 2, 1, 0).asInt(), c.in[2].swizzle(0, 3, 2, 1).asInt()).asFloat(); }
681
682 #define DECLARE_VEC_FLOAT_FUNCS(FUNC_NAME) \
683         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1),                      c.in[1].x()); } \
684         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1),           c.in[1].x()); } \
685         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0),        c.in[1].x()); }
686
687 #define DECLARE_VEC_FLOAT_FLOAT_FUNCS(FUNC_NAME) \
688         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1),                      c.in[1].x(), c.in[2].y()); } \
689         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1),           c.in[1].x(), c.in[2].y()); } \
690         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0),        c.in[1].x(), c.in[2].y()); }
691
692 #define DECLARE_VEC_VEC_FLOAT_FUNCS(FUNC_NAME) \
693         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1),                      c.in[1].swizzle(1, 0),                  c.in[2].y()); } \
694         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1),           c.in[1].swizzle(1, 2, 0),               c.in[2].y()); } \
695         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0),        c.in[1].swizzle(3, 2, 1, 0),    c.in[2].y()); }
696
697 #define DECLARE_FLOAT_FLOAT_VEC_FUNCS(FUNC_NAME) \
698         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(2, 1)); }                 \
699         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(3, 1, 2)); }              \
700         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(0, 3, 2, 1)); }
701
702 #define DECLARE_FLOAT_VEC_FUNCS(FUNC_NAME) \
703         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].z(),                                        c.in[1].swizzle(1, 0)); } \
704         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].z(),                                        c.in[1].swizzle(1, 2, 0)); } \
705         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].z(),                                        c.in[1].swizzle(3, 2, 1, 0)); }
706
707 #define DECLARE_IVEC_INT_FUNCS(FUNC_NAME) \
708         void eval_##FUNC_NAME##_ivec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(),                      (int)c.in[1].x()).asFloat(); } \
709         void eval_##FUNC_NAME##_ivec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(),           (int)c.in[1].x()).asFloat(); } \
710         void eval_##FUNC_NAME##_ivec4   (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(),        (int)c.in[1].x()).asFloat(); }
711
712 #define DECLARE_INT_IVEC_FUNCS(FUNC_NAME) \
713         void eval_##FUNC_NAME##_ivec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME((int)c.in[0].z(),                                   c.in[1].swizzle(1, 0).asInt()).asFloat(); } \
714         void eval_##FUNC_NAME##_ivec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME((int)c.in[0].z(),                                   c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); } \
715         void eval_##FUNC_NAME##_ivec4   (ShaderEvalContext& c) { c.color                = FUNC_NAME((int)c.in[0].z(),                                   c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); }
716
717 // Operators.
718
719 DECLARE_UNARY_GENTYPE_FUNCS(nop)
720 DECLARE_UNARY_GENTYPE_FUNCS(negate)
721 DECLARE_UNARY_GENTYPE_FUNCS(addOne)
722 DECLARE_UNARY_GENTYPE_FUNCS(subOne)
723 DECLARE_BINARY_GENTYPE_FUNCS(add)
724 DECLARE_BINARY_GENTYPE_FUNCS(sub)
725 DECLARE_BINARY_GENTYPE_FUNCS(mul)
726 DECLARE_BINARY_GENTYPE_FUNCS(div)
727
728 void eval_selection_float       (ShaderEvalContext& c) { c.color.x()    = selection(c.in[0].z() > 0.0f,         c.in[1].x(),                                    c.in[2].y()); }
729 void eval_selection_vec2        (ShaderEvalContext& c) { c.color.yz()   = selection(c.in[0].z() > 0.0f,         c.in[1].swizzle(1, 0),                  c.in[2].swizzle(2, 1)); }
730 void eval_selection_vec3        (ShaderEvalContext& c) { c.color.xyz()  = selection(c.in[0].z() > 0.0f,         c.in[1].swizzle(1, 2, 0),               c.in[2].swizzle(3, 1, 2)); }
731 void eval_selection_vec4        (ShaderEvalContext& c) { 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)); }
732
733 DECLARE_UNARY_INT_GENTYPE_FUNCS(nop)
734 DECLARE_UNARY_INT_GENTYPE_FUNCS(negate)
735 DECLARE_UNARY_INT_GENTYPE_FUNCS(addOne)
736 DECLARE_UNARY_INT_GENTYPE_FUNCS(subOne)
737 DECLARE_BINARY_INT_GENTYPE_FUNCS(add)
738 DECLARE_BINARY_INT_GENTYPE_FUNCS(sub)
739 DECLARE_BINARY_INT_GENTYPE_FUNCS(mul)
740 DECLARE_BINARY_INT_GENTYPE_FUNCS(div)
741
742 void eval_selection_int         (ShaderEvalContext& c) { c.color.x()    = (float)selection(c.in[0].z() > 0.0f,  (int)c.in[1].x(),                                               (int)c.in[2].y()); }
743 void eval_selection_ivec2       (ShaderEvalContext& c) { c.color.yz()   = selection(c.in[0].z() > 0.0f,                 c.in[1].swizzle(1, 0).asInt(),                  c.in[2].swizzle(2, 1).asInt()).asFloat(); }
744 void eval_selection_ivec3       (ShaderEvalContext& c) { c.color.xyz()  = selection(c.in[0].z() > 0.0f,                 c.in[1].swizzle(1, 2, 0).asInt(),               c.in[2].swizzle(3, 1, 2).asInt()).asFloat(); }
745 void eval_selection_ivec4       (ShaderEvalContext& c) { 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()).asFloat(); }
746
747 DECLARE_UNARY_BOOL_GENTYPE_FUNCS(boolNot)
748 DECLARE_BINARY_BOOL_FUNCS(logicalAnd)
749 DECLARE_BINARY_BOOL_FUNCS(logicalOr)
750 DECLARE_BINARY_BOOL_FUNCS(logicalXor)
751
752 void eval_selection_bool        (ShaderEvalContext& c) { c.color.x()    = (float)selection(c.in[0].z() > 0.0f,  c.in[1].x() > 0.0f,                                                                                                             c.in[2].y() > 0.0f); }
753 void eval_selection_bvec2       (ShaderEvalContext& c) { c.color.yz()   = selection(c.in[0].z() > 0.0f,                 greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f, 0.0f)),                                   greaterThan(c.in[2].swizzle(2, 1), Vec2(0.0f, 0.0f))).asFloat(); }
754 void eval_selection_bvec3       (ShaderEvalContext& c) { 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)),                  greaterThan(c.in[2].swizzle(3, 1, 2), Vec3(0.0f, 0.0f, 0.0f))).asFloat(); }
755 void eval_selection_bvec4       (ShaderEvalContext& c) { 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)), greaterThan(c.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f))).asFloat(); }
756
757 DECLARE_VEC_FLOAT_FUNCS(addVecScalar)
758 DECLARE_VEC_FLOAT_FUNCS(subVecScalar)
759 DECLARE_VEC_FLOAT_FUNCS(mulVecScalar)
760 DECLARE_VEC_FLOAT_FUNCS(divVecScalar)
761
762 DECLARE_FLOAT_VEC_FUNCS(addScalarVec)
763 DECLARE_FLOAT_VEC_FUNCS(subScalarVec)
764 DECLARE_FLOAT_VEC_FUNCS(mulScalarVec)
765 DECLARE_FLOAT_VEC_FUNCS(divScalarVec)
766
767 DECLARE_IVEC_INT_FUNCS(addVecScalar)
768 DECLARE_IVEC_INT_FUNCS(subVecScalar)
769 DECLARE_IVEC_INT_FUNCS(mulVecScalar)
770 DECLARE_IVEC_INT_FUNCS(divVecScalar)
771
772 DECLARE_INT_IVEC_FUNCS(addScalarVec)
773 DECLARE_INT_IVEC_FUNCS(subScalarVec)
774 DECLARE_INT_IVEC_FUNCS(mulScalarVec)
775 DECLARE_INT_IVEC_FUNCS(divScalarVec)
776
777 // Built-in functions.
778
779 DECLARE_UNARY_GENTYPE_FUNCS(radians)
780 DECLARE_UNARY_GENTYPE_FUNCS(degrees)
781 DECLARE_UNARY_GENTYPE_FUNCS(sin)
782 DECLARE_UNARY_GENTYPE_FUNCS(cos)
783 DECLARE_UNARY_GENTYPE_FUNCS(tan)
784 DECLARE_UNARY_GENTYPE_FUNCS(asin)
785 DECLARE_UNARY_GENTYPE_FUNCS(acos)
786 DECLARE_UNARY_GENTYPE_FUNCS(atan)
787 DECLARE_BINARY_GENTYPE_FUNCS(atan2)
788
789 DECLARE_BINARY_GENTYPE_FUNCS(pow)
790 DECLARE_UNARY_GENTYPE_FUNCS(exp)
791 DECLARE_UNARY_GENTYPE_FUNCS(log)
792 DECLARE_UNARY_GENTYPE_FUNCS(exp2)
793 DECLARE_UNARY_GENTYPE_FUNCS(log2)
794 DECLARE_UNARY_GENTYPE_FUNCS(sqrt)
795 DECLARE_UNARY_GENTYPE_FUNCS(inverseSqrt)
796
797 DECLARE_UNARY_GENTYPE_FUNCS(abs)
798 DECLARE_UNARY_GENTYPE_FUNCS(sign)
799 DECLARE_UNARY_GENTYPE_FUNCS(floor)
800 DECLARE_UNARY_GENTYPE_FUNCS(ceil)
801 DECLARE_UNARY_GENTYPE_FUNCS(fract)
802 DECLARE_BINARY_GENTYPE_FUNCS(mod)
803 DECLARE_VEC_FLOAT_FUNCS(modVecFloat)
804 DECLARE_BINARY_GENTYPE_FUNCS(min)
805 DECLARE_VEC_FLOAT_FUNCS(minVecFloat)
806 DECLARE_BINARY_GENTYPE_FUNCS(max)
807 DECLARE_VEC_FLOAT_FUNCS(maxVecFloat)
808 DECLARE_TERNARY_GENTYPE_FUNCS(clamp)
809 DECLARE_VEC_FLOAT_FLOAT_FUNCS(clampVecFloatFloat)
810 DECLARE_TERNARY_GENTYPE_FUNCS(mix)
811 DECLARE_VEC_VEC_FLOAT_FUNCS(mixVecVecFloat)
812 DECLARE_BINARY_GENTYPE_FUNCS(step)
813 DECLARE_FLOAT_VEC_FUNCS(stepFloatVec)
814 DECLARE_TERNARY_GENTYPE_FUNCS(smoothStep)
815 DECLARE_FLOAT_FLOAT_VEC_FUNCS(smoothStepFloatFloatVec)
816
817 DECLARE_UNARY_SCALAR_GENTYPE_FUNCS(length)
818 DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(distance)
819 DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(dot)
820 void eval_cross_vec3 (ShaderEvalContext& c) { c.color.xyz()     = cross(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)); }
821
822 DECLARE_UNARY_GENTYPE_FUNCS(normalize)
823 DECLARE_TERNARY_GENTYPE_FUNCS(faceForward)
824 DECLARE_BINARY_GENTYPE_FUNCS(reflect)
825
826 void eval_refract_float (ShaderEvalContext& c) { c.color.x()    = refract(c.in[0].z(),                 c.in[1].x(),                 c.in[2].y()); }
827 void eval_refract_vec2  (ShaderEvalContext& c) { c.color.yz()   = refract(c.in[0].swizzle(3, 1),       c.in[1].swizzle(1, 0),       c.in[2].y()); }
828 void eval_refract_vec3  (ShaderEvalContext& c) { c.color.xyz()  = refract(c.in[0].swizzle(2, 0, 1),    c.in[1].swizzle(1, 2, 0),    c.in[2].y()); }
829 void eval_refract_vec4  (ShaderEvalContext& c) { c.color                = refract(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0), c.in[2].y()); }
830
831 // Compare functions.
832
833 #define DECLARE_FLOAT_COMPARE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                  \
834         void eval_##FUNC_NAME##_float   (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(c.in[0].z(),          c.in[1].x()); }                                           \
835         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(3, 1),       c.in[1].swizzle(1, 0)); }          \
836         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(2, 0, 1),    c.in[1].swizzle(1, 2, 0)); }       \
837         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); }
838
839 #define DECLARE_FLOAT_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                    \
840         void eval_##FUNC_NAME##_float   (ShaderEvalContext& c) { c.color.x()    = (float)FUNC_NAME(c.in[0].z(),          c.in[1].x()); }                                                        \
841         void eval_##FUNC_NAME##_vec2    (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(c.in[0].swizzle(3, 1),       c.in[1].swizzle(1, 0)).asFloat(); }            \
842         void eval_##FUNC_NAME##_vec3    (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(c.in[0].swizzle(2, 0, 1),    c.in[1].swizzle(1, 2, 0)).asFloat(); }         \
843         void eval_##FUNC_NAME##_vec4    (ShaderEvalContext& c) { c.color                = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)).asFloat(); }
844
845 #define DECLARE_INT_COMPARE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                                                                    \
846         void eval_##FUNC_NAME##_int             (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x())); }                                                                      \
847         void eval_##FUNC_NAME##_ivec2   (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].swizzle(3, 1)),       chopToInt(c.in[1].swizzle(1, 0))); }            \
848         void eval_##FUNC_NAME##_ivec3   (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].swizzle(2, 0, 1)),    chopToInt(c.in[1].swizzle(1, 2, 0))); }         \
849         void eval_##FUNC_NAME##_ivec4   (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].swizzle(1, 2, 3, 0)), chopToInt(c.in[1].swizzle(3, 2, 1, 0))); }
850
851 #define DECLARE_INT_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                                                                      \
852         void eval_##FUNC_NAME##_int             (ShaderEvalContext& c) { c.color.x()    = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x())); }                                                                   \
853         void eval_##FUNC_NAME##_ivec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(chopToInt(c.in[0].swizzle(3, 1)),       chopToInt(c.in[1].swizzle(1, 0))).asFloat(); }              \
854         void eval_##FUNC_NAME##_ivec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(chopToInt(c.in[0].swizzle(2, 0, 1)),    chopToInt(c.in[1].swizzle(1, 2, 0))).asFloat(); }   \
855         void eval_##FUNC_NAME##_ivec4   (ShaderEvalContext& c) { c.color                = FUNC_NAME(chopToInt(c.in[0].swizzle(1, 2, 3, 0)), chopToInt(c.in[1].swizzle(3, 2, 1, 0))).asFloat(); }
856
857 #define DECLARE_BOOL_COMPARE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                                                                                                                           \
858         void eval_##FUNC_NAME##_bool    (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f); }                                                                                                                                              \
859         void eval_##FUNC_NAME##_bvec2   (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)),       greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f))); }                \
860         void eval_##FUNC_NAME##_bvec3   (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)),    greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f))); }             \
861         void eval_##FUNC_NAME##_bvec4   (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)), greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f))); }
862
863 #define DECLARE_BOOL_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                                                                                                                                                                                                                                                                                             \
864         void eval_##FUNC_NAME##_bool    (ShaderEvalContext& c) { c.color.x()    = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f); }                                                                                                                                           \
865         void eval_##FUNC_NAME##_bvec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)),       greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f))).asFloat(); }          \
866         void eval_##FUNC_NAME##_bvec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)),    greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f))).asFloat(); }       \
867         void eval_##FUNC_NAME##_bvec4   (ShaderEvalContext& c) { c.color                = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)), greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f))).asFloat(); }
868
869 DECLARE_FLOAT_COMPARE_FUNCS(allEqual)
870 DECLARE_FLOAT_COMPARE_FUNCS(anyNotEqual)
871 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThan)
872 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThanEqual)
873 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThan)
874 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThanEqual)
875 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(equal)
876 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(notEqual)
877
878 DECLARE_INT_COMPARE_FUNCS(allEqual)
879 DECLARE_INT_COMPARE_FUNCS(anyNotEqual)
880 DECLARE_INT_CWISE_COMPARE_FUNCS(lessThan)
881 DECLARE_INT_CWISE_COMPARE_FUNCS(lessThanEqual)
882 DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThan)
883 DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThanEqual)
884 DECLARE_INT_CWISE_COMPARE_FUNCS(equal)
885 DECLARE_INT_CWISE_COMPARE_FUNCS(notEqual)
886
887 DECLARE_BOOL_COMPARE_FUNCS(allEqual)
888 DECLARE_BOOL_COMPARE_FUNCS(anyNotEqual)
889 DECLARE_BOOL_CWISE_COMPARE_FUNCS(equal)
890 DECLARE_BOOL_CWISE_COMPARE_FUNCS(notEqual)
891
892 // Boolean functions.
893
894 #define DECLARE_UNARY_SCALAR_BVEC_FUNCS(GLSL_NAME, FUNC_NAME)                                                                                                                                                                                           \
895         void eval_##GLSL_NAME##_bvec2   (ShaderEvalContext& c) { c.color.x()    = float(FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)))); }           \
896         void eval_##GLSL_NAME##_bvec3   (ShaderEvalContext& c) { c.color.x()    = float(FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)))); }                \
897         void eval_##GLSL_NAME##_bvec4   (ShaderEvalContext& c) { c.color.x()    = float(FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)))); }
898
899 #define DECLARE_UNARY_BVEC_BVEC_FUNCS(GLSL_NAME, FUNC_NAME)                                                                                                                                                                                                     \
900         void eval_##GLSL_NAME##_bvec2   (ShaderEvalContext& c) { c.color.yz()   = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat(); }                \
901         void eval_##GLSL_NAME##_bvec3   (ShaderEvalContext& c) { c.color.xyz()  = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat(); }     \
902         void eval_##GLSL_NAME##_bvec4   (ShaderEvalContext& c) { c.color.xyzw() = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f))).asFloat(); }
903
904 DECLARE_UNARY_SCALAR_BVEC_FUNCS(any, boolAny);
905 DECLARE_UNARY_SCALAR_BVEC_FUNCS(all, boolAll);
906
907 void ShaderOperatorTests::init (void)
908 {
909         // Requisites:
910         // - input types (const, uniform, dynamic, mixture)
911         // - data types (bool, int, float, vecs, mats)
912         // -
913         // - complex expressions (\todo [petri] move to expressions?)
914         //   * early-exit from side effects
915         //   * precedence
916
917         // unary plus, minus
918         // add, sub
919         // mul (larger range)
920         // div (div-by-zero)
921         // incr, decr (int only)
922         // relational
923         // equality
924         // logical
925         // selection
926         // assignment
927         // arithmetic assignment
928
929         // parenthesis
930         // sequence
931         // subscript, function call, field selector/swizzler
932
933         // precedence
934         // data types (float, int, bool, vecs, matrices)
935
936 //      TestCaseGroup* group = new TestCaseGroup(m_testCtx, "additive", "Additive operator tests.");
937 //      addChild(group);
938
939         // * * *
940
941         // Built-in functions
942         // - precision, data types
943
944         #define BOOL_FUNCS(FUNC_NAME)                   eval_##FUNC_NAME##_bool, DE_NULL, DE_NULL, DE_NULL
945
946         #define FLOAT_VEC_FUNCS(FUNC_NAME)              DE_NULL, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
947         #define INT_VEC_FUNCS(FUNC_NAME)                DE_NULL, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
948         #define BOOL_VEC_FUNCS(FUNC_NAME)               DE_NULL, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
949
950         #define FLOAT_GENTYPE_FUNCS(FUNC_NAME)  eval_##FUNC_NAME##_float, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
951         #define INT_GENTYPE_FUNCS(FUNC_NAME)    eval_##FUNC_NAME##_int, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
952         #define BOOL_GENTYPE_FUNCS(FUNC_NAME)   eval_##FUNC_NAME##_bool, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
953
954         Value notUsed = Value(VALUE_NONE, 0.0f, 0.0f);
955
956         std::vector<BuiltinFuncGroup> funcInfoGroups;
957
958         // Unary operators.
959         funcInfoGroups.push_back(
960                 BuiltinFuncGroup("unary_operator", "Unary operator tests")
961                 << BuiltinOperInfo("plus",      "+",    GT,             Value(GT,  -1.0f, 1.0f),        notUsed,                                        notUsed,        0.5f, 0.5f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(nop))
962                 << BuiltinOperInfo("plus",      "+",    IGT,    Value(IGT, -5.0f, 5.0f),        notUsed,                                        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(nop))
963                 << BuiltinOperInfo("minus",     "-",    GT,             Value(GT,  -1.0f, 1.0f),        notUsed,                                        notUsed,        0.5f, 0.5f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(negate))
964                 << BuiltinOperInfo("minus",     "-",    IGT,    Value(IGT, -5.0f, 5.0f),        notUsed,                                        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(negate))
965                 << BuiltinOperInfo("not",       "!",    B,              Value(B,   -1.0f, 1.0f),        notUsed,                                        notUsed,        1.0f, 0.0f,             PRECMASK_NA,    eval_boolNot_bool, DE_NULL, DE_NULL, DE_NULL)
966
967                 // Pre/post incr/decr side effect cases.
968                 << BuiltinSideEffOperInfo               ("pre_increment_effect",        "++",   GT,             Value(GT,       -1.0f, 1.0f),   notUsed,        notUsed,        0.5f, 0.0f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(addOne))
969                 << BuiltinSideEffOperInfo               ("pre_increment_effect",        "++",   IGT,    Value(IGT,      -6.0f, 4.0f),   notUsed,        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(addOne))
970                 << BuiltinSideEffOperInfo               ("pre_decrement_effect",        "--",   GT,             Value(GT,       -1.0f, 1.0f),   notUsed,        notUsed,        0.5f, 1.0f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(subOne))
971                 << BuiltinSideEffOperInfo               ("pre_decrement_effect",        "--",   IGT,    Value(IGT,      -4.0f, 6.0f),   notUsed,        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(subOne))
972                 << BuiltinPostSideEffOperInfo   ("post_increment_effect",       "++",   GT,             Value(GT,       -1.0f, 1.0f),   notUsed,        notUsed,        0.5f, 0.0f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(addOne))
973                 << BuiltinPostSideEffOperInfo   ("post_increment_effect",       "++",   IGT,    Value(IGT,      -6.0f, 4.0f),   notUsed,        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(addOne))
974                 << BuiltinPostSideEffOperInfo   ("post_decrement_effect",       "--",   GT,             Value(GT,       -1.0f, 1.0f),   notUsed,        notUsed,        0.5f, 1.0f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(subOne))
975                 << BuiltinPostSideEffOperInfo   ("post_decrement_effect",       "--",   IGT,    Value(IGT,      -4.0f, 6.0f),   notUsed,        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(subOne))
976
977                 // Pre/post incr/decr result cases.
978                 << BuiltinOperInfo                              ("pre_increment_result",        "++",   GT,             Value(GT,       -1.0f, 1.0f),   notUsed,        notUsed,        0.5f, 0.0f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(addOne))
979                 << BuiltinOperInfo                              ("pre_increment_result",        "++",   IGT,    Value(IGT,      -6.0f, 4.0f),   notUsed,        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(addOne))
980                 << BuiltinOperInfo                              ("pre_decrement_result",        "--",   GT,             Value(GT,       -1.0f, 1.0f),   notUsed,        notUsed,        0.5f, 1.0f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(subOne))
981                 << BuiltinOperInfo                              ("pre_decrement_result",        "--",   IGT,    Value(IGT,      -4.0f, 6.0f),   notUsed,        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(subOne))
982                 << BuiltinPostOperInfo                  ("post_increment_result",       "++",   GT,             Value(GT,       -1.0f, 1.0f),   notUsed,        notUsed,        0.5f, 0.5f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(nop))
983                 << BuiltinPostOperInfo                  ("post_increment_result",       "++",   IGT,    Value(IGT,      -5.0f, 5.0f),   notUsed,        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(nop))
984                 << BuiltinPostOperInfo                  ("post_decrement_result",       "--",   GT,             Value(GT,       -1.0f, 1.0f),   notUsed,        notUsed,        0.5f, 0.5f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(nop))
985                 << BuiltinPostOperInfo                  ("post_decrement_result",       "--",   IGT,    Value(IGT,      -5.0f, 5.0f),   notUsed,        notUsed,        0.1f, 0.5f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(nop))
986         );
987
988         // Binary operators.
989         funcInfoGroups.push_back(
990                 BuiltinFuncGroup("binary_operator", "Binary operator tests")
991                 // Arithmetic operators.
992                 << BuiltinOperInfo("add",       "+",    GT,             Value(GT,  -1.0f,   1.0f),      Value(GT,  -1.0f,  1.0f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(add))
993                 << BuiltinOperInfo("add",       "+",    IGT,    Value(IGT, -4.0f,   6.0f),      Value(IGT, -6.0f,  5.0f),       notUsed,        0.1f,           0.5f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(add))
994                 << BuiltinOperInfo("add",       "+",    FV,             Value(FV,  -1.0f,   1.0f),      Value(F,   -1.0f,  1.0f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(addVecScalar))
995                 << BuiltinOperInfo("add",       "+",    IV,             Value(IV,  -4.0f,   6.0f),      Value(I,   -6.0f,  5.0f),       notUsed,        0.1f,           0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(addVecScalar))
996                 << BuiltinOperInfo("add",       "+",    FV,             Value(F,   -1.0f,   1.0f),      Value(FV,  -1.0f,  1.0f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(addScalarVec))
997                 << BuiltinOperInfo("add",       "+",    IV,             Value(I,   -4.0f,   6.0f),      Value(IV,  -6.0f,  5.0f),       notUsed,        0.1f,           0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(addScalarVec))
998                 << BuiltinOperInfo("sub",       "-",    GT,             Value(GT,  -1.0f,   1.0f),      Value(GT,  -1.0f,  1.0f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(sub))
999                 << BuiltinOperInfo("sub",       "-",    IGT,    Value(IGT, -4.0f,   6.0f),      Value(IGT, -6.0f,  5.0f),       notUsed,        0.1f,           0.5f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(sub))
1000                 << BuiltinOperInfo("sub",       "-",    FV,             Value(FV,  -1.0f,   1.0f),      Value(F,   -1.0f,  1.0f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(subVecScalar))
1001                 << BuiltinOperInfo("sub",       "-",    IV,             Value(IV,  -4.0f,   6.0f),      Value(I,   -6.0f,  5.0f),       notUsed,        0.1f,           0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(subVecScalar))
1002                 << BuiltinOperInfo("sub",       "-",    FV,             Value(F,   -1.0f,   1.0f),      Value(FV,  -1.0f,  1.0f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(subScalarVec))
1003                 << BuiltinOperInfo("sub",       "-",    IV,             Value(I,   -4.0f,   6.0f),      Value(IV,  -6.0f,  5.0f),       notUsed,        0.1f,           0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(subScalarVec))
1004                 << BuiltinOperInfo("mul",       "*",    GT,             Value(GT,  -1.0f,   1.0f),      Value(GT,  -1.0f,  1.0f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(mul))
1005                 << BuiltinOperInfo("mul",       "*",    IGT,    Value(IGT, -4.0f,   6.0f),      Value(IGT, -6.0f,  5.0f),       notUsed,        0.1f,           0.5f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(mul))
1006                 << BuiltinOperInfo("mul",       "*",    FV,             Value(FV,  -1.0f,   1.0f),      Value(F,   -1.0f,  1.0f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(mulVecScalar))
1007                 << BuiltinOperInfo("mul",       "*",    IV,             Value(IV,  -4.0f,   6.0f),      Value(I,   -6.0f,  5.0f),       notUsed,        0.1f,           0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(mulVecScalar))
1008                 << BuiltinOperInfo("mul",       "*",    FV,             Value(F,   -1.0f,   1.0f),      Value(FV,  -1.0f,  1.0f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(mulScalarVec))
1009                 << BuiltinOperInfo("mul",       "*",    IV,             Value(I,   -4.0f,   6.0f),      Value(IV,  -6.0f,  5.0f),       notUsed,        0.1f,           0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(mulScalarVec))
1010                 << BuiltinOperInfo("div",       "/",    GT,             Value(GT,  -1.0f,   1.0f),      Value(GT,  -2.0f, -0.5f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(div))
1011                 << BuiltinOperInfo("div",       "/",    IGT,    Value(IGT, 24.0f,  24.0f),      Value(IGT, -4.0f, -1.0f),       notUsed,        0.04f,          1.0f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(div))
1012                 << BuiltinOperInfo("div",       "/",    FV,             Value(FV,  -1.0f,   1.0f),      Value(F,   -2.0f, -0.5f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(divVecScalar))
1013                 << BuiltinOperInfo("div",       "/",    IV,             Value(IV,  24.0f,  24.0f),      Value(I,   -4.0f, -1.0f),       notUsed,        0.04f,          1.0f,           PRECMASK_ALL,   INT_VEC_FUNCS(divVecScalar))
1014                 << BuiltinOperInfo("div",       "/",    FV,             Value(F,   -1.0f,   1.0f),      Value(FV,  -2.0f, -0.5f),       notUsed,        1.0f,           0.0f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(divScalarVec))
1015                 << BuiltinOperInfo("div",       "/",    IV,             Value(I,   24.0f,  24.0f),      Value(IV,  -4.0f, -1.0f),       notUsed,        0.04f,          1.0f,           PRECMASK_ALL,   INT_VEC_FUNCS(divScalarVec))
1016
1017                 // Arithmetic assignment side effect cases.
1018                 << BuiltinSideEffOperInfo       ("add_assign_effect",           "+=",   GT,             Value(GT,       -1.0f,  1.0f),  Value(GT,       -1.0f,  1.0f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(add))
1019                 << BuiltinSideEffOperInfo       ("add_assign_effect",           "+=",   IGT,    Value(IGT,      -5.0f,  5.0f),  Value(IGT,      -5.0f,  5.0f),  notUsed,        0.05f,          0.5f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(add))
1020                 << BuiltinSideEffOperInfo       ("add_assign_effect",           "+=",   FV,             Value(FV,       -1.0f,  1.0f),  Value(F,        -1.0f,  1.0f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(addVecScalar))
1021                 << BuiltinSideEffOperInfo       ("add_assign_effect",           "+=",   IV,             Value(IV,       -5.0f,  5.0f),  Value(I,        -5.0f,  5.0f),  notUsed,        0.05f,          0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(addVecScalar))
1022                 << BuiltinSideEffOperInfo       ("sub_assign_effect",           "-=",   GT,             Value(GT,       -1.0f,  1.0f),  Value(GT,       -1.0f,  1.0f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(sub))
1023                 << BuiltinSideEffOperInfo       ("sub_assign_effect",           "-=",   IGT,    Value(IGT,      -5.0f,  5.0f),  Value(IGT,      -5.0f,  5.0f),  notUsed,        0.05f,          0.5f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(sub))
1024                 << BuiltinSideEffOperInfo       ("sub_assign_effect",           "-=",   FV,             Value(FV,       -1.0f,  1.0f),  Value(F,        -1.0f,  1.0f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(subVecScalar))
1025                 << BuiltinSideEffOperInfo       ("sub_assign_effect",           "-=",   IV,             Value(IV,       -5.0f,  5.0f),  Value(I,        -5.0f,  5.0f),  notUsed,        0.05f,          0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(subVecScalar))
1026                 << BuiltinSideEffOperInfo       ("mul_assign_effect",           "*=",   GT,             Value(GT,       -1.0f,  1.0f),  Value(GT,       -1.0f,  1.0f),  notUsed,        0.5f,           0.5f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(mul))
1027                 << BuiltinSideEffOperInfo       ("mul_assign_effect",           "*=",   IGT,    Value(IGT,      -4.0f,  4.0f),  Value(IGT,      -4.0f,  4.0f),  notUsed,        0.03f,          0.5f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(mul))
1028                 << BuiltinSideEffOperInfo       ("mul_assign_effect",           "*=",   FV,             Value(FV,       -1.0f,  1.0f),  Value(F,        -1.0f,  1.0f),  notUsed,        0.5f,           0.5f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(mulVecScalar))
1029                 << BuiltinSideEffOperInfo       ("mul_assign_effect",           "*=",   IV,             Value(IV,       -4.0f,  4.0f),  Value(I,        -4.0f,  4.0f),  notUsed,        0.03f,          0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(mulVecScalar))
1030                 << BuiltinSideEffOperInfo       ("div_assign_effect",           "/=",   GT,             Value(GT,       -1.0f,  1.0f),  Value(GT,       -2.0f, -0.5f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(div))
1031                 << BuiltinSideEffOperInfo       ("div_assign_effect",           "/=",   IGT,    Value(IGT,      24.0f, 24.0f),  Value(IGT,      -4.0f, -1.0f),  notUsed,        0.04f,          1.0f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(div))
1032                 << BuiltinSideEffOperInfo       ("div_assign_effect",           "/=",   FV,             Value(FV,       -1.0f,  1.0f),  Value(F,        -2.0f, -0.5f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(divVecScalar))
1033                 << BuiltinSideEffOperInfo       ("div_assign_effect",           "/=",   IV,             Value(IV,       24.0f, 24.0f),  Value(I,        -4.0f, -1.0f),  notUsed,        0.04f,          1.0f,           PRECMASK_ALL,   INT_VEC_FUNCS(divVecScalar))
1034
1035                 // Arithmetic assignment result cases.
1036                 << BuiltinOperInfo                      ("add_assign_result",           "+=",   GT,             Value(GT,       -1.0f,  1.0f),  Value(GT,       -1.0f,  1.0f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(add))
1037                 << BuiltinOperInfo                      ("add_assign_result",           "+=",   IGT,    Value(IGT,      -5.0f,  5.0f),  Value(IGT,      -5.0f,  5.0f),  notUsed,        0.05f,          0.5f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(add))
1038                 << BuiltinOperInfo                      ("add_assign_result",           "+=",   FV,             Value(FV,       -1.0f,  1.0f),  Value(F,        -1.0f,  1.0f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(addVecScalar))
1039                 << BuiltinOperInfo                      ("add_assign_result",           "+=",   IV,             Value(IV,       -5.0f,  5.0f),  Value(I,        -5.0f,  5.0f),  notUsed,        0.05f,          0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(addVecScalar))
1040                 << BuiltinOperInfo                      ("sub_assign_result",           "-=",   GT,             Value(GT,       -1.0f,  1.0f),  Value(GT,       -1.0f,  1.0f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(sub))
1041                 << BuiltinOperInfo                      ("sub_assign_result",           "-=",   IGT,    Value(IGT,      -5.0f,  5.0f),  Value(IGT,      -5.0f,  5.0f),  notUsed,        0.05f,          0.5f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(sub))
1042                 << BuiltinOperInfo                      ("sub_assign_result",           "-=",   FV,             Value(FV,       -1.0f,  1.0f),  Value(F,        -1.0f,  1.0f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(subVecScalar))
1043                 << BuiltinOperInfo                      ("sub_assign_result",           "-=",   IV,             Value(IV,       -5.0f,  5.0f),  Value(I,        -5.0f,  5.0f),  notUsed,        0.05f,          0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(subVecScalar))
1044                 << BuiltinOperInfo                      ("mul_assign_result",           "*=",   GT,             Value(GT,       -1.0f,  1.0f),  Value(GT,       -1.0f,  1.0f),  notUsed,        0.5f,           0.5f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(mul))
1045                 << BuiltinOperInfo                      ("mul_assign_result",           "*=",   IGT,    Value(IGT,      -4.0f,  4.0f),  Value(IGT,      -4.0f,  4.0f),  notUsed,        0.03f,          0.5f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(mul))
1046                 << BuiltinOperInfo                      ("mul_assign_result",           "*=",   FV,             Value(FV,       -1.0f,  1.0f),  Value(F,        -1.0f,  1.0f),  notUsed,        0.5f,           0.5f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(mulVecScalar))
1047                 << BuiltinOperInfo                      ("mul_assign_result",           "*=",   IV,             Value(IV,       -4.0f,  4.0f),  Value(I,        -4.0f,  4.0f),  notUsed,        0.03f,          0.5f,           PRECMASK_ALL,   INT_VEC_FUNCS(mulVecScalar))
1048                 << BuiltinOperInfo                      ("div_assign_result",           "/=",   GT,             Value(GT,       -1.0f,  1.0f),  Value(GT,       -2.0f, -0.5f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(div))
1049                 << BuiltinOperInfo                      ("div_assign_result",           "/=",   IGT,    Value(IGT,      24.0f, 24.0f),  Value(IGT,      -4.0f, -1.0f),  notUsed,        0.04f,          1.0f,           PRECMASK_ALL,   INT_GENTYPE_FUNCS(div))
1050                 << BuiltinOperInfo                      ("div_assign_result",           "/=",   FV,             Value(FV,       -1.0f,  1.0f),  Value(F,        -2.0f, -0.5f),  notUsed,        0.25f,          0.5f,           PRECMASK_ALL,   FLOAT_VEC_FUNCS(divVecScalar))
1051                 << BuiltinOperInfo                      ("div_assign_result",           "/=",   IV,             Value(IV,       24.0f, 24.0f),  Value(I,        -4.0f, -1.0f),  notUsed,        0.04f,          1.0f,           PRECMASK_ALL,   INT_VEC_FUNCS(divVecScalar))
1052
1053                 // Scalar relational operators.
1054                 << BuiltinOperInfo("less",                              "<",    B,              Value(F,   -1.0f, 1.0f),        Value(F,   -1.0f, 1.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   eval_lessThan_float,                    DE_NULL, DE_NULL, DE_NULL)
1055                 << BuiltinOperInfo("less",                              "<",    B,              Value(I,   -5.0f, 5.0f),        Value(I,   -5.0f, 5.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   eval_lessThan_int,                              DE_NULL, DE_NULL, DE_NULL)
1056                 << BuiltinOperInfo("less_or_equal",             "<=",   B,              Value(F,   -1.0f, 1.0f),        Value(F,   -1.0f, 1.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   eval_lessThanEqual_float,               DE_NULL, DE_NULL, DE_NULL)
1057                 << BuiltinOperInfo("less_or_equal",             "<=",   B,              Value(I,   -5.0f, 5.0f),        Value(I,   -5.0f, 5.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   eval_lessThanEqual_int,                 DE_NULL, DE_NULL, DE_NULL)
1058                 << BuiltinOperInfo("greater",                   ">",    B,              Value(F,   -1.0f, 1.0f),        Value(F,   -1.0f, 1.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   eval_greaterThan_float,                 DE_NULL, DE_NULL, DE_NULL)
1059                 << BuiltinOperInfo("greater",                   ">",    B,              Value(I,   -5.0f, 5.0f),        Value(I,   -5.0f, 5.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   eval_greaterThan_int,                   DE_NULL, DE_NULL, DE_NULL)
1060                 << BuiltinOperInfo("greater_or_equal",  ">=",   B,              Value(F,   -1.0f, 1.0f),        Value(F,   -1.0f, 1.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   eval_greaterThanEqual_float,    DE_NULL, DE_NULL, DE_NULL)
1061                 << BuiltinOperInfo("greater_or_equal",  ">=",   B,              Value(I,   -5.0f, 5.0f),        Value(I,   -5.0f, 5.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   eval_greaterThanEqual_int,              DE_NULL, DE_NULL, DE_NULL)
1062
1063                 // Equality comparison operators.
1064                 << BuiltinOperInfo("equal",                             "==",   B,              Value(GT,  -1.0f, 1.0f),        Value(GT,  -1.0f, 1.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(allEqual))
1065                 << BuiltinOperInfo("equal",                             "==",   B,              Value(IGT, -5.5f, 4.7f),        Value(IGT, -4.9f, 5.8f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(allEqual))
1066                 << BuiltinOperInfo("equal",                             "==",   B,              Value(BGT, -2.1f, 2.1f),        Value(BGT, -1.1f, 3.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_NA,    BOOL_GENTYPE_FUNCS(allEqual))
1067                 << BuiltinOperInfo("not_equal",                 "!=",   B,              Value(GT,  -1.0f, 1.0f),        Value(GT,  -1.0f, 1.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   FLOAT_GENTYPE_FUNCS(anyNotEqual))
1068                 << BuiltinOperInfo("not_equal",                 "!=",   B,              Value(IGT, -5.5f, 4.7f),        Value(IGT, -4.9f, 5.8f),        notUsed,        1.0f, 0.0f,             PRECMASK_ALL,   INT_GENTYPE_FUNCS(anyNotEqual))
1069                 << BuiltinOperInfo("not_equal",                 "!=",   B,              Value(BGT, -2.1f, 2.1f),        Value(BGT, -1.1f, 3.0f),        notUsed,        1.0f, 0.0f,             PRECMASK_NA,    BOOL_GENTYPE_FUNCS(anyNotEqual))
1070
1071                 // Logical operators.
1072                 << BuiltinOperInfo("logical_and",       "&&",   B,      Value(B, -1.0f, 1.0f),  Value(B, -1.0f, 1.0f),  notUsed,        1.0f, 0.0f,             PRECMASK_NA,    BOOL_FUNCS(logicalAnd))
1073                 << BuiltinOperInfo("logical_or",        "||",   B,      Value(B, -1.0f, 1.0f),  Value(B, -1.0f, 1.0f),  notUsed,        1.0f, 0.0f,             PRECMASK_NA,    BOOL_FUNCS(logicalOr))
1074                 << BuiltinOperInfo("logical_xor",       "^^",   B,      Value(B, -1.0f, 1.0f),  Value(B, -1.0f, 1.0f),  notUsed,        1.0f, 0.0f,             PRECMASK_NA,    BOOL_FUNCS(logicalXor))
1075         );
1076
1077         // 8.1 Angle and Trigonometry Functions.
1078         funcInfoGroups.push_back(
1079                 BuiltinFuncGroup("angle_and_trigonometry", "Angle and trigonometry function tests.")
1080                 << BuiltinFuncInfo("radians",           "radians",              GT,     Value(GT, -1.0f, 1.0f),         notUsed,                                        notUsed,                                        25.0f, 0.5f,    PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(radians) )
1081                 << BuiltinFuncInfo("degrees",           "degrees",              GT,     Value(GT, -1.0f, 1.0f),         notUsed,                                        notUsed,                                        0.04f, 0.5f,    PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(degrees) )
1082                 << BuiltinFuncInfo("sin",                       "sin",                  GT,     Value(GT, -5.0f, 5.0f),         notUsed,                                        notUsed,                                        0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(sin) )
1083                 << BuiltinFuncInfo("sin",                       "sin",                  GT,     Value(GT, -1.5f, 1.5f),         notUsed,                                        notUsed,                                        0.5f, 0.5f,             PRECMASK_LOWP,                          FLOAT_GENTYPE_FUNCS(sin) )
1084                 << BuiltinFuncInfo("cos",                       "cos",                  GT,     Value(GT, -5.0f, 5.0f),         notUsed,                                        notUsed,                                        0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(cos) )
1085                 << BuiltinFuncInfo("cos",                       "cos",                  GT,     Value(GT, -1.5f, 1.5f),         notUsed,                                        notUsed,                                        0.5f, 0.5f,             PRECMASK_LOWP,                          FLOAT_GENTYPE_FUNCS(cos) )
1086                 << BuiltinFuncInfo("tan",                       "tan",                  GT,     Value(GT, -5.0f, 5.0f),         notUsed,                                        notUsed,                                        0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(tan) )
1087                 << BuiltinFuncInfo("tan",                       "tan",                  GT,     Value(GT, -1.5f, 5.5f),         notUsed,                                        notUsed,                                        0.5f, 0.5f,             PRECMASK_LOWP,                          FLOAT_GENTYPE_FUNCS(tan) )
1088                 << BuiltinFuncInfo("asin",                      "asin",                 GT,     Value(GT, -1.0f, 1.0f),         notUsed,                                        notUsed,                                        1.0f, 0.0f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(asin) )
1089                 << BuiltinFuncInfo("acos",                      "acos",                 GT,     Value(GT, -1.0f, 1.0f),         notUsed,                                        notUsed,                                        1.0f, 0.0f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(acos) )
1090                 << BuiltinFuncInfo("atan",                      "atan",                 GT,     Value(GT, -4.0f, 4.0f),         notUsed,                                        notUsed,                                        0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(atan) )
1091                 << BuiltinFuncInfo("atan2",                     "atan",                 GT,     Value(GT, -4.0f, 4.0f),         Value(GT, 0.5f, 2.0f),          notUsed,                                        0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(atan2) )
1092         );
1093
1094         // 8.2 Exponential Functions.
1095         funcInfoGroups.push_back(
1096                 BuiltinFuncGroup("exponential", "Exponential function tests")
1097                 << BuiltinFuncInfo("pow",                       "pow",                  GT,     Value(GT, 0.1f, 8.0f),          Value(GT, -4.0f, 2.0f),         notUsed,                                        1.0f, 0.0f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(pow) )
1098                 << BuiltinFuncInfo("exp",                       "exp",                  GT,     Value(GT, -6.0f, 3.0f),         notUsed,                                        notUsed,                                        0.5f, 0.0f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(exp) )
1099                 << BuiltinFuncInfo("log",                       "log",                  GT,     Value(GT, 0.1f, 10.0f),         notUsed,                                        notUsed,                                        0.5f, 0.3f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(log) )
1100                 << BuiltinFuncInfo("exp2",                      "exp2",                 GT,     Value(GT, -7.0f, 2.0f),         notUsed,                                        notUsed,                                        1.0f, 0.0f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(exp2) )
1101                 << BuiltinFuncInfo("log2",                      "log2",                 GT,     Value(GT, 0.1f, 10.0f),         notUsed,                                        notUsed,                                        1.0f, 0.0f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(log2) )
1102                 << BuiltinFuncInfo("sqrt",                      "sqrt",                 GT,     Value(GT, 0.0f, 10.0f),         notUsed,                                        notUsed,                                        0.3f, 0.0f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(sqrt) )
1103                 << BuiltinFuncInfo("inversesqrt",       "inversesqrt",  GT,     Value(GT, 0.5f, 10.0f),         notUsed,                                        notUsed,                                        1.0f, 0.0f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(inverseSqrt) )
1104         );
1105
1106         // 8.3 Common Functions.
1107         funcInfoGroups.push_back(
1108                 BuiltinFuncGroup("common_functions", "Common function tests.")
1109                 << BuiltinFuncInfo("abs",                       "abs",                  GT,     Value(GT, -2.0f, 2.0f),         notUsed,                                        notUsed,                                        0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(abs) )
1110                 << BuiltinFuncInfo("sign",                      "sign",                 GT,     Value(GT, -1.5f, 1.5f),         notUsed,                                        notUsed,                                        0.3f, 0.5f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(sign) )
1111                 << BuiltinFuncInfo("floor",                     "floor",                GT,     Value(GT, -2.5f, 2.5f),         notUsed,                                        notUsed,                                        0.2f, 0.7f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(floor) )
1112                 << BuiltinFuncInfo("ceil",                      "ceil",                 GT,     Value(GT, -2.5f, 2.5f),         notUsed,                                        notUsed,                                        0.2f, 0.5f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(ceil) )
1113                 << BuiltinFuncInfo("fract",                     "fract",                GT,     Value(GT, -1.5f, 1.5f),         notUsed,                                        notUsed,                                        0.8f, 0.1f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(fract) )
1114                 << BuiltinFuncInfo("mod",                       "mod",                  GT,     Value(GT, -2.0f, 2.0f),         Value(GT, 0.9f, 6.0f),          notUsed,                                        0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(mod) )
1115                 << BuiltinFuncInfo("mod",                       "mod",                  GT,     Value(FV, -2.0f, 2.0f),         Value(F, 0.9f, 6.0f),           notUsed,                                        0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_VEC_FUNCS(modVecFloat) )
1116                 << BuiltinFuncInfo("min",                       "min",                  GT,     Value(GT, -1.0f, 1.0f),         Value(GT, -1.0f, 1.0f),         notUsed,                                        0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(min) )
1117                 << BuiltinFuncInfo("min",                       "min",                  GT,     Value(FV, -1.0f, 1.0f),         Value(F, -1.0f, 1.0f),          notUsed,                                        0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_VEC_FUNCS(minVecFloat) )
1118                 << BuiltinFuncInfo("max",                       "max",                  GT,     Value(GT, -1.0f, 1.0f),         Value(GT, -1.0f, 1.0f),         notUsed,                                        0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(max) )
1119                 << BuiltinFuncInfo("max",                       "max",                  GT,     Value(FV, -1.0f, 1.0f),         Value(F, -1.0f, 1.0f),          notUsed,                                        0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_VEC_FUNCS(maxVecFloat) )
1120                 << BuiltinFuncInfo("clamp",                     "clamp",                GT,     Value(GT, -1.0f, 1.0f),         Value(GT, -0.5f, 0.5f),         Value(GT, 0.5f, 1.0f),          0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(clamp) )
1121                 << BuiltinFuncInfo("clamp",                     "clamp",                GT,     Value(FV, -1.0f, 1.0f),         Value(F, -0.5f, 0.5f),          Value(F, 0.5f, 1.0f),           0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_VEC_FUNCS(clampVecFloatFloat) )
1122                 << BuiltinFuncInfo("mix",                       "mix",                  GT,     Value(GT, -1.0f, 1.0f),         Value(GT, -1.0f, 1.0f),         Value(GT, 0.0f, 1.0f),          0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(mix) )
1123                 << BuiltinFuncInfo("mix",                       "mix",                  GT,     Value(FV, -1.0f, 1.0f),         Value(FV, -1.0f, 1.0f),         Value(F, 0.0f, 1.0f),           0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_VEC_FUNCS(mixVecVecFloat) )
1124                 << BuiltinFuncInfo("step",                      "step",                 GT,     Value(GT, -1.0f, 1.0f),         Value(GT, -1.0f, 0.0f),         notUsed,                                        0.5f, 0.25f,    PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(step) )
1125                 << BuiltinFuncInfo("step",                      "step",                 GT,     Value(F, -1.0f, 1.0f),          Value(FV, -1.0f, 0.0f),         notUsed,                                        0.5f, 0.25f,    PRECMASK_ALL,                           FLOAT_VEC_FUNCS(stepFloatVec) )
1126                 << BuiltinFuncInfo("smoothstep",        "smoothstep",   GT,     Value(GT, -0.5f, 0.0f),         Value(GT, 0.1f, 1.0f),          Value(GT, -1.0f, 1.0f),         0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_GENTYPE_FUNCS(smoothStep) )
1127                 << BuiltinFuncInfo("smoothstep",        "smoothstep",   GT,     Value(F, -0.5f, 0.0f),          Value(F, 0.1f, 1.0f),           Value(FV, -1.0f, 1.0f),         0.5f, 0.5f,             PRECMASK_ALL,                           FLOAT_VEC_FUNCS(smoothStepFloatFloatVec) )
1128         );
1129
1130         // 8.4 Geometric Functions.
1131         funcInfoGroups.push_back(
1132                 BuiltinFuncGroup("geometric", "Geometric function tests.")
1133                 << BuiltinFuncInfo("length",            "length",               F,      Value(GT, -5.0f, 5.0f),         notUsed,                                        notUsed,                                        0.1f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(length) )
1134                 << BuiltinFuncInfo("distance",          "distance",             F,      Value(GT, -5.0f, 5.0f),         Value(GT, -5.0f, 5.0f),         notUsed,                                        0.1f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(distance) )
1135                 << BuiltinFuncInfo("dot",                       "dot",                  F,      Value(GT, -5.0f, 5.0f),         Value(GT, -5.0f, 5.0f),         notUsed,                                        0.1f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(dot) )
1136                 << BuiltinFuncInfo("cross",                     "cross",                V3,     Value(GT, -5.0f, 5.0f),         Value(GT, -5.0f, 5.0f),         notUsed,                                        0.1f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         DE_NULL, DE_NULL, eval_cross_vec3, DE_NULL )
1137                 << BuiltinFuncInfo("normalize",         "normalize",    GT,     Value(GT, 0.1f, 4.0f),          notUsed,                                        notUsed,                                        0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(normalize) )
1138                 << BuiltinFuncInfo("faceforward",       "faceforward",  GT,     Value(GT, -5.0f, 5.0f),         Value(GT, -5.0f, 5.0f),         Value(GT, -1.0f, 1.0f),         0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(faceForward) )
1139                 << BuiltinFuncInfo("reflect",           "reflect",              GT,     Value(GT, -0.8f, -0.5f),        Value(GT, 0.5f, 0.8f),          notUsed,                                        0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(reflect) )
1140                 << BuiltinFuncInfo("refract",           "refract",              GT,     Value(GT, -0.8f, 1.2f),         Value(GT, -1.1f, 0.5f),         Value(F, 0.2f, 1.5f),           0.5f, 0.5f,             PRECMASK_MEDIUMP_HIGHP,         FLOAT_GENTYPE_FUNCS(refract) )
1141         );
1142
1143         // 8.5 Matrix Functions.
1144         // separate matrix tests?
1145 //      funcInfoGroups.push_back(
1146 //              BuiltinFuncGroup("matrix", "Matrix function tests.")
1147 //              << BuiltinFuncInfo("matrixCompMult",    "matrixCompMult",       M, ... )
1148 //      );
1149
1150         // 8.6 Vector Relational Functions.
1151         funcInfoGroups.push_back(
1152                 BuiltinFuncGroup("float_compare", "Floating point comparison tests.")
1153                 << BuiltinFuncInfo("lessThan",                  "lessThan",                     BV,     Value(FV, -1.0f, 1.0f),         Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      FLOAT_VEC_FUNCS(lessThan) )
1154                 << BuiltinFuncInfo("lessThanEqual",             "lessThanEqual",        BV,     Value(FV, -1.0f, 1.0f),         Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      FLOAT_VEC_FUNCS(lessThanEqual) )
1155                 << BuiltinFuncInfo("greaterThan",               "greaterThan",          BV,     Value(FV, -1.0f, 1.0f),         Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      FLOAT_VEC_FUNCS(greaterThan) )
1156                 << BuiltinFuncInfo("greaterThanEqual",  "greaterThanEqual",     BV,     Value(FV, -1.0f, 1.0f),         Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      FLOAT_VEC_FUNCS(greaterThanEqual) )
1157                 << BuiltinFuncInfo("equal",                             "equal",                        BV,     Value(FV, -1.0f, 1.0f),         Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      FLOAT_VEC_FUNCS(equal) )
1158                 << BuiltinFuncInfo("notEqual",                  "notEqual",                     BV,     Value(FV, -1.0f, 1.0f),         Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      FLOAT_VEC_FUNCS(notEqual) )
1159         );
1160
1161         funcInfoGroups.push_back(
1162                 BuiltinFuncGroup("int_compare", "Integer comparison tests.")
1163                 << BuiltinFuncInfo("lessThan",                  "lessThan",                     BV,     Value(IV, -5.2f, 4.9f),         Value(IV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      INT_VEC_FUNCS(lessThan) )
1164                 << BuiltinFuncInfo("lessThanEqual",             "lessThanEqual",        BV,     Value(IV, -5.2f, 4.9f),         Value(IV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      INT_VEC_FUNCS(lessThanEqual) )
1165                 << BuiltinFuncInfo("greaterThan",               "greaterThan",          BV,     Value(IV, -5.2f, 4.9f),         Value(IV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      INT_VEC_FUNCS(greaterThan) )
1166                 << BuiltinFuncInfo("greaterThanEqual",  "greaterThanEqual",     BV,     Value(IV, -5.2f, 4.9f),         Value(IV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      INT_VEC_FUNCS(greaterThanEqual) )
1167                 << BuiltinFuncInfo("equal",                             "equal",                        BV,     Value(IV, -5.2f, 4.9f),         Value(IV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      INT_VEC_FUNCS(equal) )
1168                 << BuiltinFuncInfo("notEqual",                  "notEqual",                     BV,     Value(IV, -5.2f, 4.9f),         Value(IV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_ALL,      INT_VEC_FUNCS(notEqual) )
1169         );
1170
1171         funcInfoGroups.push_back(
1172                 BuiltinFuncGroup("bool_compare", "Boolean comparison tests.")
1173                 << BuiltinFuncInfo("equal",                             "equal",                        BV,     Value(BV, -5.2f, 4.9f),         Value(BV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_NA,       BOOL_VEC_FUNCS(equal) )
1174                 << BuiltinFuncInfo("notEqual",                  "notEqual",                     BV,     Value(BV, -5.2f, 4.9f),         Value(BV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_NA,       BOOL_VEC_FUNCS(notEqual) )
1175                 << BuiltinFuncInfo("any",                               "any",                          B,      Value(BV, -1.0f, 0.3f),         notUsed,                                notUsed, 1.0f, 0.0f, PRECMASK_NA,       BOOL_VEC_FUNCS(any) )
1176                 << BuiltinFuncInfo("all",                               "all",                          B,      Value(BV, -0.3f, 1.0f),         notUsed,                                notUsed, 1.0f, 0.0f, PRECMASK_NA,       BOOL_VEC_FUNCS(all) )
1177                 << BuiltinFuncInfo("not",                               "not",                          BV,     Value(BV, -1.0f, 1.0f),         notUsed,                                notUsed, 1.0f, 0.0f, PRECMASK_NA,       BOOL_VEC_FUNCS(boolNot) )
1178         );
1179
1180         // 8.7 Texture Lookup Functions
1181         // texture2D (sampler, vec2)
1182         // texture2D (sampler, vec2, bias)
1183         // texture2DProj (sampler, vec3)
1184         // texture2DProj (sampler, vec3, bias)
1185         // texture2DProj (sampler, vec4)
1186         // texture2DProj (sampler, vec4, bias)
1187         // texture2DLod (sampler, vec2, lod)
1188         // texture2DProjLod (sampler, vec3, lod)
1189         // texture2DProjLod (sampler, vec4, lod)
1190         // textureCube (sampler, vec3)
1191         // textureCube (sampler, vec3, bias)
1192         // textureCubeLod (sampler, vec3, lod)
1193
1194         static const ShaderType s_shaderTypes[] =
1195         {
1196                 SHADERTYPE_VERTEX,
1197                 SHADERTYPE_FRAGMENT
1198         };
1199
1200         static const DataType s_floatTypes[] =
1201         {
1202                 TYPE_FLOAT,
1203                 TYPE_FLOAT_VEC2,
1204                 TYPE_FLOAT_VEC3,
1205                 TYPE_FLOAT_VEC4
1206         };
1207
1208         static const DataType s_intTypes[] =
1209         {
1210                 TYPE_INT,
1211                 TYPE_INT_VEC2,
1212                 TYPE_INT_VEC3,
1213                 TYPE_INT_VEC4
1214         };
1215
1216         static const DataType s_boolTypes[] =
1217         {
1218                 TYPE_BOOL,
1219                 TYPE_BOOL_VEC2,
1220                 TYPE_BOOL_VEC3,
1221                 TYPE_BOOL_VEC4
1222         };
1223
1224         for (int outerGroupNdx = 0; outerGroupNdx < (int)funcInfoGroups.size(); outerGroupNdx++)
1225         {
1226                 // Create outer group.
1227                 const BuiltinFuncGroup& outerGroupInfo = funcInfoGroups[outerGroupNdx];
1228                 TestCaseGroup* outerGroup = new TestCaseGroup(m_context, outerGroupInfo.name, outerGroupInfo.description);
1229                 addChild(outerGroup);
1230
1231                 // Only create new group if name differs from previous one.
1232                 TestCaseGroup* innerGroup = DE_NULL;
1233
1234                 for (int funcInfoNdx = 0; funcInfoNdx < (int)outerGroupInfo.funcInfos.size(); funcInfoNdx++)
1235                 {
1236                         const BuiltinFuncInfo&  funcInfo                = outerGroupInfo.funcInfos[funcInfoNdx];
1237                         const char*                             shaderFuncName  = funcInfo.shaderFuncName;
1238                         bool                                    isBoolCase              = (funcInfo.precisionMask == PRECMASK_NA);
1239                         bool                                    isIntCase               = (funcInfo.input0.valueType & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
1240                         bool                                    isFloatCase             = !isBoolCase && !isIntCase;    // \todo [petri] Better check.
1241                         bool                                    isBoolOut               = (funcInfo.outValue & (VALUE_BOOL | VALUE_BOOL_VEC | VALUE_BOOL_GENTYPE)) != 0;
1242                         bool                                    isIntOut                = (funcInfo.outValue & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
1243                         bool                                    isFloatOut              = !isBoolOut && !isIntOut;
1244
1245                         if (!innerGroup || (string(innerGroup->getName()) != funcInfo.caseName))
1246                         {
1247                                 string groupDesc = string("Built-in function ") + shaderFuncName + "() tests.";
1248                                 innerGroup = new TestCaseGroup(m_context, funcInfo.caseName, groupDesc.c_str());
1249                                 outerGroup->addChild(innerGroup);
1250                         }
1251
1252                         for (int inScalarSize = 1; inScalarSize <= 4; inScalarSize++)
1253                         {
1254                                 int                     outScalarSize   = ((funcInfo.outValue == VALUE_FLOAT) || (funcInfo.outValue == VALUE_BOOL)) ? 1 : inScalarSize; // \todo [petri] Int.
1255                                 DataType        outDataType             = isFloatOut ? s_floatTypes[outScalarSize - 1]
1256                                                                                         : isIntOut ? s_intTypes[outScalarSize - 1]
1257                                                                                         : isBoolOut ? s_boolTypes[outScalarSize - 1]
1258                                                                                         : TYPE_LAST;
1259
1260                                 ShaderEvalFunc evalFunc = DE_NULL;
1261                                 if      (inScalarSize == 1)     evalFunc = funcInfo.evalFuncScalar;
1262                                 else if (inScalarSize == 2)     evalFunc = funcInfo.evalFuncVec2;
1263                                 else if (inScalarSize == 3)     evalFunc = funcInfo.evalFuncVec3;
1264                                 else if (inScalarSize == 4)     evalFunc = funcInfo.evalFuncVec4;
1265                                 else DE_ASSERT(false);
1266
1267                                 // Skip if no valid eval func.
1268                                 // \todo [petri] Better check for V3 only etc. cases?
1269                                 if (evalFunc == DE_NULL)
1270                                         continue;
1271
1272                                 for (int precision = 0; precision < PRECISION_LAST; precision++)
1273                                 {
1274                                         if ((funcInfo.precisionMask & (1<<precision)) ||
1275                                                 (funcInfo.precisionMask == PRECMASK_NA && precision == PRECISION_MEDIUMP)) // use mediump interpolators for booleans
1276                                         {
1277                                                 const char*     precisionStr    = getPrecisionName((Precision)precision);
1278                                                 string          precisionPrefix = isBoolCase ? "" : (string(precisionStr) + "_");
1279
1280                                                 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1281                                                 {
1282                                                         ShaderType              shaderType              = s_shaderTypes[shaderTypeNdx];
1283                                                         ShaderDataSpec  shaderSpec;
1284                                                         const char*             shaderTypeName  = getShaderTypeName(shaderType);
1285                                                         bool                    isVertexCase    = (ShaderType)shaderType == SHADERTYPE_VERTEX;
1286                                                         bool                    isUnaryOp               = (funcInfo.input1.valueType == VALUE_NONE);
1287
1288                                                         // \note Data type names will be added to description and name in a following loop.
1289                                                         string desc     = string("Built-in function ") + shaderFuncName + "(";
1290                                                         string name = precisionPrefix;
1291
1292                                                         // Generate shader op.
1293                                                         string shaderOp = string("res = ");
1294
1295                                                         // Setup shader data info.
1296                                                         shaderSpec.numInputs    = 0;
1297                                                         shaderSpec.precision    = isBoolCase ? PRECISION_LAST : (Precision)precision;
1298                                                         shaderSpec.output               = outDataType;
1299                                                         shaderSpec.resultScale  = funcInfo.resultScale;
1300                                                         shaderSpec.resultBias   = funcInfo.resultBias;
1301
1302                                                         if (funcInfo.type == OPERATOR)
1303                                                         {
1304                                                                 if (isUnaryOp && funcInfo.isUnaryPrefix)
1305                                                                         shaderOp += shaderFuncName;
1306                                                         }
1307                                                         else if (funcInfo.type == FUNCTION)
1308                                                                 shaderOp += string(shaderFuncName) + "(";
1309                                                         else // SIDE_EFFECT_OPERATOR
1310                                                                 shaderOp += "in0;\n\t";
1311
1312                                                         for (int inputNdx = 0; inputNdx < MAX_INPUTS; inputNdx++)
1313                                                         {
1314                                                                 const Value&    v                               = (inputNdx == 0) ? funcInfo.input0 : (inputNdx == 1) ? funcInfo.input1 : funcInfo.input2;
1315                                                                 const Value&    prevV                   = (inputNdx == 1) ? funcInfo.input0 : (inputNdx == 2) ? funcInfo.input1 : funcInfo.input2;
1316
1317                                                                 if (v.valueType == VALUE_NONE)
1318                                                                         continue; // Skip unused input.
1319
1320                                                                 int                             curInScalarSize = isScalarType(v.valueType) ? 1 : inScalarSize;
1321                                                                 DataType                curInDataType   = isFloatCase ? s_floatTypes[curInScalarSize - 1]
1322                                                                                                                                 : isIntCase ? s_intTypes[curInScalarSize - 1]
1323                                                                                                                                 : isBoolCase ? s_boolTypes[curInScalarSize - 1]
1324                                                                                                                                 : TYPE_LAST;
1325
1326                                                                 // Write input type(s) to case description and name.
1327
1328                                                                 if (inputNdx > 0)
1329                                                                         desc += ", ";
1330
1331                                                                 desc += getDataTypeName(curInDataType);
1332
1333                                                                 if (inputNdx == 0 || isScalarType(prevV.valueType) != isScalarType(v.valueType)) // \note Only write input type to case name if different from previous input type (avoid overly long names).
1334                                                                         name += string("") + getDataTypeName(curInDataType) + "_";
1335
1336                                                                 // Generate op input source.
1337
1338                                                                 if (funcInfo.type == OPERATOR || funcInfo.type == FUNCTION)
1339                                                                 {
1340                                                                         if (inputNdx != 0)
1341                                                                         {
1342                                                                                 if (funcInfo.type == OPERATOR && !isUnaryOp)
1343                                                                                         shaderOp += " " + string(shaderFuncName) + " ";
1344                                                                                 else
1345                                                                                         shaderOp += ", ";
1346                                                                         }
1347
1348                                                                         shaderOp += "in" + de::toString(inputNdx);
1349
1350                                                                         if (funcInfo.type == OPERATOR && isUnaryOp && !funcInfo.isUnaryPrefix)
1351                                                                                 shaderOp += string(shaderFuncName);
1352                                                                 }
1353                                                                 else
1354                                                                 {
1355                                                                         DE_ASSERT(funcInfo.type == SIDE_EFFECT_OPERATOR);
1356
1357                                                                         if (inputNdx != 0 || (isUnaryOp && funcInfo.isUnaryPrefix))
1358                                                                                 shaderOp += string("") + (isUnaryOp ? "" : " ") + shaderFuncName + (isUnaryOp ? "" : " ");
1359
1360                                                                         shaderOp += inputNdx == 0 ? "res" : "in" + de::toString(inputNdx); // \note in0 has already been assigned to res, so start from in1.
1361
1362                                                                         if (isUnaryOp && !funcInfo.isUnaryPrefix)
1363                                                                                 shaderOp += shaderFuncName;
1364                                                                 }
1365
1366                                                                 // Fill in shader info.
1367                                                                 shaderSpec.inputs[shaderSpec.numInputs++] = ShaderValue(curInDataType, v.rangeMin, v.rangeMax);
1368                                                         }
1369
1370                                                         if (funcInfo.type == FUNCTION)
1371                                                                 shaderOp += ")";
1372
1373                                                         shaderOp += ";";
1374
1375                                                         desc += ").";
1376                                                         name += shaderTypeName;
1377
1378                                                         // Create the test case.
1379                                                         innerGroup->addChild(new ShaderOperatorCase(m_context, name.c_str(), desc.c_str(), isVertexCase, evalFunc, shaderOp.c_str(), shaderSpec));
1380                                                 }
1381                                         }
1382                                 }
1383                         }
1384                 }
1385         }
1386
1387         // The ?: selection operator.
1388
1389         static const struct
1390         {
1391                 DataType                type; // The type of "Y" and "Z" operands in "X ? Y : Z" (X is always bool).
1392                 ShaderEvalFunc  evalFunc;
1393         } s_selectionInfo[] =
1394         {
1395                 { TYPE_FLOAT,           eval_selection_float    },
1396                 { TYPE_FLOAT_VEC2,      eval_selection_vec2             },
1397                 { TYPE_FLOAT_VEC3,      eval_selection_vec3             },
1398                 { TYPE_FLOAT_VEC4,      eval_selection_vec4             },
1399                 { TYPE_INT,                     eval_selection_int              },
1400                 { TYPE_INT_VEC2,        eval_selection_ivec2    },
1401                 { TYPE_INT_VEC3,        eval_selection_ivec3    },
1402                 { TYPE_INT_VEC4,        eval_selection_ivec4    },
1403                 { TYPE_BOOL,            eval_selection_bool             },
1404                 { TYPE_BOOL_VEC2,       eval_selection_bvec2    },
1405                 { TYPE_BOOL_VEC3,       eval_selection_bvec3    },
1406                 { TYPE_BOOL_VEC4,       eval_selection_bvec4    }
1407         };
1408
1409         TestCaseGroup* selectionGroup = new TestCaseGroup(m_context, "selection", "Selection operator tests");
1410         addChild(selectionGroup);
1411
1412         for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_selectionInfo); typeNdx++)
1413         {
1414                 DataType                curType                 = s_selectionInfo[typeNdx].type;
1415                 ShaderEvalFunc  evalFunc                = s_selectionInfo[typeNdx].evalFunc;
1416                 bool                    isBoolCase              = isDataTypeBoolOrBVec(curType);
1417                 bool                    isFloatCase             = isDataTypeFloatOrVec(curType);
1418                 bool                    isIntCase               = isDataTypeIntOrIVec(curType);
1419                 const char*             dataTypeStr             = getDataTypeName(curType);
1420
1421                 DE_ASSERT(isBoolCase || isFloatCase || isIntCase);
1422                 DE_UNREF(isIntCase);
1423
1424                 for (int precision = 0; precision < (int)PRECISION_LAST; precision++)
1425                 {
1426                         if (isBoolCase && precision != PRECISION_MEDIUMP) // Use mediump interpolators for booleans.
1427                                 continue;
1428
1429                         const char*     precisionStr    = getPrecisionName((Precision)precision);
1430                         string          precisionPrefix = isBoolCase ? "" : (string(precisionStr) + "_");
1431
1432                         for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1433                         {
1434                                 ShaderType              shaderType              = s_shaderTypes[shaderTypeNdx];
1435                                 ShaderDataSpec  shaderSpec;
1436                                 const char*             shaderTypeName  = getShaderTypeName(shaderType);
1437                                 bool                    isVertexCase    = (ShaderType)shaderType == SHADERTYPE_VERTEX;
1438
1439                                 string name     = precisionPrefix + dataTypeStr + "_" + shaderTypeName;
1440
1441                                 shaderSpec.numInputs    = 3;
1442                                 shaderSpec.precision    = isBoolCase ? PRECISION_LAST : (Precision)precision;
1443                                 shaderSpec.output               = curType;
1444                                 shaderSpec.resultScale  = isBoolCase ? 1.0f : isFloatCase ? 0.5f : 0.1f;
1445                                 shaderSpec.resultBias   = isBoolCase ? 0.0f : isFloatCase ? 0.5f : 0.5f;
1446
1447                                 float rangeMin = isBoolCase ? -1.0f : isFloatCase ? -1.0f : -5.0f;
1448                                 float rangeMax = isBoolCase ?  1.0f : isFloatCase ?  1.0f :  5.0f;
1449
1450                                 shaderSpec.inputs[0] = ShaderValue(TYPE_BOOL, -1.0f, 1.0f);
1451                                 shaderSpec.inputs[1] = ShaderValue(curType, rangeMin, rangeMax);
1452                                 shaderSpec.inputs[2] = ShaderValue(curType, rangeMin, rangeMax);
1453
1454                                 selectionGroup->addChild(new ShaderOperatorCase(m_context, name.c_str(), "", isVertexCase, evalFunc, "res = in0 ? in1 : in2;", shaderSpec));
1455                         }
1456                 }
1457         }
1458
1459         // The sequence operator (comma).
1460
1461         TestCaseGroup* sequenceGroup = new TestCaseGroup(m_context, "sequence", "Sequence operator tests");
1462         addChild(sequenceGroup);
1463
1464         TestCaseGroup* sequenceNoSideEffGroup = new TestCaseGroup(m_context, "no_side_effects", "Sequence tests without side-effects");
1465         TestCaseGroup* sequenceSideEffGroup = new TestCaseGroup(m_context, "side_effects", "Sequence tests with side-effects");
1466         sequenceGroup->addChild(sequenceNoSideEffGroup);
1467         sequenceGroup->addChild(sequenceSideEffGroup);
1468
1469         static const struct
1470         {
1471                 bool                    containsSideEffects;
1472                 const char*             caseName;
1473                 const char*             expressionStr;
1474                 int                             numInputs;
1475                 DataType                inputTypes[MAX_INPUTS];
1476                 DataType                resultType;
1477                 ShaderEvalFunc  evalFunc;
1478         } s_sequenceCases[] =
1479         {
1480                 { false,        "vec4",                                 "in0, in2 + in1, in1 + in0",                                                    3,      { TYPE_FLOAT_VEC4,      TYPE_FLOAT_VEC4,        TYPE_FLOAT_VEC4 },      TYPE_FLOAT_VEC4,        evalSequenceNoSideEffCase0 },
1481                 { false,        "float_int",                    "in0 + in2, in1 + in1",                                                                 3,      { TYPE_FLOAT,           TYPE_INT,                       TYPE_FLOAT              },      TYPE_INT,                       evalSequenceNoSideEffCase1 },
1482                 { false,        "bool_vec2",                    "in0 && in1, in0, ivec2(vec2(in0) + in2)",                              3,      { TYPE_BOOL,            TYPE_BOOL,                      TYPE_FLOAT_VEC2 },      TYPE_INT_VEC2,          evalSequenceNoSideEffCase2 },
1483                 { false,        "vec4_ivec4_bvec4",             "in0 + vec4(in1), in2, in1",                                                    3,      { TYPE_FLOAT_VEC4,      TYPE_INT_VEC4,          TYPE_BOOL_VEC4  },      TYPE_INT_VEC4,          evalSequenceNoSideEffCase3 },
1484
1485                 { true,         "vec4",                                 "in0++, in1 = in0 + in2, in2 = in1",                                    3,      { TYPE_FLOAT_VEC4,      TYPE_FLOAT_VEC4,        TYPE_FLOAT_VEC4 },      TYPE_FLOAT_VEC4,        evalSequenceSideEffCase0 },
1486                 { true,         "float_int",                    "in1++, in0 = float(in1), in1 = int(in0 + in2)",                3,      { TYPE_FLOAT,           TYPE_INT,                       TYPE_FLOAT              },      TYPE_INT,                       evalSequenceSideEffCase1 },
1487                 { true,         "bool_vec2",                    "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)",  3,      { TYPE_BOOL,            TYPE_BOOL,                      TYPE_FLOAT_VEC2 },      TYPE_INT_VEC2,          evalSequenceSideEffCase2 },
1488                 { true,         "vec4_ivec4_bvec4",             "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++", 3,      { TYPE_FLOAT_VEC4,      TYPE_INT_VEC4,          TYPE_BOOL_VEC4  },      TYPE_INT_VEC4,          evalSequenceSideEffCase3 }
1489         };
1490
1491         for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_sequenceCases); caseNdx++)
1492         {
1493                 for (int precision = 0; precision < (int)PRECISION_LAST; precision++)
1494                 {
1495                         for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
1496                         {
1497                                 ShaderType              shaderType              = s_shaderTypes[shaderTypeNdx];
1498                                 ShaderDataSpec  shaderSpec;
1499                                 const char*             shaderTypeName  = getShaderTypeName(shaderType);
1500                                 bool                    isVertexCase    = (ShaderType)shaderType == SHADERTYPE_VERTEX;
1501
1502                                 string name     = string("") + getPrecisionName((Precision)precision) + "_" + s_sequenceCases[caseNdx].caseName + "_" + shaderTypeName;
1503
1504                                 shaderSpec.numInputs    = s_sequenceCases[caseNdx].numInputs;
1505                                 shaderSpec.precision    = (Precision)precision;
1506                                 shaderSpec.output               = s_sequenceCases[caseNdx].resultType;
1507                                 shaderSpec.resultScale  = 0.5f;
1508                                 shaderSpec.resultBias   = 0.0f;
1509
1510                                 for (int inputNdx = 0; inputNdx < s_sequenceCases[caseNdx].numInputs; inputNdx++)
1511                                 {
1512                                         DataType        type            = s_sequenceCases[caseNdx].inputTypes[inputNdx];
1513                                         float           rangeMin        = isDataTypeFloatOrVec(type) ? -0.5f : isDataTypeIntOrIVec(type) ? -2.0f : -1.0f;
1514                                         float           rangeMax        = isDataTypeFloatOrVec(type) ?  0.5f : isDataTypeIntOrIVec(type) ?  2.0f :  1.0f;
1515
1516                                         shaderSpec.inputs[inputNdx] = ShaderValue(type, rangeMin, rangeMax);
1517                                 }
1518
1519                                 string expression = string("") + "res = (" + s_sequenceCases[caseNdx].expressionStr + ");";
1520
1521                                 TestCaseGroup* group = s_sequenceCases[caseNdx].containsSideEffects ? sequenceSideEffGroup : sequenceNoSideEffGroup;
1522                                 group->addChild(new ShaderOperatorCase(m_context, name.c_str(), "", isVertexCase, s_sequenceCases[caseNdx].evalFunc, expression.c_str(), shaderSpec));
1523                         }
1524                 }
1525         }
1526 }
1527
1528 } // Functional
1529 } // gles2
1530 } // deqp