xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fShaderOperatorTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.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 "es3fShaderOperatorTests.hpp"
25 #include "glsShaderRenderCase.hpp"
26 #include "gluShaderUtil.hpp"
27 #include "tcuStringTemplate.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "glwFunctions.hpp"
30 #include "glwEnums.hpp"
31 
32 #include "deStringUtil.hpp"
33 #include "deInt32.h"
34 #include "deMemory.h"
35 
36 #include <map>
37 #include <limits>
38 
39 using namespace tcu;
40 using namespace glu;
41 using namespace deqp::gls;
42 
43 using std::map;
44 using std::ostringstream;
45 using std::pair;
46 using std::string;
47 using std::vector;
48 
49 namespace deqp
50 {
51 namespace gles3
52 {
53 namespace Functional
54 {
55 
56 #if defined(abs)
57 #undef abs
58 #endif
59 
60 using de::clamp;
61 using de::max;
62 using de::min;
63 
64 // \note VS2013 gets confused without these
65 using tcu::acosh;
66 using tcu::asinh;
67 using tcu::atanh;
68 using tcu::exp2;
69 using tcu::log2;
70 using tcu::trunc;
71 
abs(float v)72 inline float abs(float v)
73 {
74     return deFloatAbs(v);
75 }
76 
logicalAnd(bool a,bool b)77 inline bool logicalAnd(bool a, bool b)
78 {
79     return (a && b);
80 }
logicalOr(bool a,bool b)81 inline bool logicalOr(bool a, bool b)
82 {
83     return (a || b);
84 }
logicalXor(bool a,bool b)85 inline bool logicalXor(bool a, bool b)
86 {
87     return (a != b);
88 }
89 
90 // \note stdlib.h defines div() that is not compatible with the macros.
91 template <typename T>
div(T a,T b)92 inline T div(T a, T b)
93 {
94     return a / b;
95 }
96 
97 template <typename T>
leftShift(T value,int amount)98 inline T leftShift(T value, int amount)
99 {
100     return value << amount;
101 }
102 
rightShift(uint32_t value,int amount)103 inline uint32_t rightShift(uint32_t value, int amount)
104 {
105     return value >> amount;
106 }
rightShift(int value,int amount)107 inline int rightShift(int value, int amount)
108 {
109     return (value >> amount) | (value >= 0 ? 0 : ~(~0U >> amount));
110 } // \note Arithmetic shift.
111 
112 template <typename T, int Size>
leftShift(const Vector<T,Size> & value,const Vector<int,Size> & amount)113 Vector<T, Size> leftShift(const Vector<T, Size> &value, const Vector<int, Size> &amount)
114 {
115     Vector<T, Size> result;
116     for (int i = 0; i < Size; i++)
117         result[i] = leftShift(value[i], amount[i]);
118     return result;
119 }
120 
121 template <typename T, int Size>
rightShift(const Vector<T,Size> & value,const Vector<int,Size> & amount)122 Vector<T, Size> rightShift(const Vector<T, Size> &value, const Vector<int, Size> &amount)
123 {
124     Vector<T, Size> result;
125     for (int i = 0; i < Size; i++)
126         result[i] = rightShift(value[i], amount[i]);
127     return result;
128 }
129 
130 template <typename T, int Size>
leftShiftVecScalar(const Vector<T,Size> & value,int amount)131 Vector<T, Size> leftShiftVecScalar(const Vector<T, Size> &value, int amount)
132 {
133     return leftShift(value, Vector<int, Size>(amount));
134 }
135 template <typename T, int Size>
rightShiftVecScalar(const Vector<T,Size> & value,int amount)136 Vector<T, Size> rightShiftVecScalar(const Vector<T, Size> &value, int amount)
137 {
138     return rightShift(value, Vector<int, Size>(amount));
139 }
140 
141 template <typename T, int Size>
minVecScalar(const Vector<T,Size> & v,T s)142 inline Vector<T, Size> minVecScalar(const Vector<T, Size> &v, T s)
143 {
144     Vector<T, Size> res;
145     for (int i = 0; i < Size; i++)
146         res[i] = min(v[i], s);
147     return res;
148 }
149 
150 template <typename T, int Size>
maxVecScalar(const Vector<T,Size> & v,T s)151 inline Vector<T, Size> maxVecScalar(const Vector<T, Size> &v, T s)
152 {
153     Vector<T, Size> res;
154     for (int i = 0; i < Size; i++)
155         res[i] = max(v[i], s);
156     return res;
157 }
158 
159 template <typename T, int Size>
clampVecScalarScalar(const Vector<T,Size> & v,T s0,T s1)160 inline Vector<T, Size> clampVecScalarScalar(const Vector<T, Size> &v, T s0, T s1)
161 {
162     Vector<T, Size> res;
163     for (int i = 0; i < Size; i++)
164         res[i] = clamp(v[i], s0, s1);
165     return res;
166 }
167 
168 template <typename T, int Size>
mixVecVecScalar(const Vector<T,Size> & v0,const Vector<T,Size> & v1,T s)169 inline Vector<T, Size> mixVecVecScalar(const Vector<T, Size> &v0, const Vector<T, Size> &v1, T s)
170 {
171     Vector<T, Size> res;
172     for (int i = 0; i < Size; i++)
173         res[i] = mix(v0[i], v1[i], s);
174     return res;
175 }
176 
177 template <typename T, int Size>
stepScalarVec(T s,const Vector<T,Size> & v)178 inline Vector<T, Size> stepScalarVec(T s, const Vector<T, Size> &v)
179 {
180     Vector<T, Size> res;
181     for (int i = 0; i < Size; i++)
182         res[i] = step(s, v[i]);
183     return res;
184 }
185 
186 template <typename T, int Size>
smoothStepScalarScalarVec(T s0,T s1,const Vector<T,Size> & v)187 inline Vector<T, Size> smoothStepScalarScalarVec(T s0, T s1, const Vector<T, Size> &v)
188 {
189     Vector<T, Size> res;
190     for (int i = 0; i < Size; i++)
191         res[i] = smoothStep(s0, s1, v[i]);
192     return res;
193 }
194 
addOne(float v)195 inline float addOne(float v)
196 {
197     return v + 1.0f;
198 }
subOne(float v)199 inline float subOne(float v)
200 {
201     return v - 1.0f;
202 }
addOne(int v)203 inline int addOne(int v)
204 {
205     return v + 1;
206 }
subOne(int v)207 inline int subOne(int v)
208 {
209     return v - 1;
210 }
addOne(uint32_t v)211 inline uint32_t addOne(uint32_t v)
212 {
213     return v + 1;
214 }
subOne(uint32_t v)215 inline uint32_t subOne(uint32_t v)
216 {
217     return v - 1;
218 }
219 
220 template <int Size>
addOne(const Vector<float,Size> & v)221 inline Vector<float, Size> addOne(const Vector<float, Size> &v)
222 {
223     return v + 1.0f;
224 }
225 template <int Size>
subOne(const Vector<float,Size> & v)226 inline Vector<float, Size> subOne(const Vector<float, Size> &v)
227 {
228     return v - 1.0f;
229 }
230 template <int Size>
addOne(const Vector<int,Size> & v)231 inline Vector<int, Size> addOne(const Vector<int, Size> &v)
232 {
233     return v + 1;
234 }
235 template <int Size>
subOne(const Vector<int,Size> & v)236 inline Vector<int, Size> subOne(const Vector<int, Size> &v)
237 {
238     return v - 1;
239 }
240 template <int Size>
addOne(const Vector<uint32_t,Size> & v)241 inline Vector<uint32_t, Size> addOne(const Vector<uint32_t, Size> &v)
242 {
243     return v + 1U;
244 }
245 template <int Size>
subOne(const Vector<uint32_t,Size> & v)246 inline Vector<uint32_t, Size> subOne(const Vector<uint32_t, Size> &v)
247 {
248     return (v.asInt() - 1).asUint();
249 }
250 
251 template <typename T>
selection(bool cond,T a,T b)252 inline T selection(bool cond, T a, T b)
253 {
254     return cond ? a : b;
255 }
256 
257 // Vec-scalar and scalar-vec binary operators.
258 
259 // \note This one is done separately due to how the overloaded minus operator is implemented for vector-scalar operands.
260 template <int Size>
subVecScalar(const Vector<uint32_t,Size> & v,uint32_t s)261 inline Vector<uint32_t, Size> subVecScalar(const Vector<uint32_t, Size> &v, uint32_t s)
262 {
263     return (v.asInt() - (int)s).asUint();
264 }
265 
266 template <typename T, int Size>
addVecScalar(const Vector<T,Size> & v,T s)267 inline Vector<T, Size> addVecScalar(const Vector<T, Size> &v, T s)
268 {
269     return v + s;
270 }
271 
272 // Specialize add, sub, and mul integer operations to use 64bit to avoid undefined signed integer overflows.
add(int a,int b)273 inline int add(int a, int b)
274 {
275     return static_cast<int>(static_cast<int64_t>(a) + static_cast<int64_t>(b));
276 }
sub(int a,int b)277 inline int sub(int a, int b)
278 {
279     return static_cast<int>(static_cast<int64_t>(a) - static_cast<int64_t>(b));
280 }
mul(int a,int b)281 inline int mul(int a, int b)
282 {
283     return static_cast<int>(static_cast<int64_t>(a) * static_cast<int64_t>(b));
284 }
285 
add(uint32_t a,uint32_t b)286 inline uint32_t add(uint32_t a, uint32_t b)
287 {
288     return a + b;
289 }
sub(uint32_t a,uint32_t b)290 inline uint32_t sub(uint32_t a, uint32_t b)
291 {
292     return a - b;
293 }
mul(uint32_t a,uint32_t b)294 inline uint32_t mul(uint32_t a, uint32_t b)
295 {
296     return a * b;
297 }
298 
299 #define DECLARE_IVEC_BINARY_FUNC(OP_NAME)                                                    \
300     template <int Size>                                                                      \
301     inline Vector<int, Size> OP_NAME(const Vector<int, Size> &a, const Vector<int, Size> &b) \
302     {                                                                                        \
303         Vector<int, Size> res;                                                               \
304         for (int i = 0; i < Size; i++)                                                       \
305             res.m_data[i] = OP_NAME(a.m_data[i], b.m_data[i]);                               \
306         return res;                                                                          \
307     }
308 
309 #define DECLARE_IVEC_INT_BINARY_FUNC(OP_NAME)                                      \
310     template <int Size>                                                            \
311     inline Vector<int, Size> OP_NAME##VecScalar(const Vector<int, Size> &v, int s) \
312     {                                                                              \
313         Vector<int, Size> ret;                                                     \
314         for (int i = 0; i < Size; i++)                                             \
315             ret[i] = OP_NAME(v.m_data[i], s);                                      \
316         return ret;                                                                \
317     };
318 
319 #define DECLARE_INT_IVEC_BINARY_FUNC(OP_NAME)                                      \
320     template <int Size>                                                            \
321     inline Vector<int, Size> OP_NAME##ScalarVec(int s, const Vector<int, Size> &v) \
322     {                                                                              \
323         Vector<int, Size> ret;                                                     \
324         for (int i = 0; i < Size; i++)                                             \
325             ret[i] = OP_NAME(s, v.m_data[i]);                                      \
326         return ret;                                                                \
327     };
328 
329 DECLARE_IVEC_BINARY_FUNC(add)
DECLARE_IVEC_BINARY_FUNC(sub)330 DECLARE_IVEC_BINARY_FUNC(sub)
331 DECLARE_IVEC_BINARY_FUNC(mul)
332 DECLARE_IVEC_INT_BINARY_FUNC(add)
333 DECLARE_IVEC_INT_BINARY_FUNC(sub)
334 DECLARE_IVEC_INT_BINARY_FUNC(mul)
335 DECLARE_INT_IVEC_BINARY_FUNC(add)
336 DECLARE_INT_IVEC_BINARY_FUNC(sub)
337 DECLARE_INT_IVEC_BINARY_FUNC(mul)
338 
339 template <typename T, int Size>
340 inline Vector<T, Size> subVecScalar(const Vector<T, Size> &v, T s)
341 {
342     return v - s;
343 }
344 template <typename T, int Size>
mulVecScalar(const Vector<T,Size> & v,T s)345 inline Vector<T, Size> mulVecScalar(const Vector<T, Size> &v, T s)
346 {
347     return v * s;
348 }
349 template <typename T, int Size>
divVecScalar(const Vector<T,Size> & v,T s)350 inline Vector<T, Size> divVecScalar(const Vector<T, Size> &v, T s)
351 {
352     return v / s;
353 }
354 template <typename T, int Size>
modVecScalar(const Vector<T,Size> & v,T s)355 inline Vector<T, Size> modVecScalar(const Vector<T, Size> &v, T s)
356 {
357     return mod(v, Vector<T, Size>(s));
358 }
359 template <typename T, int Size>
bitwiseAndVecScalar(const Vector<T,Size> & v,T s)360 inline Vector<T, Size> bitwiseAndVecScalar(const Vector<T, Size> &v, T s)
361 {
362     return bitwiseAnd(v, Vector<T, Size>(s));
363 }
364 template <typename T, int Size>
bitwiseOrVecScalar(const Vector<T,Size> & v,T s)365 inline Vector<T, Size> bitwiseOrVecScalar(const Vector<T, Size> &v, T s)
366 {
367     return bitwiseOr(v, Vector<T, Size>(s));
368 }
369 template <typename T, int Size>
bitwiseXorVecScalar(const Vector<T,Size> & v,T s)370 inline Vector<T, Size> bitwiseXorVecScalar(const Vector<T, Size> &v, T s)
371 {
372     return bitwiseXor(v, Vector<T, Size>(s));
373 }
374 
375 template <typename T, int Size>
addScalarVec(T s,const Vector<T,Size> & v)376 inline Vector<T, Size> addScalarVec(T s, const Vector<T, Size> &v)
377 {
378     return s + v;
379 }
380 template <typename T, int Size>
subScalarVec(T s,const Vector<T,Size> & v)381 inline Vector<T, Size> subScalarVec(T s, const Vector<T, Size> &v)
382 {
383     return s - v;
384 }
385 template <typename T, int Size>
mulScalarVec(T s,const Vector<T,Size> & v)386 inline Vector<T, Size> mulScalarVec(T s, const Vector<T, Size> &v)
387 {
388     return s * v;
389 }
390 template <typename T, int Size>
divScalarVec(T s,const Vector<T,Size> & v)391 inline Vector<T, Size> divScalarVec(T s, const Vector<T, Size> &v)
392 {
393     return s / v;
394 }
395 template <typename T, int Size>
modScalarVec(T s,const Vector<T,Size> & v)396 inline Vector<T, Size> modScalarVec(T s, const Vector<T, Size> &v)
397 {
398     return mod(Vector<T, Size>(s), v);
399 }
400 template <typename T, int Size>
bitwiseAndScalarVec(T s,const Vector<T,Size> & v)401 inline Vector<T, Size> bitwiseAndScalarVec(T s, const Vector<T, Size> &v)
402 {
403     return bitwiseAnd(Vector<T, Size>(s), v);
404 }
405 template <typename T, int Size>
bitwiseOrScalarVec(T s,const Vector<T,Size> & v)406 inline Vector<T, Size> bitwiseOrScalarVec(T s, const Vector<T, Size> &v)
407 {
408     return bitwiseOr(Vector<T, Size>(s), v);
409 }
410 template <typename T, int Size>
bitwiseXorScalarVec(T s,const Vector<T,Size> & v)411 inline Vector<T, Size> bitwiseXorScalarVec(T s, const Vector<T, Size> &v)
412 {
413     return bitwiseXor(Vector<T, Size>(s), v);
414 }
415 
416 // Reference functions for specific sequence operations for the sequence operator tests.
417 
418 // Reference for expression "in0, in2 + in1, in1 + in0"
sequenceNoSideEffCase0(const Vec4 & in0,const Vec4 & in1,const Vec4 & in2)419 inline Vec4 sequenceNoSideEffCase0(const Vec4 &in0, const Vec4 &in1, const Vec4 &in2)
420 {
421     DE_UNREF(in2);
422     return in1 + in0;
423 }
424 // Reference for expression "in0, in2 + in1, in1 + in0"
sequenceNoSideEffCase1(float in0,uint32_t in1,float in2)425 inline uint32_t sequenceNoSideEffCase1(float in0, uint32_t in1, float in2)
426 {
427     DE_UNREF(in0);
428     DE_UNREF(in2);
429     return in1 + in1;
430 }
431 // Reference for expression "in0 && in1, in0, ivec2(vec2(in0) + in2)"
sequenceNoSideEffCase2(bool in0,bool in1,const Vec2 & in2)432 inline IVec2 sequenceNoSideEffCase2(bool in0, bool in1, const Vec2 &in2)
433 {
434     DE_UNREF(in1);
435     return IVec2((int)((float)in0 + in2.x()), (int)((float)in0 + in2.y()));
436 }
437 // Reference for expression "in0 + vec4(in1), in2, in1"
sequenceNoSideEffCase3(const Vec4 & in0,const IVec4 & in1,const BVec4 & in2)438 inline IVec4 sequenceNoSideEffCase3(const Vec4 &in0, const IVec4 &in1, const BVec4 &in2)
439 {
440     DE_UNREF(in0);
441     DE_UNREF(in2);
442     return in1;
443 }
444 // Reference for expression "in0++, in1 = in0 + in2, in2 = in1"
sequenceSideEffCase0(const Vec4 & in0,const Vec4 & in1,const Vec4 & in2)445 inline Vec4 sequenceSideEffCase0(const Vec4 &in0, const Vec4 &in1, const Vec4 &in2)
446 {
447     DE_UNREF(in1);
448     return in0 + 1.0f + in2;
449 }
450 // Reference for expression "in1++, in0 = float(in1), in1 = uint(in0 + in2)"
sequenceSideEffCase1(float in0,uint32_t in1,float in2)451 inline uint32_t sequenceSideEffCase1(float in0, uint32_t in1, float in2)
452 {
453     DE_UNREF(in0);
454     return (uint32_t)(float(in1) + 1.0f + in2);
455 }
456 // Reference for expression "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)"
sequenceSideEffCase2(bool in0,bool in1,const Vec2 & in2)457 inline IVec2 sequenceSideEffCase2(bool in0, bool in1, const Vec2 &in2)
458 {
459     DE_UNREF(in1);
460     return (in2 + Vec2(1.0f) + Vec2((float)in0)).asInt();
461 }
462 // Reference for expression "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++"
sequenceSideEffCase3(const Vec4 & in0,const IVec4 & in1,const BVec4 & in2)463 inline IVec4 sequenceSideEffCase3(const Vec4 &in0, const IVec4 &in1, const BVec4 &in2)
464 {
465     return in1 + (in0 + Vec4((float)in2.x(), (float)in2.y(), (float)in2.z(), (float)in2.w())).asInt();
466 }
467 
468 // ShaderEvalFunc-type wrappers for the above functions.
evalSequenceNoSideEffCase0(ShaderEvalContext & ctx)469 void evalSequenceNoSideEffCase0(ShaderEvalContext &ctx)
470 {
471     ctx.color = sequenceNoSideEffCase0(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0),
472                                        ctx.in[2].swizzle(0, 3, 2, 1));
473 }
evalSequenceNoSideEffCase1(ShaderEvalContext & ctx)474 void evalSequenceNoSideEffCase1(ShaderEvalContext &ctx)
475 {
476     ctx.color.x() = (float)sequenceNoSideEffCase1(ctx.in[0].z(), (uint32_t)ctx.in[1].x(), ctx.in[2].y());
477 }
evalSequenceNoSideEffCase2(ShaderEvalContext & ctx)478 void evalSequenceNoSideEffCase2(ShaderEvalContext &ctx)
479 {
480     ctx.color.yz() =
481         sequenceNoSideEffCase2(ctx.in[0].z() > 0.0f, ctx.in[1].x() > 0.0f, ctx.in[2].swizzle(2, 1)).asFloat();
482 }
evalSequenceNoSideEffCase3(ShaderEvalContext & ctx)483 void evalSequenceNoSideEffCase3(ShaderEvalContext &ctx)
484 {
485     ctx.color = sequenceNoSideEffCase3(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0).asInt(),
486                                        greaterThan(ctx.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f)))
487                     .asFloat();
488 }
evalSequenceSideEffCase0(ShaderEvalContext & ctx)489 void evalSequenceSideEffCase0(ShaderEvalContext &ctx)
490 {
491     ctx.color = sequenceSideEffCase0(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0),
492                                      ctx.in[2].swizzle(0, 3, 2, 1));
493 }
evalSequenceSideEffCase1(ShaderEvalContext & ctx)494 void evalSequenceSideEffCase1(ShaderEvalContext &ctx)
495 {
496     ctx.color.x() = (float)sequenceSideEffCase1(ctx.in[0].z(), (uint32_t)ctx.in[1].x(), ctx.in[2].y());
497 }
evalSequenceSideEffCase2(ShaderEvalContext & ctx)498 void evalSequenceSideEffCase2(ShaderEvalContext &ctx)
499 {
500     ctx.color.yz() =
501         sequenceSideEffCase2(ctx.in[0].z() > 0.0f, ctx.in[1].x() > 0.0f, ctx.in[2].swizzle(2, 1)).asFloat();
502 }
evalSequenceSideEffCase3(ShaderEvalContext & ctx)503 void evalSequenceSideEffCase3(ShaderEvalContext &ctx)
504 {
505     ctx.color = sequenceSideEffCase3(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0).asInt(),
506                                      greaterThan(ctx.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f)))
507                     .asFloat();
508 }
509 
stringJoin(const vector<string> & elems,const string & delim)510 static string stringJoin(const vector<string> &elems, const string &delim)
511 {
512     string result;
513     for (int i = 0; i < (int)elems.size(); i++)
514         result += (i > 0 ? delim : "") + elems[i];
515     return result;
516 }
517 
stringReplace(string & str,const string & from,const string & to)518 static void stringReplace(string &str, const string &from, const string &to)
519 {
520     size_t start_pos = 0;
521     while ((start_pos = str.find(from, start_pos)) != std::string::npos)
522     {
523         str.replace(start_pos, from.length(), to);
524         start_pos += to.length();
525     }
526 }
527 
twoValuedVec4(const string & first,const string & second,const BVec4 & firstMask)528 static string twoValuedVec4(const string &first, const string &second, const BVec4 &firstMask)
529 {
530     vector<string> elems(4);
531     for (int i = 0; i < 4; i++)
532         elems[i] = firstMask[i] ? first : second;
533 
534     return "vec4(" + stringJoin(elems, ", ") + ")";
535 }
536 
537 enum
538 {
539     MAX_INPUTS = 3
540 };
541 
542 enum PrecisionMask
543 {
544     PRECMASK_NA      = 0, //!< Precision not applicable (booleans)
545     PRECMASK_LOWP    = (1 << PRECISION_LOWP),
546     PRECMASK_MEDIUMP = (1 << PRECISION_MEDIUMP),
547     PRECMASK_HIGHP   = (1 << PRECISION_HIGHP),
548 
549     PRECMASK_LOWP_MEDIUMP  = PRECMASK_LOWP | PRECMASK_MEDIUMP,
550     PRECMASK_MEDIUMP_HIGHP = PRECMASK_MEDIUMP | PRECMASK_HIGHP,
551     PRECMASK_ALL           = PRECMASK_LOWP | PRECMASK_MEDIUMP | PRECMASK_HIGHP
552 };
553 
554 enum ValueType
555 {
556     VALUE_NONE          = 0,
557     VALUE_FLOAT         = (1 << 0),  // float scalar
558     VALUE_FLOAT_VEC     = (1 << 1),  // float vector
559     VALUE_FLOAT_GENTYPE = (1 << 2),  // float scalar/vector
560     VALUE_VEC3          = (1 << 3),  // vec3 only
561     VALUE_MATRIX        = (1 << 4),  // matrix
562     VALUE_BOOL          = (1 << 5),  // boolean scalar
563     VALUE_BOOL_VEC      = (1 << 6),  // boolean vector
564     VALUE_BOOL_GENTYPE  = (1 << 7),  // boolean scalar/vector
565     VALUE_INT           = (1 << 8),  // int scalar
566     VALUE_INT_VEC       = (1 << 9),  // int vector
567     VALUE_INT_GENTYPE   = (1 << 10), // int scalar/vector
568     VALUE_UINT          = (1 << 11), // uint scalar
569     VALUE_UINT_VEC      = (1 << 12), // uint vector
570     VALUE_UINT_GENTYPE  = (1 << 13), // uint scalar/vector
571 
572     // Shorthands.
573     F   = VALUE_FLOAT,
574     FV  = VALUE_FLOAT_VEC,
575     GT  = VALUE_FLOAT_GENTYPE,
576     V3  = VALUE_VEC3,
577     M   = VALUE_MATRIX,
578     B   = VALUE_BOOL,
579     BV  = VALUE_BOOL_VEC,
580     BGT = VALUE_BOOL_GENTYPE,
581     I   = VALUE_INT,
582     IV  = VALUE_INT_VEC,
583     IGT = VALUE_INT_GENTYPE,
584     U   = VALUE_UINT,
585     UV  = VALUE_UINT_VEC,
586     UGT = VALUE_UINT_GENTYPE
587 };
588 
isScalarType(ValueType type)589 static inline bool isScalarType(ValueType type)
590 {
591     return type == VALUE_FLOAT || type == VALUE_BOOL || type == VALUE_INT || type == VALUE_UINT;
592 }
593 
isFloatType(ValueType type)594 static inline bool isFloatType(ValueType type)
595 {
596     return (type & (VALUE_FLOAT | VALUE_FLOAT_VEC | VALUE_FLOAT_GENTYPE)) != 0;
597 }
598 
isIntType(ValueType type)599 static inline bool isIntType(ValueType type)
600 {
601     return (type & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
602 }
603 
isUintType(ValueType type)604 static inline bool isUintType(ValueType type)
605 {
606     return (type & (VALUE_UINT | VALUE_UINT_VEC | VALUE_UINT_GENTYPE)) != 0;
607 }
608 
isBoolType(ValueType type)609 static inline bool isBoolType(ValueType type)
610 {
611     return (type & (VALUE_BOOL | VALUE_BOOL_VEC | VALUE_BOOL_GENTYPE)) != 0;
612 }
613 
getGLSLUintBits(const glw::Functions & gl,ShaderType shaderType,Precision uintPrecision)614 static inline int getGLSLUintBits(const glw::Functions &gl, ShaderType shaderType, Precision uintPrecision)
615 {
616     uint32_t intPrecisionGL;
617     uint32_t shaderTypeGL;
618 
619     switch (uintPrecision)
620     {
621     case PRECISION_LOWP:
622         intPrecisionGL = GL_LOW_INT;
623         break;
624     case PRECISION_MEDIUMP:
625         intPrecisionGL = GL_MEDIUM_INT;
626         break;
627     case PRECISION_HIGHP:
628         intPrecisionGL = GL_HIGH_INT;
629         break;
630     default:
631         DE_ASSERT(false);
632         intPrecisionGL = 0;
633     }
634 
635     switch (shaderType)
636     {
637     case SHADERTYPE_VERTEX:
638         shaderTypeGL = GL_VERTEX_SHADER;
639         break;
640     case SHADERTYPE_FRAGMENT:
641         shaderTypeGL = GL_FRAGMENT_SHADER;
642         break;
643     default:
644         DE_ASSERT(false);
645         shaderTypeGL = 0;
646     }
647 
648     glw::GLint range[2]  = {-1, -1};
649     glw::GLint precision = -1;
650 
651     gl.getShaderPrecisionFormat(shaderTypeGL, intPrecisionGL, &range[0], &precision);
652     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderPrecisionFormat failed");
653 
654     TCU_CHECK(de::inBounds(range[0], 8, 32));
655 
656     const int numBitsInType = range[0] + 1;
657     return numBitsInType;
658 }
659 
getGLSLUintMaxAsFloat(const glw::Functions & gl,ShaderType shaderType,Precision uintPrecision)660 static inline float getGLSLUintMaxAsFloat(const glw::Functions &gl, ShaderType shaderType, Precision uintPrecision)
661 {
662     const int numBitsInType             = getGLSLUintBits(gl, shaderType, uintPrecision);
663     const float maxAsFloat              = static_cast<float>((1ull << numBitsInType) - 1);
664     const float maxRepresentableAsFloat = floorf(nextafterf(maxAsFloat, 0));
665 
666     // Not accurate for integers wider than 24 bits.
667     return numBitsInType > 24 ? maxRepresentableAsFloat : maxAsFloat;
668 }
669 
670 // Float scalar that can be either constant or a symbol that can be evaluated later.
671 class FloatScalar
672 {
673 public:
674     enum Symbol
675     {
676         SYMBOL_LOWP_UINT_MAX = 0,
677         SYMBOL_MEDIUMP_UINT_MAX,
678 
679         SYMBOL_LOWP_UINT_MAX_RECIPROCAL,
680         SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL,
681 
682         SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX,
683         SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX,
684 
685         SYMBOL_LAST
686     };
687 
FloatScalar(float c)688     FloatScalar(float c) : m_isConstant(true), m_value(c)
689     {
690     }
FloatScalar(Symbol s)691     FloatScalar(Symbol s) : m_isConstant(false), m_value(s)
692     {
693     }
694 
getValue(const glw::Functions & gl,ShaderType shaderType) const695     float getValue(const glw::Functions &gl, ShaderType shaderType) const
696     {
697         if (m_isConstant)
698             return m_value.constant;
699         else
700         {
701             switch (m_value.symbol)
702             {
703             case SYMBOL_LOWP_UINT_MAX:
704                 return getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_LOWP);
705             case SYMBOL_MEDIUMP_UINT_MAX:
706                 return getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_MEDIUMP);
707 
708             case SYMBOL_LOWP_UINT_MAX_RECIPROCAL:
709                 return 1.0f / getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_LOWP);
710             case SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL:
711                 return 1.0f / getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_MEDIUMP);
712 
713             case SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX:
714                 return 1.0f - (float)std::numeric_limits<uint32_t>::max() /
715                                   getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_LOWP);
716             case SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX:
717                 return 1.0f - (float)std::numeric_limits<uint32_t>::max() /
718                                   getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_MEDIUMP);
719 
720             default:
721                 DE_ASSERT(false);
722                 return 0.0f;
723             }
724         }
725     }
726 
getValueMask(const glw::Functions & gl,ShaderType shaderType) const727     uint32_t getValueMask(const glw::Functions &gl, ShaderType shaderType) const
728     {
729         if (m_isConstant)
730             return 0;
731 
732         int bits = 0;
733         switch (m_value.symbol)
734         {
735         case SYMBOL_LOWP_UINT_MAX_RECIPROCAL:
736         case SYMBOL_LOWP_UINT_MAX:
737             bits = getGLSLUintBits(gl, shaderType, PRECISION_LOWP);
738             break;
739 
740         case SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL:
741         case SYMBOL_MEDIUMP_UINT_MAX:
742             bits = getGLSLUintBits(gl, shaderType, PRECISION_MEDIUMP);
743             break;
744 
745         case SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX:
746         case SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX:
747             return 0;
748 
749         default:
750             DE_ASSERT(false);
751             return 0;
752         }
753 
754         return bits == 32 ? 0 : (1u << bits) - 1;
755     }
756 
757 private:
758     bool m_isConstant;
759 
760     union ConstantOrSymbol
761     {
762         float constant;
763         Symbol symbol;
764 
ConstantOrSymbol(float c)765         ConstantOrSymbol(float c) : constant(c)
766         {
767         }
ConstantOrSymbol(Symbol s)768         ConstantOrSymbol(Symbol s) : symbol(s)
769         {
770         }
771     } m_value;
772 };
773 
774 struct Value
775 {
Valuedeqp::gles3::Functional::Value776     Value(ValueType valueType_, const FloatScalar &rangeMin_, const FloatScalar &rangeMax_)
777         : valueType(valueType_)
778         , rangeMin(rangeMin_)
779         , rangeMax(rangeMax_)
780     {
781     }
782 
783     ValueType valueType;
784     FloatScalar rangeMin;
785     FloatScalar rangeMax;
786 };
787 
788 enum OperationType
789 {
790     FUNCTION = 0,
791     OPERATOR,
792     SIDE_EFFECT_OPERATOR // Test the side-effect (as opposed to the result) of a side-effect operator.
793 };
794 
795 struct BuiltinFuncInfo
796 {
BuiltinFuncInfodeqp::gles3::Functional::BuiltinFuncInfo797     BuiltinFuncInfo(const char *caseName_, const char *shaderFuncName_, ValueType outValue_, Value input0_,
798                     Value input1_, Value input2_, const FloatScalar &resultScale_, const FloatScalar &resultBias_,
799                     uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_,
800                     ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_, OperationType type_ = FUNCTION,
801                     bool isUnaryPrefix_ = true)
802         : caseName(caseName_)
803         , shaderFuncName(shaderFuncName_)
804         , outValue(outValue_)
805         , input0(input0_)
806         , input1(input1_)
807         , input2(input2_)
808         , resultScale(resultScale_)
809         , resultBias(resultBias_)
810         , referenceScale(resultScale_)
811         , referenceBias(resultBias_)
812         , precisionMask(precisionMask_)
813         , evalFuncScalar(evalFuncScalar_)
814         , evalFuncVec2(evalFuncVec2_)
815         , evalFuncVec3(evalFuncVec3_)
816         , evalFuncVec4(evalFuncVec4_)
817         , type(type_)
818         , isUnaryPrefix(isUnaryPrefix_)
819     {
820     }
821 
BuiltinFuncInfodeqp::gles3::Functional::BuiltinFuncInfo822     BuiltinFuncInfo(const char *caseName_, const char *shaderFuncName_, ValueType outValue_, Value input0_,
823                     Value input1_, Value input2_, const FloatScalar &resultScale_, const FloatScalar &resultBias_,
824                     const FloatScalar &referenceScale_, const FloatScalar &referenceBias_, uint32_t precisionMask_,
825                     ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
826                     ShaderEvalFunc evalFuncVec4_, OperationType type_ = FUNCTION, bool isUnaryPrefix_ = true)
827         : caseName(caseName_)
828         , shaderFuncName(shaderFuncName_)
829         , outValue(outValue_)
830         , input0(input0_)
831         , input1(input1_)
832         , input2(input2_)
833         , resultScale(resultScale_)
834         , resultBias(resultBias_)
835         , referenceScale(referenceScale_)
836         , referenceBias(referenceBias_)
837         , precisionMask(precisionMask_)
838         , evalFuncScalar(evalFuncScalar_)
839         , evalFuncVec2(evalFuncVec2_)
840         , evalFuncVec3(evalFuncVec3_)
841         , evalFuncVec4(evalFuncVec4_)
842         , type(type_)
843         , isUnaryPrefix(isUnaryPrefix_)
844     {
845     }
846 
847     const char *caseName;       //!< Name of case.
848     const char *shaderFuncName; //!< Name in shading language.
849     ValueType outValue;
850     Value input0;
851     Value input1;
852     Value input2;
853     FloatScalar resultScale;
854     FloatScalar resultBias;
855     FloatScalar referenceScale;
856     FloatScalar referenceBias;
857     uint32_t precisionMask;
858     ShaderEvalFunc evalFuncScalar;
859     ShaderEvalFunc evalFuncVec2;
860     ShaderEvalFunc evalFuncVec3;
861     ShaderEvalFunc evalFuncVec4;
862     OperationType type;
863     bool isUnaryPrefix; //!< Whether a unary operator is a prefix operator; redundant unless unary.
864 };
865 
BuiltinOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,const FloatScalar & resultScale_,const FloatScalar & resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)866 static inline BuiltinFuncInfo BuiltinOperInfo(const char *caseName_, const char *shaderFuncName_, ValueType outValue_,
867                                               Value input0_, Value input1_, Value input2_,
868                                               const FloatScalar &resultScale_, const FloatScalar &resultBias_,
869                                               uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_,
870                                               ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
871                                               ShaderEvalFunc evalFuncVec4_)
872 {
873     return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
874                            resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_,
875                            evalFuncVec4_, OPERATOR);
876 }
877 
BuiltinOperInfoSeparateRefScaleBias(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,const FloatScalar & resultScale_,const FloatScalar & resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_,const FloatScalar & referenceScale_,const FloatScalar & referenceBias_)878 static inline BuiltinFuncInfo BuiltinOperInfoSeparateRefScaleBias(
879     const char *caseName_, const char *shaderFuncName_, ValueType outValue_, Value input0_, Value input1_,
880     Value input2_, const FloatScalar &resultScale_, const FloatScalar &resultBias_, uint32_t precisionMask_,
881     ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
882     ShaderEvalFunc evalFuncVec4_, const FloatScalar &referenceScale_, const FloatScalar &referenceBias_)
883 {
884     return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
885                            referenceScale_, referenceBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_,
886                            evalFuncVec3_, evalFuncVec4_, OPERATOR);
887 }
888 
889 // For postfix (unary) operators.
BuiltinPostOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,const FloatScalar & resultScale_,const FloatScalar & resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)890 static inline BuiltinFuncInfo BuiltinPostOperInfo(const char *caseName_, const char *shaderFuncName_,
891                                                   ValueType outValue_, Value input0_, Value input1_, Value input2_,
892                                                   const FloatScalar &resultScale_, const FloatScalar &resultBias_,
893                                                   uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_,
894                                                   ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
895                                                   ShaderEvalFunc evalFuncVec4_)
896 {
897     return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
898                            resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_,
899                            evalFuncVec4_, OPERATOR, false);
900 }
901 
BuiltinSideEffOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,const FloatScalar & resultScale_,const FloatScalar & resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)902 static inline BuiltinFuncInfo BuiltinSideEffOperInfo(const char *caseName_, const char *shaderFuncName_,
903                                                      ValueType outValue_, Value input0_, Value input1_, Value input2_,
904                                                      const FloatScalar &resultScale_, const FloatScalar &resultBias_,
905                                                      uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_,
906                                                      ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
907                                                      ShaderEvalFunc evalFuncVec4_)
908 {
909     return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
910                            resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_,
911                            evalFuncVec4_, SIDE_EFFECT_OPERATOR);
912 }
913 
914 // For postfix (unary) operators, testing side-effect.
BuiltinPostSideEffOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,const FloatScalar & resultScale_,const FloatScalar & resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)915 static inline BuiltinFuncInfo BuiltinPostSideEffOperInfo(const char *caseName_, const char *shaderFuncName_,
916                                                          ValueType outValue_, Value input0_, Value input1_,
917                                                          Value input2_, const FloatScalar &resultScale_,
918                                                          const FloatScalar &resultBias_, uint32_t precisionMask_,
919                                                          ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_,
920                                                          ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
921 {
922     return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
923                            resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_,
924                            evalFuncVec4_, SIDE_EFFECT_OPERATOR, false);
925 }
926 
927 // BuiltinFuncGroup
928 
929 struct BuiltinFuncGroup
930 {
BuiltinFuncGroupdeqp::gles3::Functional::BuiltinFuncGroup931     BuiltinFuncGroup(const char *name_, const char *description_) : name(name_), description(description_)
932     {
933     }
operator <<deqp::gles3::Functional::BuiltinFuncGroup934     BuiltinFuncGroup &operator<<(const BuiltinFuncInfo &info)
935     {
936         funcInfos.push_back(info);
937         return *this;
938     }
939 
940     const char *name;
941     const char *description;
942     std::vector<BuiltinFuncInfo> funcInfos;
943 };
944 
945 static const char *s_inSwizzles[MAX_INPUTS][4] = {{"z", "wy", "zxy", "yzwx"},
946                                                   {"x", "yx", "yzx", "wzyx"},
947                                                   {"y", "zy", "wyz", "xwzy"}};
948 
949 static const char *s_outSwizzles[] = {"x", "yz", "xyz", "xyzw"};
950 
951 static const BVec4 s_outSwizzleChannelMasks[] = {BVec4(true, false, false, false), BVec4(false, true, true, false),
952                                                  BVec4(true, true, true, false), BVec4(true, true, true, true)};
953 
954 // OperatorShaderEvaluator
955 
956 class OperatorShaderEvaluator : public ShaderEvaluator
957 {
958 public:
OperatorShaderEvaluator(const glw::Functions & gl,ShaderType shaderType,ShaderEvalFunc evalFunc,const FloatScalar & scale,const FloatScalar & bias,int resultScalarSize)959     OperatorShaderEvaluator(const glw::Functions &gl, ShaderType shaderType, ShaderEvalFunc evalFunc,
960                             const FloatScalar &scale, const FloatScalar &bias, int resultScalarSize)
961         : m_gl(gl)
962         , m_shaderType(shaderType)
963         , m_evalFunc(evalFunc)
964         , m_scale(scale)
965         , m_bias(bias)
966         , m_resultScalarSize(resultScalarSize)
967         , m_areScaleAndBiasEvaluated(false)
968         , m_evaluatedScale(-1.0f)
969         , m_evaluatedBias(-1.0f)
970     {
971         DE_ASSERT(de::inRange(resultScalarSize, 1, 4));
972     }
973 
~OperatorShaderEvaluator(void)974     virtual ~OperatorShaderEvaluator(void)
975     {
976     }
977 
evaluate(ShaderEvalContext & ctx)978     virtual void evaluate(ShaderEvalContext &ctx)
979     {
980         m_evalFunc(ctx);
981 
982         if (!m_areScaleAndBiasEvaluated)
983         {
984             m_evaluatedScale           = m_scale.getValue(m_gl, m_shaderType);
985             m_evaluatedBias            = m_bias.getValue(m_gl, m_shaderType);
986             m_areScaleAndBiasEvaluated = true;
987         }
988 
989         for (int i = 0; i < 4; i++)
990             if (s_outSwizzleChannelMasks[m_resultScalarSize - 1][i])
991                 ctx.color[i] = ctx.color[i] * m_evaluatedScale + m_evaluatedBias;
992     }
993 
994 private:
995     const glw::Functions &m_gl;
996     ShaderType m_shaderType;
997     ShaderEvalFunc m_evalFunc;
998     FloatScalar m_scale;
999     FloatScalar m_bias;
1000     int m_resultScalarSize;
1001 
1002     bool m_areScaleAndBiasEvaluated;
1003     float m_evaluatedScale;
1004     float m_evaluatedBias;
1005 };
1006 
1007 // Concrete value.
1008 
1009 struct ShaderValue
1010 {
ShaderValuedeqp::gles3::Functional::ShaderValue1011     ShaderValue(DataType type_, const FloatScalar &rangeMin_, const FloatScalar &rangeMax_)
1012         : type(type_)
1013         , rangeMin(rangeMin_)
1014         , rangeMax(rangeMax_)
1015     {
1016     }
1017 
ShaderValuedeqp::gles3::Functional::ShaderValue1018     ShaderValue(void) : type(TYPE_LAST), rangeMin(0.0f), rangeMax(0.0f)
1019     {
1020     }
1021 
1022     DataType type;
1023     FloatScalar rangeMin;
1024     FloatScalar rangeMax;
1025 };
1026 
1027 struct ShaderDataSpec
1028 {
ShaderDataSpecdeqp::gles3::Functional::ShaderDataSpec1029     ShaderDataSpec(void)
1030         : resultScale(1.0f)
1031         , resultBias(0.0f)
1032         , referenceScale(1.0f)
1033         , referenceBias(0.0f)
1034         , precision(PRECISION_LAST)
1035         , output(TYPE_LAST)
1036         , numInputs(0)
1037     {
1038     }
1039 
1040     FloatScalar resultScale;
1041     FloatScalar resultBias;
1042     FloatScalar referenceScale;
1043     FloatScalar referenceBias;
1044     Precision precision;
1045     DataType output;
1046     int numInputs;
1047     ShaderValue inputs[MAX_INPUTS];
1048 };
1049 
1050 // ShaderOperatorCase
1051 
1052 class ShaderOperatorCase : public ShaderRenderCase
1053 {
1054 public:
1055     ShaderOperatorCase(Context &context, const char *caseName, const char *description, bool isVertexCase,
1056                        ShaderEvalFunc evalFunc, const string &shaderOp, const ShaderDataSpec &spec);
1057     virtual ~ShaderOperatorCase(void);
1058 
1059 protected:
1060     void setupShaderData(void);
1061 
1062 private:
1063     ShaderOperatorCase(const ShaderOperatorCase &);            // not allowed!
1064     ShaderOperatorCase &operator=(const ShaderOperatorCase &); // not allowed!
1065 
1066     ShaderDataSpec m_spec;
1067     string m_shaderOp;
1068     OperatorShaderEvaluator m_evaluator;
1069 };
1070 
ShaderOperatorCase(Context & context,const char * caseName,const char * description,bool isVertexCase,ShaderEvalFunc evalFunc,const string & shaderOp,const ShaderDataSpec & spec)1071 ShaderOperatorCase::ShaderOperatorCase(Context &context, const char *caseName, const char *description,
1072                                        bool isVertexCase, ShaderEvalFunc evalFunc, const string &shaderOp,
1073                                        const ShaderDataSpec &spec)
1074     : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), caseName,
1075                        description, isVertexCase, m_evaluator)
1076     , m_spec(spec)
1077     , m_shaderOp(shaderOp)
1078     , m_evaluator(m_renderCtx.getFunctions(), isVertexCase ? SHADERTYPE_VERTEX : SHADERTYPE_FRAGMENT, evalFunc,
1079                   spec.referenceScale, spec.referenceBias, getDataTypeScalarSize(spec.output))
1080 {
1081 }
1082 
setupShaderData(void)1083 void ShaderOperatorCase::setupShaderData(void)
1084 {
1085     ShaderType shaderType = m_isVertexCase ? SHADERTYPE_VERTEX : SHADERTYPE_FRAGMENT;
1086     const char *precision = m_spec.precision != PRECISION_LAST ? getPrecisionName(m_spec.precision) : DE_NULL;
1087     const char *inputPrecision[MAX_INPUTS];
1088 
1089     ostringstream vtx;
1090     ostringstream frag;
1091     ostringstream &op = m_isVertexCase ? vtx : frag;
1092 
1093     vtx << "#version 300 es\n";
1094     frag << "#version 300 es\n";
1095 
1096     // Compute precision for inputs.
1097     for (int i = 0; i < m_spec.numInputs; i++)
1098     {
1099         bool isBoolVal = de::inRange<int>(m_spec.inputs[i].type, TYPE_BOOL, TYPE_BOOL_VEC4);
1100         bool isIntVal  = de::inRange<int>(m_spec.inputs[i].type, TYPE_INT, TYPE_INT_VEC4);
1101         bool isUintVal = de::inRange<int>(m_spec.inputs[i].type, TYPE_UINT, TYPE_UINT_VEC4);
1102         // \note Mediump interpolators are used for booleans, and highp for integers.
1103         Precision prec    = isBoolVal ? PRECISION_MEDIUMP : isIntVal || isUintVal ? PRECISION_HIGHP : m_spec.precision;
1104         inputPrecision[i] = getPrecisionName(prec);
1105     }
1106 
1107     // Attributes.
1108     vtx << "in highp vec4 a_position;\n";
1109     for (int i = 0; i < m_spec.numInputs; i++)
1110         vtx << "in " << inputPrecision[i] << " vec4 a_in" << i << ";\n";
1111 
1112     // Color output.
1113     frag << "layout(location = 0) out mediump vec4 o_color;\n";
1114 
1115     if (m_isVertexCase)
1116     {
1117         vtx << "out mediump vec4 v_color;\n";
1118         frag << "in mediump vec4 v_color;\n";
1119     }
1120     else
1121     {
1122         for (int i = 0; i < m_spec.numInputs; i++)
1123         {
1124             vtx << "out " << inputPrecision[i] << " vec4 v_in" << i << ";\n";
1125             frag << "in " << inputPrecision[i] << " vec4 v_in" << i << ";\n";
1126         }
1127     }
1128 
1129     vtx << "\n";
1130     vtx << "void main()\n";
1131     vtx << "{\n";
1132     vtx << "    gl_Position = a_position;\n";
1133 
1134     frag << "\n";
1135     frag << "void main()\n";
1136     frag << "{\n";
1137 
1138     bool isResFloatVec = de::inRange<int>(m_spec.output, TYPE_FLOAT, TYPE_FLOAT_VEC4);
1139     bool isResBoolVec  = de::inRange<int>(m_spec.output, TYPE_BOOL, TYPE_BOOL_VEC4);
1140     bool hasReference  = !isResFloatVec && !isResBoolVec &&
1141                         (m_spec.precision == PRECISION_LOWP || m_spec.precision == PRECISION_MEDIUMP);
1142     string refShaderOp = m_shaderOp;
1143 
1144     // Expression inputs.
1145     string prefix = m_isVertexCase ? "a_" : "v_";
1146     for (int i = 0; i < m_spec.numInputs; i++)
1147     {
1148         DataType inType      = m_spec.inputs[i].type;
1149         int inSize           = getDataTypeScalarSize(inType);
1150         bool isBool          = de::inRange<int>(inType, TYPE_BOOL, TYPE_BOOL_VEC4);
1151         bool isInt           = de::inRange<int>(inType, TYPE_INT, TYPE_INT_VEC4);
1152         bool isUint          = de::inRange<int>(inType, TYPE_UINT, TYPE_UINT_VEC4);
1153         const char *typeName = getDataTypeName(inType);
1154         const char *swizzle  = s_inSwizzles[i][inSize - 1];
1155         bool hasReferenceIn  = hasReference && !isBool;
1156 
1157         // For int/uint types, generate:
1158         //
1159         //     highp type highp_inN = ...;
1160         //     precision type inN = highp_inN;
1161         //
1162         // inN_high will be used later for reference checking.
1163         //
1164         // For other types, generate:
1165         //
1166         //     precision type inN = ...;
1167         //
1168         op << "\t";
1169         if (precision && !isBool)
1170         {
1171             if (hasReferenceIn)
1172                 op << "highp ";
1173             else
1174                 op << precision << " ";
1175         }
1176 
1177         op << typeName << " ";
1178         if (hasReferenceIn)
1179             op << "highp_";
1180         op << "in" << i << " = ";
1181 
1182         if (isBool)
1183         {
1184             if (inSize == 1)
1185                 op << "(";
1186             else
1187                 op << "greaterThan(";
1188         }
1189         else if (isInt || isUint)
1190             op << typeName << "(";
1191 
1192         op << prefix << "in" << i << "." << swizzle;
1193 
1194         if (isBool)
1195         {
1196             if (inSize == 1)
1197                 op << " > 0.0)";
1198             else
1199                 op << ", vec" << inSize << "(0.0))";
1200         }
1201         else if (isInt || isUint)
1202             op << ")";
1203 
1204         op << ";\n";
1205 
1206         if (hasReferenceIn)
1207         {
1208             op << "\t" << precision << " " << typeName << " in" << i << " = highp_in" << i << ";\n";
1209 
1210             string inputName = "in" + string(1, static_cast<char>('0' + i));
1211             stringReplace(refShaderOp, inputName, "highp_" + inputName);
1212         }
1213     }
1214 
1215     // Result variable.
1216     {
1217         const char *outTypeName = getDataTypeName(m_spec.output);
1218         bool isBoolOut          = de::inRange<int>(m_spec.output, TYPE_BOOL, TYPE_BOOL_VEC4);
1219 
1220         op << "\t";
1221         if (precision && !isBoolOut)
1222             op << precision << " ";
1223         op << outTypeName << " res = " << outTypeName << "(0.0);\n";
1224 
1225         if (hasReference)
1226         {
1227             op << "\thighp " << outTypeName << " ref = " << outTypeName << "(0.0);\n";
1228         }
1229 
1230         op << "\n";
1231     }
1232 
1233     // Expression.
1234     op << "\t" << m_shaderOp << "\n";
1235     if (hasReference)
1236     {
1237         stringReplace(refShaderOp, "res", "ref");
1238         op << "\t" << refShaderOp << "\n";
1239     }
1240     op << "\n";
1241 
1242     // Implementations may use more bits than advertised.  Assume an implementation advertising 16
1243     // bits for mediump, but actually using 24 bits for a particular operation.  We have:
1244     //
1245     //     highp ref = expr;
1246     //     mediump res = expr;
1247     //
1248     // We expect res&0xFFFF to be correct, because that ensures that _at least_ 16 bits were
1249     // provided.  However, we also need to make sure that if there is anything in the upper 16 bits
1250     // of res, that those bits match with ref.  In short, we expect to see the following bits
1251     // (assume the advertised number of bits is N, and the actual calculation is done in M bits):
1252     //
1253     //     ref = a31 ... aM aM-1 ... aN aN-1 ... a0
1254     //     res =   0 ...  0 bM-1 ... bN bN-1 ... b0
1255     //
1256     // The test verifies that bN-1 ... b0 is correct based on the shader output.  We additionally
1257     // want to make sure that:
1258     //
1259     //  - bM-1 ... bN is identical to aM-1 ... aN
1260     //  - bits above bM-1 are zero.
1261     //
1262     // This is done as follows:
1263     //
1264     //     diff = res ^ ref  --> should produce a31 ... aM 0 ... 0
1265     //     diff == 0: accept res
1266     //     diff != 0:
1267     //         lsb = log2((~diff + 1u) & diff)  --> log2(0 .. 0 1 0 ...0)
1268     //                                              == findLSB(diff)
1269     //
1270     //         outOfRangeMask = 0xFFFFFFFF << lsb  --> 1 ... 1 0 ... 0
1271     //
1272     //         (res & outOfRangeMask) == 0: accept res
1273     //
1274     // Note that (diff & ~outOfRangeMask) == 0 necessarily holds, because outOfRangeMask has 1s
1275     // starting from the first bit that differs between res and ref, which means that res and ref
1276     // are identical in those bits.
1277     int outScalarSize = getDataTypeScalarSize(m_spec.output);
1278     string floatType  = "";
1279     if (!isResFloatVec)
1280     {
1281         if (outScalarSize == 1)
1282             floatType = "float";
1283         else
1284             floatType = "vec" + string(1, static_cast<char>('0' + outScalarSize));
1285     }
1286 
1287     if (hasReference)
1288     {
1289         bool isInt                   = de::inRange<int>(m_spec.output, TYPE_INT, TYPE_INT_VEC4);
1290         const char *outTypeName      = getDataTypeName(m_spec.output);
1291         const char *outBasicTypeName = getDataTypeName(isInt ? TYPE_INT : TYPE_UINT);
1292         uint32_t resultMask          = m_spec.resultScale.getValueMask(m_renderCtx.getFunctions(), shaderType);
1293 
1294         op << "\thighp " << outTypeName << " diff = res ^ ref;\n";
1295         op << "\tdiff = (~diff + " << outTypeName << "(1)) & diff;\n";
1296         op << "\thighp " << outTypeName << " lsb = " << outTypeName << "(32);\n";
1297         op << "\thighp " << outTypeName << " outOfRangeMask = " << outTypeName << "(0);\n";
1298         if (outScalarSize == 1)
1299         {
1300             op << "\tif (diff != " << outTypeName << "(0))\n\t{\n";
1301             op << "\t\tlsb = " << outTypeName << "(log2(" << floatType << "(diff)));\n";
1302             op << "\t\toutOfRangeMask = " << outTypeName << "(0xFFFFFFFF) << lsb;\n";
1303             op << "\t}\n";
1304         }
1305         else
1306         {
1307             op << "\tbvec" << outScalarSize << " isDiffZero = equal(diff, " << outTypeName << "(0));\n";
1308             op << "\thighp " << outTypeName << " lsbUnsantized = " << outTypeName << "(log2(vec" << outScalarSize
1309                << "((~diff + " << outTypeName << "(1)) & diff)));\n";
1310             for (int channel = 0; channel < outScalarSize; ++channel)
1311             {
1312                 op << "\tif (!isDiffZero[" << channel << "])\n\t{\n";
1313                 op << "\t\tlsb[" << channel << "] = lsbUnsantized[" << channel << "];\n";
1314                 op << "\t\toutOfRangeMask[" << channel << "] = " << outBasicTypeName << "(0xFFFFFFFF) << lsb["
1315                    << channel << "];\n";
1316                 op << "\t}\n";
1317             }
1318         }
1319         op << "\thighp " << outTypeName << " outOfRangeRes = res & outOfRangeMask;\n";
1320         op << "\tif (outOfRangeRes != " << outTypeName << "(0)) res = " << outTypeName << "(0);\n";
1321 
1322         if (resultMask != 0)
1323             op << "\tres &= " << outTypeName << "(" << resultMask << ");\n";
1324 
1325         op << "\n";
1326     }
1327 
1328     // Convert to color.
1329     op << "\thighp vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n";
1330     op << "\tcolor." << s_outSwizzles[outScalarSize - 1] << " = " << floatType << "(res);\n";
1331 
1332     // Scale & bias.
1333     float resultScale = m_spec.resultScale.getValue(m_renderCtx.getFunctions(), shaderType);
1334     float resultBias  = m_spec.resultBias.getValue(m_renderCtx.getFunctions(), shaderType);
1335     if ((resultScale != 1.0f) || (resultBias != 0.0f))
1336     {
1337         op << "\tcolor = color";
1338         if (resultScale != 1.0f)
1339             op << " * " << twoValuedVec4(de::toString(resultScale), "1.0", s_outSwizzleChannelMasks[outScalarSize - 1]);
1340         if (resultBias != 0.0f)
1341             op << " + "
1342                << twoValuedVec4(de::floatToString(resultBias, 2), "0.0", s_outSwizzleChannelMasks[outScalarSize - 1]);
1343         op << ";\n";
1344     }
1345 
1346     // ..
1347     if (m_isVertexCase)
1348     {
1349         vtx << "    v_color = color;\n";
1350         frag << "    o_color = v_color;\n";
1351     }
1352     else
1353     {
1354         for (int i = 0; i < m_spec.numInputs; i++)
1355             vtx << "    v_in" << i << " = a_in" << i << ";\n";
1356         frag << "    o_color = color;\n";
1357     }
1358 
1359     vtx << "}\n";
1360     frag << "}\n";
1361 
1362     m_vertShaderSource = vtx.str();
1363     m_fragShaderSource = frag.str();
1364 
1365     // Setup the user attributes.
1366     m_userAttribTransforms.resize(m_spec.numInputs);
1367     for (int inputNdx = 0; inputNdx < m_spec.numInputs; inputNdx++)
1368     {
1369         const ShaderValue &v = m_spec.inputs[inputNdx];
1370         DE_ASSERT(v.type != TYPE_LAST);
1371 
1372         float rangeMin = v.rangeMin.getValue(m_renderCtx.getFunctions(), shaderType);
1373         float rangeMax = v.rangeMax.getValue(m_renderCtx.getFunctions(), shaderType);
1374         float scale    = rangeMax - rangeMin;
1375         float minBias  = rangeMin;
1376         float maxBias  = rangeMax;
1377         Mat4 attribMatrix;
1378 
1379         for (int rowNdx = 0; rowNdx < 4; rowNdx++)
1380         {
1381             Vec4 row;
1382 
1383             switch ((rowNdx + inputNdx) % 4)
1384             {
1385             case 0:
1386                 row = Vec4(scale, 0.0f, 0.0f, minBias);
1387                 break;
1388             case 1:
1389                 row = Vec4(0.0f, scale, 0.0f, minBias);
1390                 break;
1391             case 2:
1392                 row = Vec4(-scale, 0.0f, 0.0f, maxBias);
1393                 break;
1394             case 3:
1395                 row = Vec4(0.0f, -scale, 0.0f, maxBias);
1396                 break;
1397             default:
1398                 DE_ASSERT(false);
1399             }
1400 
1401             attribMatrix.setRow(rowNdx, row);
1402         }
1403 
1404         m_userAttribTransforms[inputNdx] = attribMatrix;
1405     }
1406 }
1407 
~ShaderOperatorCase(void)1408 ShaderOperatorCase::~ShaderOperatorCase(void)
1409 {
1410 }
1411 
1412 // ShaderOperatorTests.
1413 
ShaderOperatorTests(Context & context)1414 ShaderOperatorTests::ShaderOperatorTests(Context &context) : TestCaseGroup(context, "operator", "Operator tests.")
1415 {
1416 }
1417 
~ShaderOperatorTests(void)1418 ShaderOperatorTests::~ShaderOperatorTests(void)
1419 {
1420 }
1421 
1422 // Vector math functions.
1423 template <typename T>
nop(T f)1424 inline T nop(T f)
1425 {
1426     return f;
1427 }
1428 
1429 template <typename T, int Size>
nop(const Vector<T,Size> & v)1430 Vector<T, Size> nop(const Vector<T, Size> &v)
1431 {
1432     return v;
1433 }
1434 
1435 #define DECLARE_UNARY_GENTYPE_FUNCS(FUNC_NAME)               \
1436     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)      \
1437     {                                                        \
1438         c.color.x() = FUNC_NAME(c.in[0].swizzle(2)).x();     \
1439     }                                                        \
1440     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)       \
1441     {                                                        \
1442         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1));     \
1443     }                                                        \
1444     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)       \
1445     {                                                        \
1446         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1)); \
1447     }                                                        \
1448     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)       \
1449     {                                                        \
1450         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0));    \
1451     }
1452 
1453 #define DECLARE_BINARY_GENTYPE_FUNCS(FUNC_NAME)                                        \
1454     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)                                \
1455     {                                                                                  \
1456         c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0)).x();           \
1457     }                                                                                  \
1458     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                 \
1459     {                                                                                  \
1460         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0));        \
1461     }                                                                                  \
1462     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                 \
1463     {                                                                                  \
1464         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)); \
1465     }                                                                                  \
1466     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                 \
1467     {                                                                                  \
1468         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); \
1469     }
1470 
1471 #define DECLARE_TERNARY_GENTYPE_FUNCS(FUNC_NAME)                                                                    \
1472     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)                                                             \
1473     {                                                                                                               \
1474         c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0), c.in[2].swizzle(1)).x();                    \
1475     }                                                                                                               \
1476     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                                              \
1477     {                                                                                                               \
1478         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0), c.in[2].swizzle(2, 1));              \
1479     }                                                                                                               \
1480     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                                              \
1481     {                                                                                                               \
1482         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));    \
1483     }                                                                                                               \
1484     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                                              \
1485     {                                                                                                               \
1486         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)); \
1487     }
1488 
1489 #define DECLARE_UNARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME)         \
1490     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)       \
1491     {                                                         \
1492         c.color.x() = FUNC_NAME(c.in[0].swizzle(2));          \
1493     }                                                         \
1494     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)        \
1495     {                                                         \
1496         c.color.x() = FUNC_NAME(c.in[0].swizzle(3, 1));       \
1497     }                                                         \
1498     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)        \
1499     {                                                         \
1500         c.color.x() = FUNC_NAME(c.in[0].swizzle(2, 0, 1));    \
1501     }                                                         \
1502     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)        \
1503     {                                                         \
1504         c.color.x() = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0)); \
1505     }
1506 
1507 #define DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME)                                     \
1508     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)                                    \
1509     {                                                                                      \
1510         c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0));                   \
1511     }                                                                                      \
1512     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                     \
1513     {                                                                                      \
1514         c.color.x() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0));             \
1515     }                                                                                      \
1516     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                     \
1517     {                                                                                      \
1518         c.color.x() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0));       \
1519     }                                                                                      \
1520     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                     \
1521     {                                                                                      \
1522         c.color.x() = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); \
1523     }
1524 
1525 #define DECLARE_BINARY_BOOL_FUNCS(FUNC_NAME)                                    \
1526     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                          \
1527     {                                                                           \
1528         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f); \
1529     }
1530 
1531 #define DECLARE_UNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME)                                             \
1532     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                                          \
1533     {                                                                                           \
1534         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f);                                     \
1535     }                                                                                           \
1536     void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c)                                         \
1537     {                                                                                           \
1538         c.color.yz() = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat();     \
1539     }                                                                                           \
1540     void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c)                                         \
1541     {                                                                                           \
1542         c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat(); \
1543     }                                                                                           \
1544     void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c)                                         \
1545     {                                                                                           \
1546         c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f))).asFloat();    \
1547     }
1548 
1549 #define DECLARE_TERNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME)                                                                 \
1550     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                                                                \
1551     {                                                                                                                 \
1552         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f, c.in[2].y() > 0.0f);                   \
1553     }                                                                                                                 \
1554     void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c)                                                               \
1555     {                                                                                                                 \
1556         c.color.yz() =                                                                                                \
1557             FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)), greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f)), \
1558                       greaterThan(c.in[2].swizzle(2, 1), Vec2(0.0f)))                                                 \
1559                 .asFloat();                                                                                           \
1560     }                                                                                                                 \
1561     void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c)                                                               \
1562     {                                                                                                                 \
1563         c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)),                                  \
1564                                   greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f)),                                  \
1565                                   greaterThan(c.in[2].swizzle(3, 1, 2), Vec3(0.0f)))                                  \
1566                             .asFloat();                                                                               \
1567     }                                                                                                                 \
1568     void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c)                                                               \
1569     {                                                                                                                 \
1570         c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)),                                     \
1571                             greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f)),                                     \
1572                             greaterThan(c.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f)))                                     \
1573                       .asFloat();                                                                                     \
1574     }
1575 
1576 #define DECLARE_UNARY_INT_GENTYPE_FUNCS(FUNC_NAME)                             \
1577     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                          \
1578     {                                                                          \
1579         c.color.x() = (float)FUNC_NAME((int)c.in[0].z());                      \
1580     }                                                                          \
1581     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                        \
1582     {                                                                          \
1583         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt()).asFloat();     \
1584     }                                                                          \
1585     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                        \
1586     {                                                                          \
1587         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt()).asFloat(); \
1588     }                                                                          \
1589     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                        \
1590     {                                                                          \
1591         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt()).asFloat();    \
1592     }
1593 
1594 #define DECLARE_BINARY_INT_GENTYPE_FUNCS(FUNC_NAME)                                                              \
1595     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                                                            \
1596     {                                                                                                            \
1597         c.color.x() = (float)FUNC_NAME((int)c.in[0].z(), (int)c.in[1].x());                                      \
1598     }                                                                                                            \
1599     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                          \
1600     {                                                                                                            \
1601         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), c.in[1].swizzle(1, 0).asInt()).asFloat();        \
1602     }                                                                                                            \
1603     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                          \
1604     {                                                                                                            \
1605         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
1606     }                                                                                                            \
1607     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                          \
1608     {                                                                                                            \
1609         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); \
1610     }
1611 
1612 #define DECLARE_UNARY_UINT_GENTYPE_FUNCS(FUNC_NAME)                             \
1613     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                          \
1614     {                                                                           \
1615         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z());                  \
1616     }                                                                           \
1617     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                         \
1618     {                                                                           \
1619         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint()).asFloat();     \
1620     }                                                                           \
1621     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                         \
1622     {                                                                           \
1623         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint()).asFloat(); \
1624     }                                                                           \
1625     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                         \
1626     {                                                                           \
1627         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint()).asFloat();    \
1628     }
1629 
1630 #define DECLARE_BINARY_UINT_GENTYPE_FUNCS(FUNC_NAME)                                                               \
1631     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                                             \
1632     {                                                                                                              \
1633         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x());                              \
1634     }                                                                                                              \
1635     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                            \
1636     {                                                                                                              \
1637         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()).asFloat();        \
1638     }                                                                                                              \
1639     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                            \
1640     {                                                                                                              \
1641         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
1642     }                                                                                                              \
1643     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                            \
1644     {                                                                                                              \
1645         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat(); \
1646     }
1647 
1648 #define DECLARE_TERNARY_INT_GENTYPE_FUNCS(FUNC_NAME)                                                               \
1649     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                                                              \
1650     {                                                                                                              \
1651         c.color.x() = (float)FUNC_NAME((int)c.in[0].z(), (int)c.in[1].x(), (int)c.in[2].y());                      \
1652     }                                                                                                              \
1653     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                            \
1654     {                                                                                                              \
1655         c.color.yz() =                                                                                             \
1656             FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), c.in[1].swizzle(1, 0).asInt(), c.in[2].swizzle(2, 1).asInt()) \
1657                 .asFloat();                                                                                        \
1658     }                                                                                                              \
1659     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                            \
1660     {                                                                                                              \
1661         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), c.in[1].swizzle(1, 2, 0).asInt(),              \
1662                                   c.in[2].swizzle(3, 1, 2).asInt())                                                \
1663                             .asFloat();                                                                            \
1664     }                                                                                                              \
1665     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                            \
1666     {                                                                                                              \
1667         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), c.in[1].swizzle(3, 2, 1, 0).asInt(),              \
1668                             c.in[2].swizzle(0, 3, 2, 1).asInt())                                                   \
1669                       .asFloat();                                                                                  \
1670     }
1671 
1672 #define DECLARE_TERNARY_UINT_GENTYPE_FUNCS(FUNC_NAME)                                                                 \
1673     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                                                \
1674     {                                                                                                                 \
1675         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y());          \
1676     }                                                                                                                 \
1677     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                               \
1678     {                                                                                                                 \
1679         c.color.yz() =                                                                                                \
1680             FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint(), c.in[2].swizzle(2, 1).asUint()) \
1681                 .asFloat();                                                                                           \
1682     }                                                                                                                 \
1683     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                               \
1684     {                                                                                                                 \
1685         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint(),               \
1686                                   c.in[2].swizzle(3, 1, 2).asUint())                                                  \
1687                             .asFloat();                                                                               \
1688     }                                                                                                                 \
1689     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                               \
1690     {                                                                                                                 \
1691         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint(),               \
1692                             c.in[2].swizzle(0, 3, 2, 1).asUint())                                                     \
1693                       .asFloat();                                                                                     \
1694     }
1695 
1696 #define DECLARE_VEC_FLOAT_FUNCS(FUNC_NAME)                                \
1697     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                    \
1698     {                                                                     \
1699         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].x());     \
1700     }                                                                     \
1701     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                    \
1702     {                                                                     \
1703         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].x()); \
1704     }                                                                     \
1705     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                    \
1706     {                                                                     \
1707         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].x());    \
1708     }
1709 
1710 #define DECLARE_VEC_FLOAT_FLOAT_FUNCS(FUNC_NAME)                                       \
1711     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                 \
1712     {                                                                                  \
1713         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].x(), c.in[2].y());     \
1714     }                                                                                  \
1715     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                 \
1716     {                                                                                  \
1717         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].x(), c.in[2].y()); \
1718     }                                                                                  \
1719     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                 \
1720     {                                                                                  \
1721         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].x(), c.in[2].y());    \
1722     }
1723 
1724 #define DECLARE_VEC_VEC_FLOAT_FUNCS(FUNC_NAME)                                                      \
1725     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                              \
1726     {                                                                                               \
1727         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0), c.in[2].y());        \
1728     }                                                                                               \
1729     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                              \
1730     {                                                                                               \
1731         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0), c.in[2].y()); \
1732     }                                                                                               \
1733     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                              \
1734     {                                                                                               \
1735         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0), c.in[2].y()); \
1736     }
1737 
1738 #define DECLARE_FLOAT_FLOAT_VEC_FUNCS(FUNC_NAME)                                       \
1739     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                 \
1740     {                                                                                  \
1741         c.color.yz() = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(2, 1));     \
1742     }                                                                                  \
1743     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                 \
1744     {                                                                                  \
1745         c.color.xyz() = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(3, 1, 2)); \
1746     }                                                                                  \
1747     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                 \
1748     {                                                                                  \
1749         c.color = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(0, 3, 2, 1));    \
1750     }
1751 
1752 #define DECLARE_FLOAT_VEC_FUNCS(FUNC_NAME)                                \
1753     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                    \
1754     {                                                                     \
1755         c.color.yz() = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(1, 0));     \
1756     }                                                                     \
1757     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                    \
1758     {                                                                     \
1759         c.color.xyz() = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(1, 2, 0)); \
1760     }                                                                     \
1761     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                    \
1762     {                                                                     \
1763         c.color = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0));    \
1764     }
1765 
1766 #define DECLARE_IVEC_INT_FUNCS(FUNC_NAME)                                                        \
1767     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                          \
1768     {                                                                                            \
1769         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), (int)c.in[1].x()).asFloat();     \
1770     }                                                                                            \
1771     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                          \
1772     {                                                                                            \
1773         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), (int)c.in[1].x()).asFloat(); \
1774     }                                                                                            \
1775     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                          \
1776     {                                                                                            \
1777         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), (int)c.in[1].x()).asFloat();    \
1778     }
1779 
1780 #define DECLARE_IVEC_INT_INT_FUNCS(FUNC_NAME)                                                                      \
1781     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                            \
1782     {                                                                                                              \
1783         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), (int)c.in[1].x(), (int)c.in[2].y()).asFloat();     \
1784     }                                                                                                              \
1785     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                            \
1786     {                                                                                                              \
1787         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), (int)c.in[1].x(), (int)c.in[2].y()).asFloat(); \
1788     }                                                                                                              \
1789     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                            \
1790     {                                                                                                              \
1791         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), (int)c.in[1].x(), (int)c.in[2].y()).asFloat();    \
1792     }
1793 
1794 #define DECLARE_INT_IVEC_FUNCS(FUNC_NAME)                                                        \
1795     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                          \
1796     {                                                                                            \
1797         c.color.yz() = FUNC_NAME((int)c.in[0].z(), c.in[1].swizzle(1, 0).asInt()).asFloat();     \
1798     }                                                                                            \
1799     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                          \
1800     {                                                                                            \
1801         c.color.xyz() = FUNC_NAME((int)c.in[0].z(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
1802     }                                                                                            \
1803     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                          \
1804     {                                                                                            \
1805         c.color = FUNC_NAME((int)c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat();    \
1806     }
1807 
1808 #define DECLARE_UVEC_UINT_FUNCS(FUNC_NAME)                                                             \
1809     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                \
1810     {                                                                                                  \
1811         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), (uint32_t)c.in[1].x()).asFloat();     \
1812     }                                                                                                  \
1813     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                \
1814     {                                                                                                  \
1815         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), (uint32_t)c.in[1].x()).asFloat(); \
1816     }                                                                                                  \
1817     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                \
1818     {                                                                                                  \
1819         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), (uint32_t)c.in[1].x()).asFloat();    \
1820     }
1821 
1822 #define DECLARE_UVEC_UINT_UINT_FUNCS(FUNC_NAME)                                                                      \
1823     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                              \
1824     {                                                                                                                \
1825         c.color.yz() =                                                                                               \
1826             FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()).asFloat();       \
1827     }                                                                                                                \
1828     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                              \
1829     {                                                                                                                \
1830         c.color.xyz() =                                                                                              \
1831             FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()).asFloat();    \
1832     }                                                                                                                \
1833     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                              \
1834     {                                                                                                                \
1835         c.color =                                                                                                    \
1836             FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()).asFloat(); \
1837     }
1838 
1839 #define DECLARE_UINT_UVEC_FUNCS(FUNC_NAME)                                                             \
1840     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                \
1841     {                                                                                                  \
1842         c.color.yz() = FUNC_NAME((uint32_t)c.in[0].z(), c.in[1].swizzle(1, 0).asUint()).asFloat();     \
1843     }                                                                                                  \
1844     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                \
1845     {                                                                                                  \
1846         c.color.xyz() = FUNC_NAME((uint32_t)c.in[0].z(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
1847     }                                                                                                  \
1848     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                \
1849     {                                                                                                  \
1850         c.color = FUNC_NAME((uint32_t)c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat();    \
1851     }
1852 
1853 #define DECLARE_BINARY_INT_VEC_FUNCS(FUNC_NAME)                                                                  \
1854     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                          \
1855     {                                                                                                            \
1856         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), c.in[1].swizzle(1, 0).asInt()).asFloat();        \
1857     }                                                                                                            \
1858     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                          \
1859     {                                                                                                            \
1860         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
1861     }                                                                                                            \
1862     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                          \
1863     {                                                                                                            \
1864         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); \
1865     }
1866 
1867 #define DECLARE_BINARY_UINT_VEC_FUNCS(FUNC_NAME)                                                                   \
1868     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                            \
1869     {                                                                                                              \
1870         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()).asFloat();        \
1871     }                                                                                                              \
1872     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                            \
1873     {                                                                                                              \
1874         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
1875     }                                                                                                              \
1876     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                            \
1877     {                                                                                                              \
1878         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat(); \
1879     }
1880 
1881 #define DECLARE_UINT_INT_GENTYPE_FUNCS(FUNC_NAME)                                                                 \
1882     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                                            \
1883     {                                                                                                             \
1884         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (int)c.in[1].x());                                  \
1885     }                                                                                                             \
1886     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                           \
1887     {                                                                                                             \
1888         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asInt()).asFloat();        \
1889     }                                                                                                             \
1890     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                           \
1891     {                                                                                                             \
1892         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
1893     }                                                                                                             \
1894     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                           \
1895     {                                                                                                             \
1896         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); \
1897     }
1898 
1899 #define DECLARE_UVEC_INT_FUNCS(FUNC_NAME)                                                         \
1900     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                           \
1901     {                                                                                             \
1902         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), (int)c.in[1].x()).asFloat();     \
1903     }                                                                                             \
1904     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                           \
1905     {                                                                                             \
1906         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), (int)c.in[1].x()).asFloat(); \
1907     }                                                                                             \
1908     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                           \
1909     {                                                                                             \
1910         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), (int)c.in[1].x()).asFloat();    \
1911     }
1912 
1913 // Operators.
1914 
1915 DECLARE_UNARY_GENTYPE_FUNCS(nop)
DECLARE_UNARY_GENTYPE_FUNCS(negate)1916 DECLARE_UNARY_GENTYPE_FUNCS(negate)
1917 DECLARE_UNARY_GENTYPE_FUNCS(addOne)
1918 DECLARE_UNARY_GENTYPE_FUNCS(subOne)
1919 DECLARE_BINARY_GENTYPE_FUNCS(add)
1920 DECLARE_BINARY_GENTYPE_FUNCS(sub)
1921 DECLARE_BINARY_GENTYPE_FUNCS(mul)
1922 DECLARE_BINARY_GENTYPE_FUNCS(div)
1923 
1924 void eval_selection_float(ShaderEvalContext &c)
1925 {
1926     c.color.x() = selection(c.in[0].z() > 0.0f, c.in[1].x(), c.in[2].y());
1927 }
eval_selection_vec2(ShaderEvalContext & c)1928 void eval_selection_vec2(ShaderEvalContext &c)
1929 {
1930     c.color.yz() = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 0), c.in[2].swizzle(2, 1));
1931 }
eval_selection_vec3(ShaderEvalContext & c)1932 void eval_selection_vec3(ShaderEvalContext &c)
1933 {
1934     c.color.xyz() = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 2, 0), c.in[2].swizzle(3, 1, 2));
1935 }
eval_selection_vec4(ShaderEvalContext & c)1936 void eval_selection_vec4(ShaderEvalContext &c)
1937 {
1938     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));
1939 }
1940 
1941 DECLARE_UNARY_INT_GENTYPE_FUNCS(nop)
DECLARE_UNARY_INT_GENTYPE_FUNCS(negate)1942 DECLARE_UNARY_INT_GENTYPE_FUNCS(negate)
1943 DECLARE_UNARY_INT_GENTYPE_FUNCS(addOne)
1944 DECLARE_UNARY_INT_GENTYPE_FUNCS(subOne)
1945 DECLARE_UNARY_INT_GENTYPE_FUNCS(bitwiseNot)
1946 DECLARE_BINARY_INT_GENTYPE_FUNCS(add)
1947 DECLARE_BINARY_INT_GENTYPE_FUNCS(sub)
1948 DECLARE_BINARY_INT_GENTYPE_FUNCS(mul)
1949 DECLARE_BINARY_INT_GENTYPE_FUNCS(div)
1950 DECLARE_BINARY_INT_GENTYPE_FUNCS(mod)
1951 DECLARE_BINARY_INT_GENTYPE_FUNCS(bitwiseAnd)
1952 DECLARE_BINARY_INT_GENTYPE_FUNCS(bitwiseOr)
1953 DECLARE_BINARY_INT_GENTYPE_FUNCS(bitwiseXor)
1954 
1955 void eval_leftShift_int(ShaderEvalContext &c)
1956 {
1957     c.color.x() = (float)leftShift((int)c.in[0].z(), (int)c.in[1].x());
1958 }
DECLARE_BINARY_INT_VEC_FUNCS(leftShift)1959 DECLARE_BINARY_INT_VEC_FUNCS(leftShift)
1960 void eval_rightShift_int(ShaderEvalContext &c)
1961 {
1962     c.color.x() = (float)rightShift((int)c.in[0].z(), (int)c.in[1].x());
1963 }
1964 DECLARE_BINARY_INT_VEC_FUNCS(rightShift)
DECLARE_IVEC_INT_FUNCS(leftShiftVecScalar)1965 DECLARE_IVEC_INT_FUNCS(leftShiftVecScalar)
1966 DECLARE_IVEC_INT_FUNCS(rightShiftVecScalar)
1967 
1968 void eval_selection_int(ShaderEvalContext &c)
1969 {
1970     c.color.x() = (float)selection(c.in[0].z() > 0.0f, (int)c.in[1].x(), (int)c.in[2].y());
1971 }
eval_selection_ivec2(ShaderEvalContext & c)1972 void eval_selection_ivec2(ShaderEvalContext &c)
1973 {
1974     c.color.yz() =
1975         selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 0).asInt(), c.in[2].swizzle(2, 1).asInt()).asFloat();
1976 }
eval_selection_ivec3(ShaderEvalContext & c)1977 void eval_selection_ivec3(ShaderEvalContext &c)
1978 {
1979     c.color.xyz() =
1980         selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 2, 0).asInt(), c.in[2].swizzle(3, 1, 2).asInt()).asFloat();
1981 }
eval_selection_ivec4(ShaderEvalContext & c)1982 void eval_selection_ivec4(ShaderEvalContext &c)
1983 {
1984     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())
1985                   .asFloat();
1986 }
1987 
1988 DECLARE_UNARY_UINT_GENTYPE_FUNCS(nop)
DECLARE_UNARY_UINT_GENTYPE_FUNCS(negate)1989 DECLARE_UNARY_UINT_GENTYPE_FUNCS(negate)
1990 DECLARE_UNARY_UINT_GENTYPE_FUNCS(bitwiseNot)
1991 DECLARE_UNARY_UINT_GENTYPE_FUNCS(addOne)
1992 DECLARE_UNARY_UINT_GENTYPE_FUNCS(subOne)
1993 DECLARE_BINARY_UINT_GENTYPE_FUNCS(add)
1994 DECLARE_BINARY_UINT_GENTYPE_FUNCS(sub)
1995 DECLARE_BINARY_UINT_GENTYPE_FUNCS(mul)
1996 DECLARE_BINARY_UINT_GENTYPE_FUNCS(div)
1997 DECLARE_BINARY_UINT_GENTYPE_FUNCS(mod)
1998 DECLARE_BINARY_UINT_GENTYPE_FUNCS(bitwiseAnd)
1999 DECLARE_BINARY_UINT_GENTYPE_FUNCS(bitwiseOr)
2000 DECLARE_BINARY_UINT_GENTYPE_FUNCS(bitwiseXor)
2001 
2002 DECLARE_UINT_INT_GENTYPE_FUNCS(leftShift)
2003 DECLARE_UINT_INT_GENTYPE_FUNCS(rightShift)
2004 DECLARE_UVEC_INT_FUNCS(leftShiftVecScalar)
2005 DECLARE_UVEC_INT_FUNCS(rightShiftVecScalar)
2006 
2007 void eval_selection_uint(ShaderEvalContext &c)
2008 {
2009     c.color.x() = (float)selection(c.in[0].z() > 0.0f, (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y());
2010 }
eval_selection_uvec2(ShaderEvalContext & c)2011 void eval_selection_uvec2(ShaderEvalContext &c)
2012 {
2013     c.color.yz() =
2014         selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 0).asUint(), c.in[2].swizzle(2, 1).asUint()).asFloat();
2015 }
eval_selection_uvec3(ShaderEvalContext & c)2016 void eval_selection_uvec3(ShaderEvalContext &c)
2017 {
2018     c.color.xyz() =
2019         selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 2, 0).asUint(), c.in[2].swizzle(3, 1, 2).asUint()).asFloat();
2020 }
eval_selection_uvec4(ShaderEvalContext & c)2021 void eval_selection_uvec4(ShaderEvalContext &c)
2022 {
2023     c.color = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(3, 2, 1, 0).asUint(), c.in[2].swizzle(0, 3, 2, 1).asUint())
2024                   .asFloat();
2025 }
2026 
2027 DECLARE_UNARY_BOOL_GENTYPE_FUNCS(boolNot)
DECLARE_BINARY_BOOL_FUNCS(logicalAnd)2028 DECLARE_BINARY_BOOL_FUNCS(logicalAnd)
2029 DECLARE_BINARY_BOOL_FUNCS(logicalOr)
2030 DECLARE_BINARY_BOOL_FUNCS(logicalXor)
2031 
2032 void eval_selection_bool(ShaderEvalContext &c)
2033 {
2034     c.color.x() = (float)selection(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f, c.in[2].y() > 0.0f);
2035 }
eval_selection_bvec2(ShaderEvalContext & c)2036 void eval_selection_bvec2(ShaderEvalContext &c)
2037 {
2038     c.color.yz() = selection(c.in[0].z() > 0.0f, greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f, 0.0f)),
2039                              greaterThan(c.in[2].swizzle(2, 1), Vec2(0.0f, 0.0f)))
2040                        .asFloat();
2041 }
eval_selection_bvec3(ShaderEvalContext & c)2042 void eval_selection_bvec3(ShaderEvalContext &c)
2043 {
2044     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)),
2045                               greaterThan(c.in[2].swizzle(3, 1, 2), Vec3(0.0f, 0.0f, 0.0f)))
2046                         .asFloat();
2047 }
eval_selection_bvec4(ShaderEvalContext & c)2048 void eval_selection_bvec4(ShaderEvalContext &c)
2049 {
2050     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)),
2051                         greaterThan(c.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f)))
2052                   .asFloat();
2053 }
2054 
2055 DECLARE_VEC_FLOAT_FUNCS(addVecScalar)
DECLARE_VEC_FLOAT_FUNCS(subVecScalar)2056 DECLARE_VEC_FLOAT_FUNCS(subVecScalar)
2057 DECLARE_VEC_FLOAT_FUNCS(mulVecScalar)
2058 DECLARE_VEC_FLOAT_FUNCS(divVecScalar)
2059 
2060 DECLARE_FLOAT_VEC_FUNCS(addScalarVec)
2061 DECLARE_FLOAT_VEC_FUNCS(subScalarVec)
2062 DECLARE_FLOAT_VEC_FUNCS(mulScalarVec)
2063 DECLARE_FLOAT_VEC_FUNCS(divScalarVec)
2064 
2065 DECLARE_IVEC_INT_FUNCS(addVecScalar)
2066 DECLARE_IVEC_INT_FUNCS(subVecScalar)
2067 DECLARE_IVEC_INT_FUNCS(mulVecScalar)
2068 DECLARE_IVEC_INT_FUNCS(divVecScalar)
2069 DECLARE_IVEC_INT_FUNCS(modVecScalar)
2070 DECLARE_IVEC_INT_FUNCS(bitwiseAndVecScalar)
2071 DECLARE_IVEC_INT_FUNCS(bitwiseOrVecScalar)
2072 DECLARE_IVEC_INT_FUNCS(bitwiseXorVecScalar)
2073 
2074 DECLARE_INT_IVEC_FUNCS(addScalarVec)
2075 DECLARE_INT_IVEC_FUNCS(subScalarVec)
2076 DECLARE_INT_IVEC_FUNCS(mulScalarVec)
2077 DECLARE_INT_IVEC_FUNCS(divScalarVec)
2078 DECLARE_INT_IVEC_FUNCS(modScalarVec)
2079 DECLARE_INT_IVEC_FUNCS(bitwiseAndScalarVec)
2080 DECLARE_INT_IVEC_FUNCS(bitwiseOrScalarVec)
2081 DECLARE_INT_IVEC_FUNCS(bitwiseXorScalarVec)
2082 
2083 DECLARE_UVEC_UINT_FUNCS(addVecScalar)
2084 DECLARE_UVEC_UINT_FUNCS(subVecScalar)
2085 DECLARE_UVEC_UINT_FUNCS(mulVecScalar)
2086 DECLARE_UVEC_UINT_FUNCS(divVecScalar)
2087 DECLARE_UVEC_UINT_FUNCS(modVecScalar)
2088 DECLARE_UVEC_UINT_FUNCS(bitwiseAndVecScalar)
2089 DECLARE_UVEC_UINT_FUNCS(bitwiseOrVecScalar)
2090 DECLARE_UVEC_UINT_FUNCS(bitwiseXorVecScalar)
2091 
2092 DECLARE_UINT_UVEC_FUNCS(addScalarVec)
2093 DECLARE_UINT_UVEC_FUNCS(subScalarVec)
2094 DECLARE_UINT_UVEC_FUNCS(mulScalarVec)
2095 DECLARE_UINT_UVEC_FUNCS(divScalarVec)
2096 DECLARE_UINT_UVEC_FUNCS(modScalarVec)
2097 DECLARE_UINT_UVEC_FUNCS(bitwiseAndScalarVec)
2098 DECLARE_UINT_UVEC_FUNCS(bitwiseOrScalarVec)
2099 DECLARE_UINT_UVEC_FUNCS(bitwiseXorScalarVec)
2100 
2101 // Built-in functions.
2102 
2103 DECLARE_UNARY_GENTYPE_FUNCS(radians)
2104 DECLARE_UNARY_GENTYPE_FUNCS(degrees)
2105 DECLARE_UNARY_GENTYPE_FUNCS(sin)
2106 DECLARE_UNARY_GENTYPE_FUNCS(cos)
2107 DECLARE_UNARY_GENTYPE_FUNCS(tan)
2108 DECLARE_UNARY_GENTYPE_FUNCS(asin)
2109 DECLARE_UNARY_GENTYPE_FUNCS(acos)
2110 DECLARE_UNARY_GENTYPE_FUNCS(atan)
2111 DECLARE_BINARY_GENTYPE_FUNCS(atan2)
2112 DECLARE_UNARY_GENTYPE_FUNCS(sinh)
2113 DECLARE_UNARY_GENTYPE_FUNCS(cosh)
2114 DECLARE_UNARY_GENTYPE_FUNCS(tanh)
2115 DECLARE_UNARY_GENTYPE_FUNCS(asinh)
2116 DECLARE_UNARY_GENTYPE_FUNCS(acosh)
2117 DECLARE_UNARY_GENTYPE_FUNCS(atanh)
2118 
2119 DECLARE_BINARY_GENTYPE_FUNCS(pow)
2120 DECLARE_UNARY_GENTYPE_FUNCS(exp)
2121 DECLARE_UNARY_GENTYPE_FUNCS(log)
2122 DECLARE_UNARY_GENTYPE_FUNCS(exp2)
2123 DECLARE_UNARY_GENTYPE_FUNCS(log2)
2124 DECLARE_UNARY_GENTYPE_FUNCS(sqrt)
2125 DECLARE_UNARY_GENTYPE_FUNCS(inverseSqrt)
2126 
2127 DECLARE_UNARY_GENTYPE_FUNCS(abs)
2128 DECLARE_UNARY_GENTYPE_FUNCS(sign)
2129 DECLARE_UNARY_GENTYPE_FUNCS(floor)
2130 DECLARE_UNARY_GENTYPE_FUNCS(trunc)
2131 DECLARE_UNARY_GENTYPE_FUNCS(roundToEven)
2132 DECLARE_UNARY_GENTYPE_FUNCS(ceil)
2133 DECLARE_UNARY_GENTYPE_FUNCS(fract)
2134 DECLARE_BINARY_GENTYPE_FUNCS(mod)
2135 DECLARE_VEC_FLOAT_FUNCS(modVecScalar)
2136 DECLARE_BINARY_GENTYPE_FUNCS(min)
2137 DECLARE_VEC_FLOAT_FUNCS(minVecScalar)
2138 DECLARE_BINARY_INT_GENTYPE_FUNCS(min)
2139 DECLARE_IVEC_INT_FUNCS(minVecScalar)
2140 DECLARE_BINARY_UINT_GENTYPE_FUNCS(min)
2141 DECLARE_UVEC_UINT_FUNCS(minVecScalar)
2142 DECLARE_BINARY_GENTYPE_FUNCS(max)
2143 DECLARE_VEC_FLOAT_FUNCS(maxVecScalar)
2144 DECLARE_BINARY_INT_GENTYPE_FUNCS(max)
2145 DECLARE_IVEC_INT_FUNCS(maxVecScalar)
2146 DECLARE_BINARY_UINT_GENTYPE_FUNCS(max)
2147 DECLARE_UVEC_UINT_FUNCS(maxVecScalar)
2148 DECLARE_TERNARY_GENTYPE_FUNCS(clamp)
2149 DECLARE_VEC_FLOAT_FLOAT_FUNCS(clampVecScalarScalar)
2150 DECLARE_TERNARY_INT_GENTYPE_FUNCS(clamp)
2151 DECLARE_IVEC_INT_INT_FUNCS(clampVecScalarScalar)
2152 DECLARE_TERNARY_UINT_GENTYPE_FUNCS(clamp)
2153 DECLARE_UVEC_UINT_UINT_FUNCS(clampVecScalarScalar)
2154 DECLARE_TERNARY_GENTYPE_FUNCS(mix)
2155 DECLARE_VEC_VEC_FLOAT_FUNCS(mixVecVecScalar)
2156 DECLARE_BINARY_GENTYPE_FUNCS(step)
2157 DECLARE_FLOAT_VEC_FUNCS(stepScalarVec)
2158 DECLARE_TERNARY_GENTYPE_FUNCS(smoothStep)
2159 DECLARE_FLOAT_FLOAT_VEC_FUNCS(smoothStepScalarScalarVec)
2160 
2161 DECLARE_UNARY_SCALAR_GENTYPE_FUNCS(length)
2162 DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(distance)
2163 DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(dot)
2164 void eval_cross_vec3(ShaderEvalContext &c)
2165 {
2166     c.color.xyz() = cross(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0));
2167 }
2168 
2169 DECLARE_UNARY_GENTYPE_FUNCS(normalize)
DECLARE_TERNARY_GENTYPE_FUNCS(faceForward)2170 DECLARE_TERNARY_GENTYPE_FUNCS(faceForward)
2171 DECLARE_BINARY_GENTYPE_FUNCS(reflect)
2172 
2173 void eval_refract_float(ShaderEvalContext &c)
2174 {
2175     c.color.x() = refract(c.in[0].z(), c.in[1].x(), c.in[2].y());
2176 }
eval_refract_vec2(ShaderEvalContext & c)2177 void eval_refract_vec2(ShaderEvalContext &c)
2178 {
2179     c.color.yz() = refract(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0), c.in[2].y());
2180 }
eval_refract_vec3(ShaderEvalContext & c)2181 void eval_refract_vec3(ShaderEvalContext &c)
2182 {
2183     c.color.xyz() = refract(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0), c.in[2].y());
2184 }
eval_refract_vec4(ShaderEvalContext & c)2185 void eval_refract_vec4(ShaderEvalContext &c)
2186 {
2187     c.color = refract(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0), c.in[2].y());
2188 }
2189 
2190 // Compare functions.
2191 
2192 #define DECLARE_FLOAT_COMPARE_FUNCS(FUNC_NAME)                                                    \
2193     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)                                           \
2194     {                                                                                             \
2195         c.color.x() = (float)FUNC_NAME(c.in[0].z(), c.in[1].x());                                 \
2196     }                                                                                             \
2197     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                            \
2198     {                                                                                             \
2199         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0));             \
2200     }                                                                                             \
2201     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                            \
2202     {                                                                                             \
2203         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0));       \
2204     }                                                                                             \
2205     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                            \
2206     {                                                                                             \
2207         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); \
2208     }
2209 
2210 #define DECLARE_FLOAT_CWISE_COMPARE_FUNCS(FUNC_NAME)                                             \
2211     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)                                          \
2212     {                                                                                            \
2213         c.color.x() = (float)FUNC_NAME(c.in[0].z(), c.in[1].x());                                \
2214     }                                                                                            \
2215     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                           \
2216     {                                                                                            \
2217         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0)).asFloat();        \
2218     }                                                                                            \
2219     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                           \
2220     {                                                                                            \
2221         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)).asFloat(); \
2222     }                                                                                            \
2223     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                           \
2224     {                                                                                            \
2225         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)).asFloat(); \
2226     }
2227 
2228 #define DECLARE_INT_COMPARE_FUNCS(FUNC_NAME)                                                                      \
2229     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                                                             \
2230     {                                                                                                             \
2231         c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x()));                           \
2232     }                                                                                                             \
2233     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                           \
2234     {                                                                                                             \
2235         c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].swizzle(3, 1)), chopToInt(c.in[1].swizzle(1, 0)));       \
2236     }                                                                                                             \
2237     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                           \
2238     {                                                                                                             \
2239         c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].swizzle(2, 0, 1)), chopToInt(c.in[1].swizzle(1, 2, 0))); \
2240     }                                                                                                             \
2241     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                           \
2242     {                                                                                                             \
2243         c.color.x() =                                                                                             \
2244             (float)FUNC_NAME(chopToInt(c.in[0].swizzle(1, 2, 3, 0)), chopToInt(c.in[1].swizzle(3, 2, 1, 0)));     \
2245     }
2246 
2247 #define DECLARE_INT_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                                     \
2248     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                                                                  \
2249     {                                                                                                                  \
2250         c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x()));                                \
2251     }                                                                                                                  \
2252     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                                \
2253     {                                                                                                                  \
2254         c.color.yz() = FUNC_NAME(chopToInt(c.in[0].swizzle(3, 1)), chopToInt(c.in[1].swizzle(1, 0))).asFloat();        \
2255     }                                                                                                                  \
2256     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                                \
2257     {                                                                                                                  \
2258         c.color.xyz() = FUNC_NAME(chopToInt(c.in[0].swizzle(2, 0, 1)), chopToInt(c.in[1].swizzle(1, 2, 0))).asFloat(); \
2259     }                                                                                                                  \
2260     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                                \
2261     {                                                                                                                  \
2262         c.color = FUNC_NAME(chopToInt(c.in[0].swizzle(1, 2, 3, 0)), chopToInt(c.in[1].swizzle(3, 2, 1, 0))).asFloat(); \
2263     }
2264 
2265 #define DECLARE_UINT_COMPARE_FUNCS(FUNC_NAME)                                                                       \
2266     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                                              \
2267     {                                                                                                               \
2268         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x());                               \
2269     }                                                                                                               \
2270     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                             \
2271     {                                                                                                               \
2272         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint());             \
2273     }                                                                                                               \
2274     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                             \
2275     {                                                                                                               \
2276         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint());       \
2277     }                                                                                                               \
2278     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                             \
2279     {                                                                                                               \
2280         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()); \
2281     }
2282 
2283 #define DECLARE_UINT_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                                \
2284     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                                             \
2285     {                                                                                                              \
2286         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x());                              \
2287     }                                                                                                              \
2288     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                            \
2289     {                                                                                                              \
2290         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()).asFloat();        \
2291     }                                                                                                              \
2292     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                            \
2293     {                                                                                                              \
2294         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
2295     }                                                                                                              \
2296     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                            \
2297     {                                                                                                              \
2298         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat(); \
2299     }
2300 
2301 #define DECLARE_BOOL_COMPARE_FUNCS(FUNC_NAME)                                                 \
2302     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                                        \
2303     {                                                                                         \
2304         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f);               \
2305     }                                                                                         \
2306     void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c)                                       \
2307     {                                                                                         \
2308         c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)),        \
2309                                        greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f)));       \
2310     }                                                                                         \
2311     void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c)                                       \
2312     {                                                                                         \
2313         c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)),     \
2314                                        greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f)));    \
2315     }                                                                                         \
2316     void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c)                                       \
2317     {                                                                                         \
2318         c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)),  \
2319                                        greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f))); \
2320     }
2321 
2322 #define DECLARE_BOOL_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                                   \
2323     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                                                                \
2324     {                                                                                                                 \
2325         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f);                                       \
2326     }                                                                                                                 \
2327     void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c)                                                               \
2328     {                                                                                                                 \
2329         c.color.yz() =                                                                                                \
2330             FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)), greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f))) \
2331                 .asFloat();                                                                                           \
2332     }                                                                                                                 \
2333     void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c)                                                               \
2334     {                                                                                                                 \
2335         c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)),                                  \
2336                                   greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f)))                                  \
2337                             .asFloat();                                                                               \
2338     }                                                                                                                 \
2339     void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c)                                                               \
2340     {                                                                                                                 \
2341         c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)),                                     \
2342                             greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f)))                                     \
2343                       .asFloat();                                                                                     \
2344     }
2345 
2346 DECLARE_FLOAT_COMPARE_FUNCS(allEqual)
DECLARE_FLOAT_COMPARE_FUNCS(anyNotEqual)2347 DECLARE_FLOAT_COMPARE_FUNCS(anyNotEqual)
2348 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThan)
2349 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThanEqual)
2350 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThan)
2351 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThanEqual)
2352 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(equal)
2353 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(notEqual)
2354 
2355 DECLARE_INT_COMPARE_FUNCS(allEqual)
2356 DECLARE_INT_COMPARE_FUNCS(anyNotEqual)
2357 DECLARE_INT_CWISE_COMPARE_FUNCS(lessThan)
2358 DECLARE_INT_CWISE_COMPARE_FUNCS(lessThanEqual)
2359 DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThan)
2360 DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThanEqual)
2361 DECLARE_INT_CWISE_COMPARE_FUNCS(equal)
2362 DECLARE_INT_CWISE_COMPARE_FUNCS(notEqual)
2363 
2364 DECLARE_UINT_COMPARE_FUNCS(allEqual)
2365 DECLARE_UINT_COMPARE_FUNCS(anyNotEqual)
2366 DECLARE_UINT_CWISE_COMPARE_FUNCS(lessThan)
2367 DECLARE_UINT_CWISE_COMPARE_FUNCS(lessThanEqual)
2368 DECLARE_UINT_CWISE_COMPARE_FUNCS(greaterThan)
2369 DECLARE_UINT_CWISE_COMPARE_FUNCS(greaterThanEqual)
2370 DECLARE_UINT_CWISE_COMPARE_FUNCS(equal)
2371 DECLARE_UINT_CWISE_COMPARE_FUNCS(notEqual)
2372 
2373 DECLARE_BOOL_COMPARE_FUNCS(allEqual)
2374 DECLARE_BOOL_COMPARE_FUNCS(anyNotEqual)
2375 DECLARE_BOOL_CWISE_COMPARE_FUNCS(equal)
2376 DECLARE_BOOL_CWISE_COMPARE_FUNCS(notEqual)
2377 
2378 // Boolean functions.
2379 
2380 #define DECLARE_UNARY_SCALAR_BVEC_FUNCS(GLSL_NAME, FUNC_NAME)                                 \
2381     void eval_##GLSL_NAME##_bvec2(ShaderEvalContext &c)                                       \
2382     {                                                                                         \
2383         c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))));       \
2384     }                                                                                         \
2385     void eval_##GLSL_NAME##_bvec3(ShaderEvalContext &c)                                       \
2386     {                                                                                         \
2387         c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))));    \
2388     }                                                                                         \
2389     void eval_##GLSL_NAME##_bvec4(ShaderEvalContext &c)                                       \
2390     {                                                                                         \
2391         c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)))); \
2392     }
2393 
2394 #define DECLARE_UNARY_BVEC_BVEC_FUNCS(GLSL_NAME, FUNC_NAME)                                         \
2395     void eval_##GLSL_NAME##_bvec2(ShaderEvalContext &c)                                             \
2396     {                                                                                               \
2397         c.color.yz() = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat();         \
2398     }                                                                                               \
2399     void eval_##GLSL_NAME##_bvec3(ShaderEvalContext &c)                                             \
2400     {                                                                                               \
2401         c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat();     \
2402     }                                                                                               \
2403     void eval_##GLSL_NAME##_bvec4(ShaderEvalContext &c)                                             \
2404     {                                                                                               \
2405         c.color.xyzw() = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f))).asFloat(); \
2406     }
2407 
2408 DECLARE_UNARY_SCALAR_BVEC_FUNCS(any, boolAny)
2409 DECLARE_UNARY_SCALAR_BVEC_FUNCS(all, boolAll)
2410 
2411 void ShaderOperatorTests::init(void)
2412 {
2413 #define BOOL_FUNCS(FUNC_NAME) eval_##FUNC_NAME##_bool, DE_NULL, DE_NULL, DE_NULL
2414 
2415 #define FLOAT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
2416 #define INT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
2417 #define UINT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_uvec2, eval_##FUNC_NAME##_uvec3, eval_##FUNC_NAME##_uvec4
2418 #define BOOL_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
2419 
2420 #define FLOAT_GENTYPE_FUNCS(FUNC_NAME) \
2421     eval_##FUNC_NAME##_float, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
2422 #define INT_GENTYPE_FUNCS(FUNC_NAME) \
2423     eval_##FUNC_NAME##_int, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
2424 #define UINT_GENTYPE_FUNCS(FUNC_NAME) \
2425     eval_##FUNC_NAME##_uint, eval_##FUNC_NAME##_uvec2, eval_##FUNC_NAME##_uvec3, eval_##FUNC_NAME##_uvec4
2426 #define BOOL_GENTYPE_FUNCS(FUNC_NAME) \
2427     eval_##FUNC_NAME##_bool, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
2428 
2429     // Shorthands.
2430     Value notUsed              = Value(VALUE_NONE, 0.0f, 0.0f);
2431     FloatScalar::Symbol lUMax  = FloatScalar::SYMBOL_LOWP_UINT_MAX;
2432     FloatScalar::Symbol mUMax  = FloatScalar::SYMBOL_MEDIUMP_UINT_MAX;
2433     FloatScalar::Symbol lUMaxR = FloatScalar::SYMBOL_LOWP_UINT_MAX_RECIPROCAL;
2434     FloatScalar::Symbol mUMaxR = FloatScalar::SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL;
2435 
2436     std::vector<BuiltinFuncGroup> funcInfoGroups;
2437 
2438     // Unary operators.
2439     funcInfoGroups.push_back(
2440         BuiltinFuncGroup("unary_operator", "Unary operator tests")
2441         << BuiltinOperInfo("plus", "+", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL,
2442                            FLOAT_GENTYPE_FUNCS(nop))
2443         << BuiltinOperInfo("plus", "+", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL,
2444                            INT_GENTYPE_FUNCS(nop))
2445         << BuiltinOperInfo("plus", "+", UGT, Value(UGT, 0.0f, 2e2f), notUsed, notUsed, 5e-3f, 0.0f, PRECMASK_ALL,
2446                            UINT_GENTYPE_FUNCS(nop))
2447         << BuiltinOperInfo("minus", "-", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL,
2448                            FLOAT_GENTYPE_FUNCS(negate))
2449         << BuiltinOperInfo("minus", "-", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL,
2450                            INT_GENTYPE_FUNCS(negate))
2451         << BuiltinOperInfoSeparateRefScaleBias("minus", "-", UGT, Value(UGT, 0.0f, lUMax), notUsed, notUsed, lUMaxR,
2452                                                0.0f, PRECMASK_LOWP, UINT_GENTYPE_FUNCS(negate), lUMaxR,
2453                                                FloatScalar::SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX)
2454         << BuiltinOperInfoSeparateRefScaleBias("minus", "-", UGT, Value(UGT, 0.0f, mUMax), notUsed, notUsed, mUMaxR,
2455                                                0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(negate), mUMaxR,
2456                                                FloatScalar::SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX)
2457         << BuiltinOperInfo("minus", "-", UGT, Value(UGT, 0.0f, 4e9f), notUsed, notUsed, 2e-10f, 0.0f, PRECMASK_HIGHP,
2458                            UINT_GENTYPE_FUNCS(negate))
2459         << BuiltinOperInfo("not", "!", B, Value(B, -1.0f, 1.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_NA,
2460                            eval_boolNot_bool, DE_NULL, DE_NULL, DE_NULL)
2461         << BuiltinOperInfo("bitwise_not", "~", IGT, Value(IGT, -1e5f, 1e5f), notUsed, notUsed, 5e-5f, 0.5f,
2462                            PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseNot))
2463         << BuiltinOperInfo("bitwise_not", "~", UGT, Value(UGT, 0.0f, 2e9f), notUsed, notUsed, 2e-10f, 0.0f,
2464                            PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseNot))
2465 
2466         // Pre/post incr/decr side effect cases.
2467         << BuiltinSideEffOperInfo("pre_increment_effect", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
2468                                   0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
2469         << BuiltinSideEffOperInfo("pre_increment_effect", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed, 0.1f,
2470                                   0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
2471         << BuiltinSideEffOperInfo("pre_increment_effect", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed, 0.1f,
2472                                   0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(addOne))
2473         << BuiltinSideEffOperInfo("pre_decrement_effect", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
2474                                   1.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
2475         << BuiltinSideEffOperInfo("pre_decrement_effect", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed, 0.1f,
2476                                   0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
2477         << BuiltinSideEffOperInfo("pre_decrement_effect", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed, 0.1f,
2478                                   0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(subOne))
2479         << BuiltinPostSideEffOperInfo("post_increment_effect", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
2480                                       0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
2481         << BuiltinPostSideEffOperInfo("post_increment_effect", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed,
2482                                       0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
2483         << BuiltinPostSideEffOperInfo("post_increment_effect", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed,
2484                                       0.1f, 0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(addOne))
2485         << BuiltinPostSideEffOperInfo("post_decrement_effect", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
2486                                       1.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
2487         << BuiltinPostSideEffOperInfo("post_decrement_effect", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed,
2488                                       0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
2489         << BuiltinPostSideEffOperInfo("post_decrement_effect", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed,
2490                                       0.1f, 0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(subOne))
2491 
2492         // Pre/post incr/decr result cases.
2493         << BuiltinOperInfo("pre_increment_result", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.0f,
2494                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
2495         << BuiltinOperInfo("pre_increment_result", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed, 0.1f, 0.5f,
2496                            PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
2497         << BuiltinOperInfo("pre_increment_result", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed, 0.1f, 0.0f,
2498                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(addOne))
2499         << BuiltinOperInfo("pre_decrement_result", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 1.0f,
2500                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
2501         << BuiltinOperInfo("pre_decrement_result", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed, 0.1f, 0.5f,
2502                            PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
2503         << BuiltinOperInfo("pre_decrement_result", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed, 0.1f, 0.0f,
2504                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(subOne))
2505         << BuiltinPostOperInfo("post_increment_result", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f,
2506                                PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(nop))
2507         << BuiltinPostOperInfo("post_increment_result", "++", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f,
2508                                0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(nop))
2509         << BuiltinPostOperInfo("post_increment_result", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed, 0.1f, 0.0f,
2510                                PRECMASK_ALL, UINT_GENTYPE_FUNCS(nop))
2511         << BuiltinPostOperInfo("post_decrement_result", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f,
2512                                PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(nop))
2513         << BuiltinPostOperInfo("post_decrement_result", "--", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f,
2514                                0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(nop))
2515         << BuiltinPostOperInfo("post_decrement_result", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed, 0.1f,
2516                                0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(nop)));
2517 
2518     BuiltinFuncGroup binaryOpGroup("binary_operator", "Binary operator tests");
2519 
2520     // Normal binary operations and their corresponding assignment operations have lots in common; generate both in the following loop.
2521 
2522     for (int binaryOperatorType = 0; binaryOperatorType <= 2;
2523          binaryOperatorType++) // 0: normal op test, 1: assignment op side-effect test, 2: assignment op result test
2524     {
2525         bool isNormalOp  = binaryOperatorType == 0;
2526         bool isAssignEff = binaryOperatorType == 1;
2527         bool isAssignRes = binaryOperatorType == 2;
2528 
2529         DE_ASSERT(isNormalOp || isAssignEff || isAssignRes);
2530         DE_UNREF(isAssignRes);
2531 
2532         const char *addName        = isNormalOp ? "add" : isAssignEff ? "add_assign_effect" : "add_assign_result";
2533         const char *subName        = isNormalOp ? "sub" : isAssignEff ? "sub_assign_effect" : "sub_assign_result";
2534         const char *mulName        = isNormalOp ? "mul" : isAssignEff ? "mul_assign_effect" : "mul_assign_result";
2535         const char *divName        = isNormalOp ? "div" : isAssignEff ? "div_assign_effect" : "div_assign_result";
2536         const char *modName        = isNormalOp ? "mod" : isAssignEff ? "mod_assign_effect" : "mod_assign_result";
2537         const char *andName        = isNormalOp  ? "bitwise_and" :
2538                                      isAssignEff ? "bitwise_and_assign_effect" :
2539                                                    "bitwise_and_assign_result";
2540         const char *orName         = isNormalOp  ? "bitwise_or" :
2541                                      isAssignEff ? "bitwise_or_assign_effect" :
2542                                                    "bitwise_or_assign_result";
2543         const char *xorName        = isNormalOp  ? "bitwise_xor" :
2544                                      isAssignEff ? "bitwise_xor_assign_effect" :
2545                                                    "bitwise_xor_assign_result";
2546         const char *leftShiftName  = isNormalOp  ? "left_shift" :
2547                                      isAssignEff ? "left_shift_assign_effect" :
2548                                                    "left_shift_assign_result";
2549         const char *rightShiftName = isNormalOp  ? "right_shift" :
2550                                      isAssignEff ? "right_shift_assign_effect" :
2551                                                    "right_shift_assign_result";
2552         const char *addOp          = isNormalOp ? "+" : "+=";
2553         const char *subOp          = isNormalOp ? "-" : "-=";
2554         const char *mulOp          = isNormalOp ? "*" : "*=";
2555         const char *divOp          = isNormalOp ? "/" : "/=";
2556         const char *modOp          = isNormalOp ? "%" : "%=";
2557         const char *andOp          = isNormalOp ? "&" : "&=";
2558         const char *orOp           = isNormalOp ? "|" : "|=";
2559         const char *xorOp          = isNormalOp ? "^" : "^=";
2560         const char *leftShiftOp    = isNormalOp ? "<<" : "<<=";
2561         const char *rightShiftOp   = isNormalOp ? ">>" : ">>=";
2562 
2563         // Pointer to appropriate OperInfo function.
2564         BuiltinFuncInfo (*operInfoFunc)(const char *, const char *, ValueType, Value, Value, Value, const FloatScalar &,
2565                                         const FloatScalar &, uint32_t, ShaderEvalFunc, ShaderEvalFunc, ShaderEvalFunc,
2566                                         ShaderEvalFunc) = isAssignEff ? BuiltinSideEffOperInfo : BuiltinOperInfo;
2567 
2568         DE_ASSERT(operInfoFunc != DE_NULL);
2569 
2570         // The following cases will be added for each operator, precision and fundamental type (float, int, uint) combination, where applicable:
2571         // gentype <op> gentype
2572         // vector <op> scalar
2573         // For normal (non-assigning) operators only:
2574         //   scalar <op> vector
2575 
2576         // The add operator.
2577 
2578         binaryOpGroup << operInfoFunc(addName, addOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f,
2579                                       0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(add))
2580                       << operInfoFunc(addName, addOp, IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed,
2581                                       0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(add))
2582                       << operInfoFunc(addName, addOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2583                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(add))
2584                       << operInfoFunc(addName, addOp, UGT, Value(UGT, 0.0f, 1e2f), Value(UGT, 0.0f, 1e2f), notUsed,
2585                                       5e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(add))
2586                       << operInfoFunc(addName, addOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2587                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(add))
2588                       << operInfoFunc(addName, addOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
2589                                       0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(addVecScalar))
2590                       << operInfoFunc(addName, addOp, IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f,
2591                                       0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(addVecScalar))
2592                       << operInfoFunc(addName, addOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
2593                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(addVecScalar))
2594                       << operInfoFunc(addName, addOp, UV, Value(UV, 0.0f, 1e2f), Value(U, 0.0f, 1e2f), notUsed, 5e-3f,
2595                                       0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(addVecScalar))
2596                       << operInfoFunc(addName, addOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2597                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(addVecScalar));
2598 
2599         if (isNormalOp)
2600             binaryOpGroup << operInfoFunc(addName, addOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
2601                                           1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(addScalarVec))
2602                           << operInfoFunc(addName, addOp, IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed,
2603                                           0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(addScalarVec))
2604                           << operInfoFunc(addName, addOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2605                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(addScalarVec))
2606                           << operInfoFunc(addName, addOp, UV, Value(U, 0.0f, 1e2f), Value(UV, 0.0f, 1e2f), notUsed,
2607                                           5e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(addScalarVec))
2608                           << operInfoFunc(addName, addOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2609                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(addScalarVec));
2610 
2611         // The subtract operator.
2612 
2613         binaryOpGroup << operInfoFunc(subName, subOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f,
2614                                       0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(sub))
2615                       << operInfoFunc(subName, subOp, IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed,
2616                                       0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(sub))
2617                       << operInfoFunc(subName, subOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2618                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(sub))
2619                       << operInfoFunc(subName, subOp, UGT, Value(UGT, 1e2f, 2e2f), Value(UGT, 0.0f, 1e2f), notUsed,
2620                                       5e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(sub))
2621                       << operInfoFunc(subName, subOp, UGT, Value(UGT, .5e9f, 3.7e9f), Value(UGT, 0.0f, 3.9e9f), notUsed,
2622                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(sub))
2623                       << operInfoFunc(subName, subOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
2624                                       0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(subVecScalar))
2625                       << operInfoFunc(subName, subOp, IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f,
2626                                       0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(subVecScalar))
2627                       << operInfoFunc(subName, subOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
2628                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(subVecScalar))
2629                       << operInfoFunc(subName, subOp, UV, Value(UV, 1e2f, 2e2f), Value(U, 0.0f, 1e2f), notUsed, 5e-3f,
2630                                       0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(subVecScalar))
2631                       << operInfoFunc(subName, subOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2632                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(subVecScalar));
2633 
2634         if (isNormalOp)
2635             binaryOpGroup << operInfoFunc(subName, subOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
2636                                           1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(subScalarVec))
2637                           << operInfoFunc(subName, subOp, IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed,
2638                                           0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(subScalarVec))
2639                           << operInfoFunc(subName, subOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2640                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(subScalarVec))
2641                           << operInfoFunc(subName, subOp, UV, Value(U, 1e2f, 2e2f), Value(UV, 0.0f, 1e2f), notUsed,
2642                                           5e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(subScalarVec))
2643                           << operInfoFunc(subName, subOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2644                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(subScalarVec));
2645 
2646         // The multiply operator.
2647 
2648         binaryOpGroup << operInfoFunc(mulName, mulOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f,
2649                                       0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(mul))
2650                       << operInfoFunc(mulName, mulOp, IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed,
2651                                       0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(mul))
2652                       << operInfoFunc(mulName, mulOp, IGT, Value(IGT, -3e5f, 3e5f), Value(IGT, -3e4f, 3e4f), notUsed,
2653                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(mul))
2654                       << operInfoFunc(mulName, mulOp, UGT, Value(UGT, 0.0f, 16.0f), Value(UGT, 0.0f, 16.0f), notUsed,
2655                                       4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(mul))
2656                       << operInfoFunc(mulName, mulOp, UGT, Value(UGT, 0.0f, 6e5f), Value(UGT, 0.0f, 6e4f), notUsed,
2657                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(mul))
2658                       << operInfoFunc(mulName, mulOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
2659                                       0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mulVecScalar))
2660                       << operInfoFunc(mulName, mulOp, IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f,
2661                                       0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(mulVecScalar))
2662                       << operInfoFunc(mulName, mulOp, IV, Value(IV, -3e5f, 3e5f), Value(I, -3e4f, 3e4f), notUsed,
2663                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(mulVecScalar))
2664                       << operInfoFunc(mulName, mulOp, UV, Value(UV, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 4e-3f,
2665                                       0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(mulVecScalar))
2666                       << operInfoFunc(mulName, mulOp, UV, Value(UV, 0.0f, 6e5f), Value(U, 0.0f, 6e4f), notUsed, 2e-10f,
2667                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(mulVecScalar));
2668 
2669         if (isNormalOp)
2670             binaryOpGroup << operInfoFunc(mulName, mulOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
2671                                           1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mulScalarVec))
2672                           << operInfoFunc(mulName, mulOp, IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed,
2673                                           0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(mulScalarVec))
2674                           << operInfoFunc(mulName, mulOp, IV, Value(I, -3e5f, 3e5f), Value(IV, -3e4f, 3e4f), notUsed,
2675                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(mulScalarVec))
2676                           << operInfoFunc(mulName, mulOp, UV, Value(U, 0.0f, 16.0f), Value(UV, 0.0f, 16.0f), notUsed,
2677                                           4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(mulScalarVec))
2678                           << operInfoFunc(mulName, mulOp, UV, Value(U, 0.0f, 6e5f), Value(UV, 0.0f, 6e4f), notUsed,
2679                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(mulScalarVec));
2680 
2681         // The divide operator.
2682 
2683         binaryOpGroup << operInfoFunc(divName, divOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -2.0f, -0.5f), notUsed,
2684                                       1.0f, 0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(div))
2685                       << operInfoFunc(divName, divOp, IGT, Value(IGT, 24.0f, 24.0f), Value(IGT, -4.0f, -1.0f), notUsed,
2686                                       0.04f, 1.0f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(div))
2687                       << operInfoFunc(divName, divOp, IGT, Value(IGT, 40320.0f, 40320.0f), Value(IGT, -8.0f, -1.0f),
2688                                       notUsed, 1e-5f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(div))
2689                       << operInfoFunc(divName, divOp, UGT, Value(UGT, 0.0f, 24.0f), Value(UGT, 1.0f, 4.0f), notUsed,
2690                                       0.04f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(div))
2691                       << operInfoFunc(divName, divOp, UGT, Value(UGT, 0.0f, 40320.0f), Value(UGT, 1.0f, 8.0f), notUsed,
2692                                       1e-5f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(div))
2693                       << operInfoFunc(divName, divOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -2.0f, -0.5f), notUsed, 1.0f,
2694                                       0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(divVecScalar))
2695                       << operInfoFunc(divName, divOp, IV, Value(IV, 24.0f, 24.0f), Value(I, -4.0f, -1.0f), notUsed,
2696                                       0.04f, 1.0f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(divVecScalar))
2697                       << operInfoFunc(divName, divOp, IV, Value(IV, 40320.0f, 40320.0f), Value(I, -8.0f, -1.0f),
2698                                       notUsed, 1e-5f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(divVecScalar))
2699                       << operInfoFunc(divName, divOp, UV, Value(UV, 0.0f, 24.0f), Value(U, 1.0f, 4.0f), notUsed, 0.04f,
2700                                       0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(divVecScalar))
2701                       << operInfoFunc(divName, divOp, UV, Value(UV, 0.0f, 40320.0f), Value(U, 1.0f, 8.0f), notUsed,
2702                                       1e-5f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(divVecScalar));
2703 
2704         if (isNormalOp)
2705             binaryOpGroup << operInfoFunc(divName, divOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -2.0f, -0.5f), notUsed,
2706                                           1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(divScalarVec))
2707                           << operInfoFunc(divName, divOp, IV, Value(I, 24.0f, 24.0f), Value(IV, -4.0f, -1.0f), notUsed,
2708                                           0.04f, 1.0f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(divScalarVec))
2709                           << operInfoFunc(divName, divOp, IV, Value(I, 40320.0f, 40320.0f), Value(IV, -8.0f, -1.0f),
2710                                           notUsed, 1e-5f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(divScalarVec))
2711                           << operInfoFunc(divName, divOp, UV, Value(U, 0.0f, 24.0f), Value(UV, 1.0f, 4.0f), notUsed,
2712                                           0.04f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(divScalarVec))
2713                           << operInfoFunc(divName, divOp, UV, Value(U, 0.0f, 40320.0f), Value(UV, 1.0f, 8.0f), notUsed,
2714                                           1e-5f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(divScalarVec));
2715 
2716         // The modulus operator.
2717 
2718         binaryOpGroup << operInfoFunc(modName, modOp, IGT, Value(IGT, 0.0f, 6.0f), Value(IGT, 1.1f, 6.1f), notUsed,
2719                                       0.25f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(mod))
2720                       << operInfoFunc(modName, modOp, IGT, Value(IGT, 0.0f, 14.0f), Value(IGT, 1.1f, 11.1f), notUsed,
2721                                       0.1f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(mod))
2722                       << operInfoFunc(modName, modOp, UGT, Value(UGT, 0.0f, 6.0f), Value(UGT, 1.1f, 6.1f), notUsed,
2723                                       0.25f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(mod))
2724                       << operInfoFunc(modName, modOp, UGT, Value(UGT, 0.0f, 24.0f), Value(UGT, 1.1f, 11.1f), notUsed,
2725                                       0.1f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(mod))
2726                       << operInfoFunc(modName, modOp, IV, Value(IV, 0.0f, 6.0f), Value(I, 1.1f, 6.1f), notUsed, 0.25f,
2727                                       0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(modVecScalar))
2728                       << operInfoFunc(modName, modOp, IV, Value(IV, 0.0f, 6.0f), Value(I, 1.1f, 11.1f), notUsed, 0.1f,
2729                                       0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(modVecScalar))
2730                       << operInfoFunc(modName, modOp, UV, Value(UV, 0.0f, 6.0f), Value(U, 1.1f, 6.1f), notUsed, 0.25f,
2731                                       0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(modVecScalar))
2732                       << operInfoFunc(modName, modOp, UV, Value(UV, 0.0f, 24.0f), Value(U, 1.1f, 11.1f), notUsed, 0.1f,
2733                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(modVecScalar));
2734 
2735         if (isNormalOp)
2736             binaryOpGroup << operInfoFunc(modName, modOp, IV, Value(I, 0.0f, 6.0f), Value(IV, 1.1f, 6.1f), notUsed,
2737                                           0.25f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(modScalarVec))
2738                           << operInfoFunc(modName, modOp, IV, Value(I, 0.0f, 6.0f), Value(IV, 1.1f, 11.1f), notUsed,
2739                                           0.1f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(modScalarVec))
2740                           << operInfoFunc(modName, modOp, UV, Value(U, 0.0f, 6.0f), Value(UV, 1.1f, 6.1f), notUsed,
2741                                           0.25f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(modScalarVec))
2742                           << operInfoFunc(modName, modOp, UV, Value(U, 0.0f, 24.0f), Value(UV, 1.1f, 11.1f), notUsed,
2743                                           0.1f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(modScalarVec));
2744 
2745         // The bitwise and operator.
2746 
2747         binaryOpGroup << operInfoFunc(andName, andOp, IGT, Value(IGT, -16.0f, 16.0f), Value(IGT, -16.0f, 16.0f),
2748                                       notUsed, 0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(bitwiseAnd))
2749                       << operInfoFunc(andName, andOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2750                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseAnd))
2751                       << operInfoFunc(andName, andOp, UGT, Value(UGT, 0.0f, 32.0f), Value(UGT, 0.0f, 32.0f), notUsed,
2752                                       0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(bitwiseAnd))
2753                       << operInfoFunc(andName, andOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2754                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseAnd))
2755                       << operInfoFunc(andName, andOp, IV, Value(IV, -16.0f, 16.0f), Value(I, -16.0f, 16.0f), notUsed,
2756                                       0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(bitwiseAndVecScalar))
2757                       << operInfoFunc(andName, andOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
2758                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseAndVecScalar))
2759                       << operInfoFunc(andName, andOp, UV, Value(UV, 0.0f, 32.0f), Value(U, 0.0f, 32.0f), notUsed, 0.03f,
2760                                       0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseAndVecScalar))
2761                       << operInfoFunc(andName, andOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2762                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseAndVecScalar));
2763 
2764         if (isNormalOp)
2765             binaryOpGroup << operInfoFunc(andName, andOp, IV, Value(I, -16.0f, 16.0f), Value(IV, -16.0f, 16.0f),
2766                                           notUsed, 0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP,
2767                                           INT_VEC_FUNCS(bitwiseAndScalarVec))
2768                           << operInfoFunc(andName, andOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2769                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseAndScalarVec))
2770                           << operInfoFunc(andName, andOp, UV, Value(U, 0.0f, 32.0f), Value(UV, 0.0f, 32.0f), notUsed,
2771                                           0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseAndScalarVec))
2772                           << operInfoFunc(andName, andOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2773                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseAndScalarVec));
2774 
2775         // The bitwise or operator.
2776 
2777         binaryOpGroup << operInfoFunc(orName, orOp, IGT, Value(IGT, -16.0f, 16.0f), Value(IGT, -16.0f, 16.0f), notUsed,
2778                                       0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(bitwiseOr))
2779                       << operInfoFunc(orName, orOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2780                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseOr))
2781                       << operInfoFunc(orName, orOp, UGT, Value(UGT, 0.0f, 32.0f), Value(UGT, 0.0f, 32.0f), notUsed,
2782                                       0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(bitwiseOr))
2783                       << operInfoFunc(orName, orOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2784                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseOr))
2785                       << operInfoFunc(orName, orOp, IV, Value(IV, -16.0f, 16.0f), Value(I, -16.0f, 16.0f), notUsed,
2786                                       0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(bitwiseOrVecScalar))
2787                       << operInfoFunc(orName, orOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed, 4e-10f,
2788                                       0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseOrVecScalar))
2789                       << operInfoFunc(orName, orOp, UV, Value(UV, 0.0f, 32.0f), Value(U, 0.0f, 32.0f), notUsed, 0.03f,
2790                                       0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseOrVecScalar))
2791                       << operInfoFunc(orName, orOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2792                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseOrVecScalar));
2793 
2794         if (isNormalOp)
2795             binaryOpGroup << operInfoFunc(orName, orOp, IV, Value(I, -16.0f, 16.0f), Value(IV, -16.0f, 16.0f), notUsed,
2796                                           0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(bitwiseOrScalarVec))
2797                           << operInfoFunc(orName, orOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2798                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseOrScalarVec))
2799                           << operInfoFunc(orName, orOp, UV, Value(U, 0.0f, 32.0f), Value(UV, 0.0f, 32.0f), notUsed,
2800                                           0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseOrScalarVec))
2801                           << operInfoFunc(orName, orOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2802                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseOrScalarVec));
2803 
2804         // The bitwise xor operator.
2805 
2806         binaryOpGroup << operInfoFunc(xorName, xorOp, IGT, Value(IGT, -16.0f, 16.0f), Value(IGT, -16.0f, 16.0f),
2807                                       notUsed, 0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(bitwiseXor))
2808                       << operInfoFunc(xorName, xorOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2809                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseXor))
2810                       << operInfoFunc(xorName, xorOp, UGT, Value(UGT, 0.0f, 32.0f), Value(UGT, 0.0f, 32.0f), notUsed,
2811                                       0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(bitwiseXor))
2812                       << operInfoFunc(xorName, xorOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2813                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseXor))
2814                       << operInfoFunc(xorName, xorOp, IV, Value(IV, -16.0f, 16.0f), Value(I, -16.0f, 16.0f), notUsed,
2815                                       0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(bitwiseXorVecScalar))
2816                       << operInfoFunc(xorName, xorOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
2817                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseXorVecScalar))
2818                       << operInfoFunc(xorName, xorOp, UV, Value(UV, 0.0f, 32.0f), Value(U, 0.0f, 32.0f), notUsed, 0.03f,
2819                                       0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseXorVecScalar))
2820                       << operInfoFunc(xorName, xorOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2821                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseXorVecScalar));
2822 
2823         if (isNormalOp)
2824             binaryOpGroup << operInfoFunc(xorName, xorOp, IV, Value(I, -16.0f, 16.0f), Value(IV, -16.0f, 16.0f),
2825                                           notUsed, 0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP,
2826                                           INT_VEC_FUNCS(bitwiseXorScalarVec))
2827                           << operInfoFunc(xorName, xorOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2828                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseXorScalarVec))
2829                           << operInfoFunc(xorName, xorOp, UV, Value(U, 0.0f, 32.0f), Value(UV, 0.0f, 32.0f), notUsed,
2830                                           0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseXorScalarVec))
2831                           << operInfoFunc(xorName, xorOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2832                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseXorScalarVec));
2833 
2834         // The left shift operator. Second operand (shift amount) can be either int or uint, even for uint and int first operand, respectively.
2835 
2836         for (int isSignedAmount = 0; isSignedAmount <= 1; isSignedAmount++)
2837         {
2838             ValueType gType = isSignedAmount == 0 ? UGT : IGT;
2839             ValueType sType = isSignedAmount == 0 ? U : I;
2840             binaryOpGroup << operInfoFunc(leftShiftName, leftShiftOp, IGT, Value(IGT, -7.0f, 7.0f),
2841                                           Value(gType, 0.0f, 4.0f), notUsed, 4e-3f, 0.5f, PRECMASK_LOWP_MEDIUMP,
2842                                           INT_GENTYPE_FUNCS(leftShift))
2843                           << operInfoFunc(leftShiftName, leftShiftOp, IGT, Value(IGT, -7.0f, 7.0f),
2844                                           Value(gType, 0.0f, 27.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
2845                                           INT_GENTYPE_FUNCS(leftShift))
2846                           << operInfoFunc(leftShiftName, leftShiftOp, UGT, Value(UGT, 0.0f, 7.0f),
2847                                           Value(gType, 0.0f, 5.0f), notUsed, 4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP,
2848                                           UINT_GENTYPE_FUNCS(leftShift))
2849                           << operInfoFunc(leftShiftName, leftShiftOp, UGT, Value(UGT, 0.0f, 7.0f),
2850                                           Value(gType, 0.0f, 28.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
2851                                           UINT_GENTYPE_FUNCS(leftShift))
2852                           << operInfoFunc(leftShiftName, leftShiftOp, IV, Value(IV, -7.0f, 7.0f),
2853                                           Value(sType, 0.0f, 4.0f), notUsed, 4e-3f, 0.5f, PRECMASK_LOWP_MEDIUMP,
2854                                           INT_VEC_FUNCS(leftShiftVecScalar))
2855                           << operInfoFunc(leftShiftName, leftShiftOp, IV, Value(IV, -7.0f, 7.0f),
2856                                           Value(sType, 0.0f, 27.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
2857                                           INT_VEC_FUNCS(leftShiftVecScalar))
2858                           << operInfoFunc(leftShiftName, leftShiftOp, UV, Value(UV, 0.0f, 7.0f),
2859                                           Value(sType, 0.0f, 5.0f), notUsed, 4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP,
2860                                           UINT_VEC_FUNCS(leftShiftVecScalar))
2861                           << operInfoFunc(leftShiftName, leftShiftOp, UV, Value(UV, 0.0f, 7.0f),
2862                                           Value(sType, 0.0f, 28.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
2863                                           UINT_VEC_FUNCS(leftShiftVecScalar));
2864         }
2865 
2866         // The right shift operator. Second operand (shift amount) can be either int or uint, even for uint and int first operand, respectively.
2867 
2868         for (int isSignedAmount = 0; isSignedAmount <= 1; isSignedAmount++)
2869         {
2870             ValueType gType = isSignedAmount == 0 ? UGT : IGT;
2871             ValueType sType = isSignedAmount == 0 ? U : I;
2872             binaryOpGroup << operInfoFunc(rightShiftName, rightShiftOp, IGT, Value(IGT, -127.0f, 127.0f),
2873                                           Value(gType, 0.0f, 8.0f), notUsed, 4e-3f, 0.5f, PRECMASK_LOWP_MEDIUMP,
2874                                           INT_GENTYPE_FUNCS(rightShift))
2875                           << operInfoFunc(rightShiftName, rightShiftOp, IGT, Value(IGT, -2e9f, 2e9f),
2876                                           Value(gType, 0.0f, 31.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
2877                                           INT_GENTYPE_FUNCS(rightShift))
2878                           << operInfoFunc(rightShiftName, rightShiftOp, UGT, Value(UGT, 0.0f, 255.0f),
2879                                           Value(gType, 0.0f, 8.0f), notUsed, 4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP,
2880                                           UINT_GENTYPE_FUNCS(rightShift))
2881                           << operInfoFunc(rightShiftName, rightShiftOp, UGT, Value(UGT, 0.0f, 4e9f),
2882                                           Value(gType, 0.0f, 31.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
2883                                           UINT_GENTYPE_FUNCS(rightShift))
2884                           << operInfoFunc(rightShiftName, rightShiftOp, IV, Value(IV, -127.0f, 127.0f),
2885                                           Value(sType, 0.0f, 8.0f), notUsed, 4e-3f, 0.5f, PRECMASK_LOWP_MEDIUMP,
2886                                           INT_VEC_FUNCS(rightShiftVecScalar))
2887                           << operInfoFunc(rightShiftName, rightShiftOp, IV, Value(IV, -2e9f, 2e9f),
2888                                           Value(sType, 0.0f, 31.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
2889                                           INT_VEC_FUNCS(rightShiftVecScalar))
2890                           << operInfoFunc(rightShiftName, rightShiftOp, UV, Value(UV, 0.0f, 255.0f),
2891                                           Value(sType, 0.0f, 8.0f), notUsed, 4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP,
2892                                           UINT_VEC_FUNCS(rightShiftVecScalar))
2893                           << operInfoFunc(rightShiftName, rightShiftOp, UV, Value(UV, 0.0f, 4e9f),
2894                                           Value(sType, 0.0f, 31.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
2895                                           UINT_VEC_FUNCS(rightShiftVecScalar));
2896         }
2897     }
2898 
2899     // Rest of binary operators.
2900 
2901     binaryOpGroup
2902         // Scalar relational operators.
2903         << BuiltinOperInfo("less", "<", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2904                            PRECMASK_ALL, eval_lessThan_float, DE_NULL, DE_NULL, DE_NULL)
2905         << BuiltinOperInfo("less", "<", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
2906                            PRECMASK_ALL, eval_lessThan_int, DE_NULL, DE_NULL, DE_NULL)
2907         << BuiltinOperInfo("less", "<", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f, 0.0f,
2908                            PRECMASK_ALL, eval_lessThan_uint, DE_NULL, DE_NULL, DE_NULL)
2909         << BuiltinOperInfo("less_or_equal", "<=", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2910                            PRECMASK_ALL, eval_lessThanEqual_float, DE_NULL, DE_NULL, DE_NULL)
2911         << BuiltinOperInfo("less_or_equal", "<=", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
2912                            PRECMASK_ALL, eval_lessThanEqual_int, DE_NULL, DE_NULL, DE_NULL)
2913         << BuiltinOperInfo("less_or_equal", "<=", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f, 0.0f,
2914                            PRECMASK_ALL, eval_lessThanEqual_uint, DE_NULL, DE_NULL, DE_NULL)
2915         << BuiltinOperInfo("greater", ">", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2916                            PRECMASK_ALL, eval_greaterThan_float, DE_NULL, DE_NULL, DE_NULL)
2917         << BuiltinOperInfo("greater", ">", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
2918                            PRECMASK_ALL, eval_greaterThan_int, DE_NULL, DE_NULL, DE_NULL)
2919         << BuiltinOperInfo("greater", ">", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f, 0.0f,
2920                            PRECMASK_ALL, eval_greaterThan_uint, DE_NULL, DE_NULL, DE_NULL)
2921         << BuiltinOperInfo("greater_or_equal", ">=", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
2922                            0.0f, PRECMASK_ALL, eval_greaterThanEqual_float, DE_NULL, DE_NULL, DE_NULL)
2923         << BuiltinOperInfo("greater_or_equal", ">=", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f,
2924                            0.0f, PRECMASK_ALL, eval_greaterThanEqual_int, DE_NULL, DE_NULL, DE_NULL)
2925         << BuiltinOperInfo("greater_or_equal", ">=", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f,
2926                            0.0f, PRECMASK_ALL, eval_greaterThanEqual_uint, DE_NULL, DE_NULL, DE_NULL)
2927 
2928         // Equality comparison operators.
2929         << BuiltinOperInfo("equal", "==", B, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2930                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(allEqual))
2931         << BuiltinOperInfo("equal", "==", B, Value(IGT, -5.5f, 4.7f), Value(IGT, -2.1f, 0.1f), notUsed, 1.0f, 0.0f,
2932                            PRECMASK_ALL, INT_GENTYPE_FUNCS(allEqual))
2933         << BuiltinOperInfo("equal", "==", B, Value(UGT, 0.0f, 8.0f), Value(UGT, 3.5f, 4.5f), notUsed, 1.0f, 0.0f,
2934                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(allEqual))
2935         << BuiltinOperInfo("equal", "==", B, Value(BGT, -2.1f, 2.1f), Value(BGT, -1.1f, 3.0f), notUsed, 1.0f, 0.0f,
2936                            PRECMASK_NA, BOOL_GENTYPE_FUNCS(allEqual))
2937         << BuiltinOperInfo("not_equal", "!=", B, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2938                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(anyNotEqual))
2939         << BuiltinOperInfo("not_equal", "!=", B, Value(IGT, -5.5f, 4.7f), Value(IGT, -2.1f, 0.1f), notUsed, 1.0f, 0.0f,
2940                            PRECMASK_ALL, INT_GENTYPE_FUNCS(anyNotEqual))
2941         << BuiltinOperInfo("not_equal", "!=", B, Value(UGT, 0.0f, 8.0f), Value(UGT, 3.5f, 4.5f), notUsed, 1.0f, 0.0f,
2942                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(anyNotEqual))
2943         << BuiltinOperInfo("not_equal", "!=", B, Value(BGT, -2.1f, 2.1f), Value(BGT, -1.1f, 3.0f), notUsed, 1.0f, 0.0f,
2944                            PRECMASK_NA, BOOL_GENTYPE_FUNCS(anyNotEqual))
2945 
2946         // Logical operators.
2947         << BuiltinOperInfo("logical_and", "&&", B, Value(B, -1.0f, 1.0f), Value(B, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2948                            PRECMASK_NA, BOOL_FUNCS(logicalAnd))
2949         << BuiltinOperInfo("logical_or", "||", B, Value(B, -1.0f, 1.0f), Value(B, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2950                            PRECMASK_NA, BOOL_FUNCS(logicalOr))
2951         << BuiltinOperInfo("logical_xor", "^^", B, Value(B, -1.0f, 1.0f), Value(B, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2952                            PRECMASK_NA, BOOL_FUNCS(logicalXor));
2953 
2954     funcInfoGroups.push_back(binaryOpGroup);
2955 
2956     // 8.1 Angle and Trigonometry Functions.
2957     funcInfoGroups.push_back(BuiltinFuncGroup("angle_and_trigonometry", "Angle and trigonometry function tests.")
2958                              << BuiltinFuncInfo("radians", "radians", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed,
2959                                                 25.0f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(radians))
2960                              << BuiltinFuncInfo("degrees", "degrees", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed,
2961                                                 0.04f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(degrees))
2962                              << BuiltinFuncInfo("sin", "sin", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f, 0.5f,
2963                                                 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(sin))
2964                              << BuiltinFuncInfo("sin", "sin", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f, 0.5f,
2965                                                 PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(sin))
2966                              << BuiltinFuncInfo("cos", "cos", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f, 0.5f,
2967                                                 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(cos))
2968                              << BuiltinFuncInfo("cos", "cos", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f, 0.5f,
2969                                                 PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(cos))
2970                              << BuiltinFuncInfo("tan", "tan", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f, 0.5f,
2971                                                 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(tan))
2972                              << BuiltinFuncInfo("tan", "tan", GT, Value(GT, -1.5f, 5.5f), notUsed, notUsed, 0.5f, 0.5f,
2973                                                 PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(tan))
2974                              << BuiltinFuncInfo("asin", "asin", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 1.0f,
2975                                                 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(asin))
2976                              << BuiltinFuncInfo("acos", "acos", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 1.0f,
2977                                                 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(acos))
2978                              << BuiltinFuncInfo("atan", "atan", GT, Value(GT, -4.0f, 4.0f), notUsed, notUsed, 0.5f,
2979                                                 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(atan))
2980                              << BuiltinFuncInfo("atan2", "atan", GT, Value(GT, -4.0f, 4.0f), Value(GT, 0.5f, 2.0f),
2981                                                 notUsed, 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(atan2))
2982                              << BuiltinFuncInfo("sinh", "sinh", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f,
2983                                                 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(sinh))
2984                              << BuiltinFuncInfo("sinh", "sinh", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f,
2985                                                 0.5f, PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(sinh))
2986                              << BuiltinFuncInfo("cosh", "cosh", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f,
2987                                                 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(cosh))
2988                              << BuiltinFuncInfo("cosh", "cosh", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f,
2989                                                 0.5f, PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(cosh))
2990                              << BuiltinFuncInfo("tanh", "tanh", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f,
2991                                                 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(tanh))
2992                              << BuiltinFuncInfo("tanh", "tanh", GT, Value(GT, -1.5f, 5.5f), notUsed, notUsed, 0.5f,
2993                                                 0.5f, PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(tanh))
2994                              << BuiltinFuncInfo("asinh", "asinh", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 1.0f,
2995                                                 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(asinh))
2996                              << BuiltinFuncInfo("acosh", "acosh", GT, Value(GT, 1.0f, 2.2f), notUsed, notUsed, 1.0f,
2997                                                 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(acosh))
2998                              << BuiltinFuncInfo("atanh", "atanh", GT, Value(GT, -0.99f, 0.99f), notUsed, notUsed, 1.0f,
2999                                                 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(atanh)));
3000 
3001     // 8.2 Exponential Functions.
3002     funcInfoGroups.push_back(BuiltinFuncGroup("exponential", "Exponential function tests")
3003                              << BuiltinFuncInfo("pow", "pow", GT, Value(GT, 0.1f, 8.0f), Value(GT, -4.0f, 2.0f),
3004                                                 notUsed, 1.0f, 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(pow))
3005                              << BuiltinFuncInfo("exp", "exp", GT, Value(GT, -6.0f, 3.0f), notUsed, notUsed, 0.5f, 0.0f,
3006                                                 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(exp))
3007                              << BuiltinFuncInfo("log", "log", GT, Value(GT, 0.1f, 10.0f), notUsed, notUsed, 0.5f, 0.3f,
3008                                                 PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(log))
3009                              << BuiltinFuncInfo("exp2", "exp2", GT, Value(GT, -7.0f, 2.0f), notUsed, notUsed, 1.0f,
3010                                                 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(exp2))
3011                              << BuiltinFuncInfo("log2", "log2", GT, Value(GT, 0.1f, 10.0f), notUsed, notUsed, 1.0f,
3012                                                 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(log2))
3013                              << BuiltinFuncInfo("sqrt", "sqrt", GT, Value(GT, 0.0f, 10.0f), notUsed, notUsed, 0.3f,
3014                                                 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(sqrt))
3015                              << BuiltinFuncInfo("inversesqrt", "inversesqrt", GT, Value(GT, 0.5f, 10.0f), notUsed,
3016                                                 notUsed, 1.0f, 0.0f, PRECMASK_MEDIUMP_HIGHP,
3017                                                 FLOAT_GENTYPE_FUNCS(inverseSqrt)));
3018 
3019     // 8.3 Common Functions.
3020     funcInfoGroups.push_back(
3021         BuiltinFuncGroup("common_functions", "Common function tests.")
3022         << BuiltinFuncInfo("abs", "abs", GT, Value(GT, -2.0f, 2.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL,
3023                            FLOAT_GENTYPE_FUNCS(abs))
3024         << BuiltinFuncInfo("sign", "sign", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.3f, 0.5f, PRECMASK_ALL,
3025                            FLOAT_GENTYPE_FUNCS(sign))
3026         << BuiltinFuncInfo("floor", "floor", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.7f, PRECMASK_ALL,
3027                            FLOAT_GENTYPE_FUNCS(floor))
3028         << BuiltinFuncInfo("trunc", "trunc", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.7f, PRECMASK_ALL,
3029                            FLOAT_GENTYPE_FUNCS(trunc))
3030         << BuiltinFuncInfo("round", "round", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.7f, PRECMASK_ALL,
3031                            FLOAT_GENTYPE_FUNCS(roundToEven))
3032         << BuiltinFuncInfo("roundEven", "roundEven", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.7f,
3033                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(roundToEven))
3034         << BuiltinFuncInfo("ceil", "ceil", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.5f, PRECMASK_ALL,
3035                            FLOAT_GENTYPE_FUNCS(ceil))
3036         << BuiltinFuncInfo("fract", "fract", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.8f, 0.1f, PRECMASK_ALL,
3037                            FLOAT_GENTYPE_FUNCS(fract))
3038         << BuiltinFuncInfo("mod", "mod", GT, Value(GT, -2.0f, 2.0f), Value(GT, 0.9f, 6.0f), notUsed, 0.5f, 0.5f,
3039                            PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(mod))
3040         << BuiltinFuncInfo("mod", "mod", GT, Value(FV, -2.0f, 2.0f), Value(F, 0.9f, 6.0f), notUsed, 0.5f, 0.5f,
3041                            PRECMASK_MEDIUMP_HIGHP, FLOAT_VEC_FUNCS(modVecScalar))
3042         << BuiltinFuncInfo("min", "min", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 0.5f, 0.5f,
3043                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(min))
3044         << BuiltinFuncInfo("min", "min", GT, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 0.5f, 0.5f,
3045                            PRECMASK_ALL, FLOAT_VEC_FUNCS(minVecScalar))
3046         << BuiltinFuncInfo("min", "min", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
3047                            PRECMASK_ALL, INT_GENTYPE_FUNCS(min))
3048         << BuiltinFuncInfo("min", "min", IGT, Value(IV, -4.0f, 4.0f), Value(I, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
3049                            PRECMASK_ALL, INT_VEC_FUNCS(minVecScalar))
3050         << BuiltinFuncInfo("min", "min", UGT, Value(UGT, 0.0f, 8.0f), Value(UGT, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
3051                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(min))
3052         << BuiltinFuncInfo("min", "min", UGT, Value(UV, 0.0f, 8.0f), Value(U, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
3053                            PRECMASK_ALL, UINT_VEC_FUNCS(minVecScalar))
3054         << BuiltinFuncInfo("max", "max", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 0.5f, 0.5f,
3055                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(max))
3056         << BuiltinFuncInfo("max", "max", GT, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 0.5f, 0.5f,
3057                            PRECMASK_ALL, FLOAT_VEC_FUNCS(maxVecScalar))
3058         << BuiltinFuncInfo("max", "max", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
3059                            PRECMASK_ALL, INT_GENTYPE_FUNCS(max))
3060         << BuiltinFuncInfo("max", "max", IGT, Value(IV, -4.0f, 4.0f), Value(I, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
3061                            PRECMASK_ALL, INT_VEC_FUNCS(maxVecScalar))
3062         << BuiltinFuncInfo("max", "max", UGT, Value(UGT, 0.0f, 8.0f), Value(UGT, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
3063                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(max))
3064         << BuiltinFuncInfo("max", "max", UGT, Value(UV, 0.0f, 8.0f), Value(U, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
3065                            PRECMASK_ALL, UINT_VEC_FUNCS(maxVecScalar))
3066         << BuiltinFuncInfo("clamp", "clamp", GT, Value(GT, -1.0f, 1.0f), Value(GT, -0.5f, 0.5f), Value(GT, 0.5f, 1.0f),
3067                            0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(clamp))
3068         << BuiltinFuncInfo("clamp", "clamp", GT, Value(FV, -1.0f, 1.0f), Value(F, -0.5f, 0.5f), Value(F, 0.5f, 1.0f),
3069                            0.5f, 0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(clampVecScalarScalar))
3070         << BuiltinFuncInfo("clamp", "clamp", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -2.0f, 2.0f),
3071                            Value(IGT, 2.0f, 4.0f), 0.125f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(clamp))
3072         << BuiltinFuncInfo("clamp", "clamp", IGT, Value(IV, -4.0f, 4.0f), Value(I, -2.0f, 2.0f), Value(I, 2.0f, 4.0f),
3073                            0.125f, 0.5f, PRECMASK_ALL, INT_VEC_FUNCS(clampVecScalarScalar))
3074         << BuiltinFuncInfo("clamp", "clamp", UGT, Value(UGT, 0.0f, 8.0f), Value(UGT, 2.0f, 6.0f),
3075                            Value(UGT, 6.0f, 8.0f), 0.125f, 0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(clamp))
3076         << BuiltinFuncInfo("clamp", "clamp", UGT, Value(UV, 0.0f, 8.0f), Value(U, 2.0f, 6.0f), Value(U, 6.0f, 8.0f),
3077                            0.125f, 0.0f, PRECMASK_ALL, UINT_VEC_FUNCS(clampVecScalarScalar))
3078         << BuiltinFuncInfo("mix", "mix", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), Value(GT, 0.0f, 1.0f),
3079                            0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(mix))
3080         << BuiltinFuncInfo("mix", "mix", GT, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), Value(F, 0.0f, 1.0f), 0.5f,
3081                            0.5f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mixVecVecScalar))
3082         << BuiltinFuncInfo("step", "step", GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 0.0f), notUsed, 0.5f, 0.25f,
3083                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(step))
3084         << BuiltinFuncInfo("step", "step", GT, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 0.0f), notUsed, 0.5f, 0.25f,
3085                            PRECMASK_ALL, FLOAT_VEC_FUNCS(stepScalarVec))
3086         << BuiltinFuncInfo("smoothstep", "smoothstep", GT, Value(GT, -0.5f, 0.0f), Value(GT, 0.1f, 1.0f),
3087                            Value(GT, -1.0f, 1.0f), 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(smoothStep))
3088         << BuiltinFuncInfo("smoothstep", "smoothstep", GT, Value(F, -0.5f, 0.0f), Value(F, 0.1f, 1.0f),
3089                            Value(FV, -1.0f, 1.0f), 0.5f, 0.5f, PRECMASK_ALL,
3090                            FLOAT_VEC_FUNCS(smoothStepScalarScalarVec)));
3091 
3092     // 8.4 Geometric Functions.
3093     funcInfoGroups.push_back(
3094         BuiltinFuncGroup("geometric", "Geometric function tests.")
3095         << BuiltinFuncInfo("length", "length", F, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f,
3096                            PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(length))
3097         << BuiltinFuncInfo("distance", "distance", F, Value(GT, -5.0f, 5.0f), Value(GT, -5.0f, 5.0f), notUsed, 0.1f,
3098                            0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(distance))
3099         << BuiltinFuncInfo("dot", "dot", F, Value(GT, -5.0f, 5.0f), Value(GT, -5.0f, 5.0f), notUsed, 0.1f, 0.5f,
3100                            PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(dot))
3101         << BuiltinFuncInfo("cross", "cross", V3, Value(GT, -5.0f, 5.0f), Value(GT, -5.0f, 5.0f), notUsed, 0.1f, 0.5f,
3102                            PRECMASK_MEDIUMP_HIGHP, DE_NULL, DE_NULL, eval_cross_vec3, DE_NULL)
3103         << BuiltinFuncInfo("normalize", "normalize", GT, Value(GT, 0.1f, 4.0f), notUsed, notUsed, 0.5f, 0.5f,
3104                            PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(normalize))
3105         << BuiltinFuncInfo("faceforward", "faceforward", GT, Value(GT, -5.0f, 5.0f), Value(GT, -5.0f, 5.0f),
3106                            Value(GT, -1.0f, 1.0f), 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(faceForward))
3107         << BuiltinFuncInfo("reflect", "reflect", GT, Value(GT, -0.8f, -0.5f), Value(GT, 0.5f, 0.8f), notUsed, 0.5f,
3108                            0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(reflect))
3109         << BuiltinFuncInfo("refract", "refract", GT, Value(GT, -0.8f, 1.2f), Value(GT, -1.1f, 0.5f),
3110                            Value(F, 0.2f, 1.5f), 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(refract)));
3111 
3112     // 8.5 Matrix Functions.
3113     // separate matrix tests?
3114     //    funcInfoGroups.push_back(
3115     //        BuiltinFuncGroup("matrix", "Matrix function tests.")
3116     //        << BuiltinFuncInfo("matrixCompMult", "matrixCompMult", M, ... )
3117     // );
3118 
3119     // 8.6 Vector Relational Functions.
3120     funcInfoGroups.push_back(
3121         BuiltinFuncGroup("float_compare", "Floating point comparison tests.")
3122         << BuiltinFuncInfo("lessThan", "lessThan", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f,
3123                            0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(lessThan))
3124         << BuiltinFuncInfo("lessThanEqual", "lessThanEqual", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f),
3125                            notUsed, 1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(lessThanEqual))
3126         << BuiltinFuncInfo("greaterThan", "greaterThan", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
3127                            1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(greaterThan))
3128         << BuiltinFuncInfo("greaterThanEqual", "greaterThanEqual", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f),
3129                            notUsed, 1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(greaterThanEqual))
3130         << BuiltinFuncInfo("equal", "equal", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
3131                            PRECMASK_ALL, FLOAT_VEC_FUNCS(equal))
3132         << BuiltinFuncInfo("notEqual", "notEqual", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f,
3133                            0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(notEqual)));
3134 
3135     funcInfoGroups.push_back(
3136         BuiltinFuncGroup("int_compare", "Integer comparison tests.")
3137         << BuiltinFuncInfo("lessThan", "lessThan", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed, 1.0f,
3138                            0.0f, PRECMASK_ALL, INT_VEC_FUNCS(lessThan))
3139         << BuiltinFuncInfo("lessThanEqual", "lessThanEqual", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f),
3140                            notUsed, 1.0f, 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(lessThanEqual))
3141         << BuiltinFuncInfo("greaterThan", "greaterThan", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed,
3142                            1.0f, 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(greaterThan))
3143         << BuiltinFuncInfo("greaterThanEqual", "greaterThanEqual", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f),
3144                            notUsed, 1.0f, 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(greaterThanEqual))
3145         << BuiltinFuncInfo("equal", "equal", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
3146                            PRECMASK_ALL, INT_VEC_FUNCS(equal))
3147         << BuiltinFuncInfo("notEqual", "notEqual", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed, 1.0f,
3148                            0.0f, PRECMASK_ALL, INT_VEC_FUNCS(notEqual)));
3149 
3150     funcInfoGroups.push_back(BuiltinFuncGroup("bool_compare", "Boolean comparison tests.")
3151                              << BuiltinFuncInfo("equal", "equal", BV, Value(BV, -5.2f, 4.9f), Value(BV, -5.0f, 5.0f),
3152                                                 notUsed, 1.0f, 0.0f, PRECMASK_NA, BOOL_VEC_FUNCS(equal))
3153                              << BuiltinFuncInfo("notEqual", "notEqual", BV, Value(BV, -5.2f, 4.9f),
3154                                                 Value(BV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_NA,
3155                                                 BOOL_VEC_FUNCS(notEqual))
3156                              << BuiltinFuncInfo("any", "any", B, Value(BV, -1.0f, 0.3f), notUsed, notUsed, 1.0f, 0.0f,
3157                                                 PRECMASK_NA, BOOL_VEC_FUNCS(any))
3158                              << BuiltinFuncInfo("all", "all", B, Value(BV, -0.3f, 1.0f), notUsed, notUsed, 1.0f, 0.0f,
3159                                                 PRECMASK_NA, BOOL_VEC_FUNCS(all))
3160                              << BuiltinFuncInfo("not", "not", BV, Value(BV, -1.0f, 1.0f), notUsed, notUsed, 1.0f, 0.0f,
3161                                                 PRECMASK_NA, BOOL_VEC_FUNCS(boolNot)));
3162 
3163     static const ShaderType s_shaderTypes[] = {SHADERTYPE_VERTEX, SHADERTYPE_FRAGMENT};
3164 
3165     static const DataType s_floatTypes[] = {TYPE_FLOAT, TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4};
3166 
3167     static const DataType s_intTypes[] = {TYPE_INT, TYPE_INT_VEC2, TYPE_INT_VEC3, TYPE_INT_VEC4};
3168 
3169     static const DataType s_uintTypes[] = {TYPE_UINT, TYPE_UINT_VEC2, TYPE_UINT_VEC3, TYPE_UINT_VEC4};
3170 
3171     static const DataType s_boolTypes[] = {TYPE_BOOL, TYPE_BOOL_VEC2, TYPE_BOOL_VEC3, TYPE_BOOL_VEC4};
3172 
3173     for (int outerGroupNdx = 0; outerGroupNdx < (int)funcInfoGroups.size(); outerGroupNdx++)
3174     {
3175         // Create outer group.
3176         const BuiltinFuncGroup &outerGroupInfo = funcInfoGroups[outerGroupNdx];
3177         TestCaseGroup *outerGroup = new TestCaseGroup(m_context, outerGroupInfo.name, outerGroupInfo.description);
3178         addChild(outerGroup);
3179 
3180         // Only create new group if name differs from previous one.
3181         TestCaseGroup *innerGroup = DE_NULL;
3182 
3183         for (int funcInfoNdx = 0; funcInfoNdx < (int)outerGroupInfo.funcInfos.size(); funcInfoNdx++)
3184         {
3185             const BuiltinFuncInfo &funcInfo = outerGroupInfo.funcInfos[funcInfoNdx];
3186             const char *shaderFuncName      = funcInfo.shaderFuncName;
3187             bool isBoolCase                 = (funcInfo.precisionMask == PRECMASK_NA);
3188             bool isBoolOut  = (funcInfo.outValue & (VALUE_BOOL | VALUE_BOOL_VEC | VALUE_BOOL_GENTYPE)) != 0;
3189             bool isIntOut   = (funcInfo.outValue & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
3190             bool isUintOut  = (funcInfo.outValue & (VALUE_UINT | VALUE_UINT_VEC | VALUE_UINT_GENTYPE)) != 0;
3191             bool isFloatOut = !isBoolOut && !isIntOut && !isUintOut;
3192 
3193             if (!innerGroup || (string(innerGroup->getName()) != funcInfo.caseName))
3194             {
3195                 string groupDesc = string("Built-in function ") + shaderFuncName + "() tests.";
3196                 innerGroup       = new TestCaseGroup(m_context, funcInfo.caseName, groupDesc.c_str());
3197                 outerGroup->addChild(innerGroup);
3198             }
3199 
3200             for (int inScalarSize = 1; inScalarSize <= 4; inScalarSize++)
3201             {
3202                 int outScalarSize    = ((funcInfo.outValue == VALUE_FLOAT) || (funcInfo.outValue == VALUE_BOOL)) ?
3203                                            1 :
3204                                            inScalarSize; // \todo [petri] Int.
3205                 DataType outDataType = isFloatOut ? s_floatTypes[outScalarSize - 1] :
3206                                        isIntOut   ? s_intTypes[outScalarSize - 1] :
3207                                        isUintOut  ? s_uintTypes[outScalarSize - 1] :
3208                                        isBoolOut  ? s_boolTypes[outScalarSize - 1] :
3209                                                     TYPE_LAST;
3210 
3211                 ShaderEvalFunc evalFunc = DE_NULL;
3212                 switch (inScalarSize)
3213                 {
3214                 case 1:
3215                     evalFunc = funcInfo.evalFuncScalar;
3216                     break;
3217                 case 2:
3218                     evalFunc = funcInfo.evalFuncVec2;
3219                     break;
3220                 case 3:
3221                     evalFunc = funcInfo.evalFuncVec3;
3222                     break;
3223                 case 4:
3224                     evalFunc = funcInfo.evalFuncVec4;
3225                     break;
3226                 default:
3227                     DE_ASSERT(false);
3228                 }
3229                 // Skip if no valid eval func.
3230                 // \todo [petri] Better check for V3 only etc. cases?
3231                 if (evalFunc == DE_NULL)
3232                     continue;
3233 
3234                 for (int precision = 0; precision < PRECISION_LAST; precision++)
3235                 {
3236                     if ((funcInfo.precisionMask & (1 << precision)) ||
3237                         (funcInfo.precisionMask == PRECMASK_NA &&
3238                          precision == PRECISION_MEDIUMP)) // use mediump interpolators for booleans
3239                     {
3240                         const char *precisionStr = getPrecisionName((Precision)precision);
3241                         string precisionPrefix   = isBoolCase ? "" : (string(precisionStr) + "_");
3242 
3243                         for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
3244                         {
3245                             ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
3246                             ShaderDataSpec shaderSpec;
3247                             const char *shaderTypeName = getShaderTypeName(shaderType);
3248                             bool isVertexCase          = (ShaderType)shaderType == SHADERTYPE_VERTEX;
3249                             bool isUnaryOp             = (funcInfo.input1.valueType == VALUE_NONE);
3250 
3251                             // \note Data type names will be added to description and name in a following loop.
3252                             string desc = string("Built-in function ") + shaderFuncName + "(";
3253                             string name = precisionPrefix;
3254 
3255                             // Generate shader op.
3256                             string shaderOp = "res = ";
3257 
3258                             // Setup shader data info.
3259                             shaderSpec.numInputs      = 0;
3260                             shaderSpec.precision      = isBoolCase ? PRECISION_LAST : (Precision)precision;
3261                             shaderSpec.output         = outDataType;
3262                             shaderSpec.resultScale    = funcInfo.resultScale;
3263                             shaderSpec.resultBias     = funcInfo.resultBias;
3264                             shaderSpec.referenceScale = funcInfo.referenceScale;
3265                             shaderSpec.referenceBias  = funcInfo.referenceBias;
3266 
3267                             if (funcInfo.type == OPERATOR)
3268                             {
3269                                 if (isUnaryOp && funcInfo.isUnaryPrefix)
3270                                     shaderOp += shaderFuncName;
3271                             }
3272                             else if (funcInfo.type == FUNCTION)
3273                                 shaderOp += string(shaderFuncName) + "(";
3274                             else // SIDE_EFFECT_OPERATOR
3275                                 shaderOp += "in0;\n\t";
3276 
3277                             for (int inputNdx = 0; inputNdx < MAX_INPUTS; inputNdx++)
3278                             {
3279                                 const Value &prevV = (inputNdx == 1) ? funcInfo.input0 :
3280                                                      (inputNdx == 2) ? funcInfo.input1 :
3281                                                                        funcInfo.input2;
3282                                 const Value &v     = (inputNdx == 0) ? funcInfo.input0 :
3283                                                      (inputNdx == 1) ? funcInfo.input1 :
3284                                                                        funcInfo.input2;
3285 
3286                                 if (v.valueType == VALUE_NONE)
3287                                     continue; // Skip unused input.
3288 
3289                                 int prevInScalarSize = isScalarType(prevV.valueType) ? 1 : inScalarSize;
3290                                 DataType prevInDataType =
3291                                     isFloatType(prevV.valueType) ? s_floatTypes[prevInScalarSize - 1] :
3292                                     isIntType(prevV.valueType)   ? s_intTypes[prevInScalarSize - 1] :
3293                                     isUintType(prevV.valueType)  ? s_uintTypes[prevInScalarSize - 1] :
3294                                     isBoolType(prevV.valueType)  ? s_boolTypes[prevInScalarSize - 1] :
3295                                                                    TYPE_LAST;
3296 
3297                                 int curInScalarSize    = isScalarType(v.valueType) ? 1 : inScalarSize;
3298                                 DataType curInDataType = isFloatType(v.valueType) ? s_floatTypes[curInScalarSize - 1] :
3299                                                          isIntType(v.valueType)   ? s_intTypes[curInScalarSize - 1] :
3300                                                          isUintType(v.valueType)  ? s_uintTypes[curInScalarSize - 1] :
3301                                                          isBoolType(v.valueType)  ? s_boolTypes[curInScalarSize - 1] :
3302                                                                                     TYPE_LAST;
3303 
3304                                 // Write input type(s) to case description and name.
3305 
3306                                 if (inputNdx > 0)
3307                                     desc += ", ";
3308 
3309                                 desc += getDataTypeName(curInDataType);
3310 
3311                                 if (inputNdx == 0 ||
3312                                     prevInDataType !=
3313                                         curInDataType) // \note Only write input type to case name if different from previous input type (avoid overly long names).
3314                                     name += string("") + getDataTypeName(curInDataType) + "_";
3315 
3316                                 // Generate op input source.
3317 
3318                                 if (funcInfo.type == OPERATOR || funcInfo.type == FUNCTION)
3319                                 {
3320                                     if (inputNdx != 0)
3321                                     {
3322                                         if (funcInfo.type == OPERATOR && !isUnaryOp)
3323                                             shaderOp += " " + string(shaderFuncName) + " ";
3324                                         else
3325                                             shaderOp += ", ";
3326                                     }
3327 
3328                                     shaderOp += "in" + de::toString(inputNdx);
3329 
3330                                     if (funcInfo.type == OPERATOR && isUnaryOp && !funcInfo.isUnaryPrefix)
3331                                         shaderOp += string(shaderFuncName);
3332                                 }
3333                                 else
3334                                 {
3335                                     DE_ASSERT(funcInfo.type == SIDE_EFFECT_OPERATOR);
3336 
3337                                     if (inputNdx != 0 || (isUnaryOp && funcInfo.isUnaryPrefix))
3338                                         shaderOp += string("") + (isUnaryOp ? "" : " ") + shaderFuncName +
3339                                                     (isUnaryOp ? "" : " ");
3340 
3341                                     shaderOp +=
3342                                         inputNdx == 0 ?
3343                                             "res" :
3344                                             "in" +
3345                                                 de::toString(
3346                                                     inputNdx); // \note in0 has already been assigned to res, so start from in1.
3347 
3348                                     if (isUnaryOp && !funcInfo.isUnaryPrefix)
3349                                         shaderOp += shaderFuncName;
3350                                 }
3351 
3352                                 // Fill in shader info.
3353                                 shaderSpec.inputs[shaderSpec.numInputs++] =
3354                                     ShaderValue(curInDataType, v.rangeMin, v.rangeMax);
3355                             }
3356 
3357                             if (funcInfo.type == FUNCTION)
3358                                 shaderOp += ")";
3359 
3360                             shaderOp += ";";
3361 
3362                             desc += ").";
3363                             name += shaderTypeName;
3364 
3365                             // Create the test case.
3366                             innerGroup->addChild(new ShaderOperatorCase(m_context, name.c_str(), desc.c_str(),
3367                                                                         isVertexCase, evalFunc, shaderOp, shaderSpec));
3368                         }
3369                     }
3370                 }
3371             }
3372         }
3373     }
3374 
3375     // The ?: selection operator.
3376 
3377     static const struct
3378     {
3379         DataType type; // The type of "Y" and "Z" operands in "X ? Y : Z" (X is always bool).
3380         ShaderEvalFunc evalFunc;
3381     } s_selectionInfo[] = {{TYPE_FLOAT, eval_selection_float},     {TYPE_FLOAT_VEC2, eval_selection_vec2},
3382                            {TYPE_FLOAT_VEC3, eval_selection_vec3}, {TYPE_FLOAT_VEC4, eval_selection_vec4},
3383                            {TYPE_INT, eval_selection_int},         {TYPE_INT_VEC2, eval_selection_ivec2},
3384                            {TYPE_INT_VEC3, eval_selection_ivec3},  {TYPE_INT_VEC4, eval_selection_ivec4},
3385                            {TYPE_UINT, eval_selection_uint},       {TYPE_UINT_VEC2, eval_selection_uvec2},
3386                            {TYPE_UINT_VEC3, eval_selection_uvec3}, {TYPE_UINT_VEC4, eval_selection_uvec4},
3387                            {TYPE_BOOL, eval_selection_bool},       {TYPE_BOOL_VEC2, eval_selection_bvec2},
3388                            {TYPE_BOOL_VEC3, eval_selection_bvec3}, {TYPE_BOOL_VEC4, eval_selection_bvec4}};
3389 
3390     TestCaseGroup *selectionGroup = new TestCaseGroup(m_context, "selection", "Selection operator tests");
3391     addChild(selectionGroup);
3392 
3393     for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_selectionInfo); typeNdx++)
3394     {
3395         DataType curType        = s_selectionInfo[typeNdx].type;
3396         ShaderEvalFunc evalFunc = s_selectionInfo[typeNdx].evalFunc;
3397         bool isBoolCase         = isDataTypeBoolOrBVec(curType);
3398         bool isFloatCase        = isDataTypeFloatOrVec(curType);
3399         bool isIntCase          = isDataTypeIntOrIVec(curType);
3400         bool isUintCase         = isDataTypeUintOrUVec(curType);
3401         const char *dataTypeStr = getDataTypeName(curType);
3402 
3403         DE_ASSERT(isBoolCase || isFloatCase || isIntCase || isUintCase);
3404         DE_UNREF(isIntCase);
3405 
3406         for (int precision = 0; precision < (int)PRECISION_LAST; precision++)
3407         {
3408             if (isBoolCase && precision != PRECISION_MEDIUMP) // Use mediump interpolators for booleans.
3409                 continue;
3410 
3411             const char *precisionStr = getPrecisionName((Precision)precision);
3412             string precisionPrefix   = isBoolCase ? "" : (string(precisionStr) + "_");
3413 
3414             for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
3415             {
3416                 ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
3417                 ShaderDataSpec shaderSpec;
3418                 const char *shaderTypeName = getShaderTypeName(shaderType);
3419                 bool isVertexCase          = (ShaderType)shaderType == SHADERTYPE_VERTEX;
3420 
3421                 string name = precisionPrefix + dataTypeStr + "_" + shaderTypeName;
3422 
3423                 shaderSpec.numInputs      = 3;
3424                 shaderSpec.precision      = isBoolCase ? PRECISION_LAST : (Precision)precision;
3425                 shaderSpec.output         = curType;
3426                 shaderSpec.resultScale    = isBoolCase ? 1.0f : isFloatCase ? 0.5f : isUintCase ? 0.5f : 0.1f;
3427                 shaderSpec.resultBias     = isBoolCase ? 0.0f : isFloatCase ? 0.5f : isUintCase ? 0.0f : 0.5f;
3428                 shaderSpec.referenceScale = shaderSpec.resultScale;
3429                 shaderSpec.referenceBias  = shaderSpec.resultBias;
3430 
3431                 float rangeMin = isBoolCase ? -1.0f : isFloatCase ? -1.0f : isUintCase ? 0.0f : -5.0f;
3432                 float rangeMax = isBoolCase ? 1.0f : isFloatCase ? 1.0f : isUintCase ? 2.0f : 5.0f;
3433 
3434                 shaderSpec.inputs[0] = ShaderValue(TYPE_BOOL, -1.0f, 1.0f);
3435                 shaderSpec.inputs[1] = ShaderValue(curType, rangeMin, rangeMax);
3436                 shaderSpec.inputs[2] = ShaderValue(curType, rangeMin, rangeMax);
3437 
3438                 selectionGroup->addChild(new ShaderOperatorCase(m_context, name.c_str(), "", isVertexCase, evalFunc,
3439                                                                 "res = in0 ? in1 : in2;", shaderSpec));
3440             }
3441         }
3442     }
3443 
3444     // The sequence operator (comma).
3445 
3446     TestCaseGroup *sequenceGroup = new TestCaseGroup(m_context, "sequence", "Sequence operator tests");
3447     addChild(sequenceGroup);
3448 
3449     TestCaseGroup *sequenceNoSideEffGroup =
3450         new TestCaseGroup(m_context, "no_side_effects", "Sequence tests without side-effects");
3451     TestCaseGroup *sequenceSideEffGroup =
3452         new TestCaseGroup(m_context, "side_effects", "Sequence tests with side-effects");
3453     sequenceGroup->addChild(sequenceNoSideEffGroup);
3454     sequenceGroup->addChild(sequenceSideEffGroup);
3455 
3456     static const struct
3457     {
3458         bool containsSideEffects;
3459         const char *caseName;
3460         const char *expressionStr;
3461         int numInputs;
3462         DataType inputTypes[MAX_INPUTS];
3463         DataType resultType;
3464         ShaderEvalFunc evalFunc;
3465     } s_sequenceCases[] = {{false,
3466                             "vec4",
3467                             "in0, in2 + in1, in1 + in0",
3468                             3,
3469                             {TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4},
3470                             TYPE_FLOAT_VEC4,
3471                             evalSequenceNoSideEffCase0},
3472                            {false,
3473                             "float_uint",
3474                             "in0 + in2, in1 + in1",
3475                             3,
3476                             {TYPE_FLOAT, TYPE_UINT, TYPE_FLOAT},
3477                             TYPE_UINT,
3478                             evalSequenceNoSideEffCase1},
3479                            {false,
3480                             "bool_vec2",
3481                             "in0 && in1, in0, ivec2(vec2(in0) + in2)",
3482                             3,
3483                             {TYPE_BOOL, TYPE_BOOL, TYPE_FLOAT_VEC2},
3484                             TYPE_INT_VEC2,
3485                             evalSequenceNoSideEffCase2},
3486                            {false,
3487                             "vec4_ivec4_bvec4",
3488                             "in0 + vec4(in1), in2, in1",
3489                             3,
3490                             {TYPE_FLOAT_VEC4, TYPE_INT_VEC4, TYPE_BOOL_VEC4},
3491                             TYPE_INT_VEC4,
3492                             evalSequenceNoSideEffCase3},
3493 
3494                            {true,
3495                             "vec4",
3496                             "in0++, in1 = in0 + in2, in2 = in1",
3497                             3,
3498                             {TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4},
3499                             TYPE_FLOAT_VEC4,
3500                             evalSequenceSideEffCase0},
3501                            {true,
3502                             "float_uint",
3503                             "in1++, in0 = float(in1), in1 = uint(in0 + in2)",
3504                             3,
3505                             {TYPE_FLOAT, TYPE_UINT, TYPE_FLOAT},
3506                             TYPE_UINT,
3507                             evalSequenceSideEffCase1},
3508                            {true,
3509                             "bool_vec2",
3510                             "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)",
3511                             3,
3512                             {TYPE_BOOL, TYPE_BOOL, TYPE_FLOAT_VEC2},
3513                             TYPE_INT_VEC2,
3514                             evalSequenceSideEffCase2},
3515                            {true,
3516                             "vec4_ivec4_bvec4",
3517                             "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++",
3518                             3,
3519                             {TYPE_FLOAT_VEC4, TYPE_INT_VEC4, TYPE_BOOL_VEC4},
3520                             TYPE_INT_VEC4,
3521                             evalSequenceSideEffCase3}};
3522 
3523     for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_sequenceCases); caseNdx++)
3524     {
3525         for (int precision = 0; precision < (int)PRECISION_LAST; precision++)
3526         {
3527             for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
3528             {
3529                 ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
3530                 ShaderDataSpec shaderSpec;
3531                 const char *shaderTypeName = getShaderTypeName(shaderType);
3532                 bool isVertexCase          = (ShaderType)shaderType == SHADERTYPE_VERTEX;
3533 
3534                 string name = string("") + getPrecisionName((Precision)precision) + "_" +
3535                               s_sequenceCases[caseNdx].caseName + "_" + shaderTypeName;
3536 
3537                 shaderSpec.numInputs      = s_sequenceCases[caseNdx].numInputs;
3538                 shaderSpec.precision      = (Precision)precision;
3539                 shaderSpec.output         = s_sequenceCases[caseNdx].resultType;
3540                 shaderSpec.resultScale    = 0.5f;
3541                 shaderSpec.resultBias     = 0.0f;
3542                 shaderSpec.referenceScale = shaderSpec.resultScale;
3543                 shaderSpec.referenceBias  = shaderSpec.resultBias;
3544 
3545                 for (int inputNdx = 0; inputNdx < s_sequenceCases[caseNdx].numInputs; inputNdx++)
3546                 {
3547                     DataType type  = s_sequenceCases[caseNdx].inputTypes[inputNdx];
3548                     float rangeMin = isDataTypeFloatOrVec(type) ? -0.5f :
3549                                      isDataTypeIntOrIVec(type)  ? -2.0f :
3550                                      isDataTypeUintOrUVec(type) ? 0.0f :
3551                                                                   -1.0f;
3552                     float rangeMax = isDataTypeFloatOrVec(type) ? 0.5f :
3553                                      isDataTypeIntOrIVec(type)  ? 2.0f :
3554                                      isDataTypeUintOrUVec(type) ? 2.0f :
3555                                                                   1.0f;
3556 
3557                     shaderSpec.inputs[inputNdx] = ShaderValue(type, rangeMin, rangeMax);
3558                 }
3559 
3560                 string expression = string("res = (") + s_sequenceCases[caseNdx].expressionStr + ");";
3561 
3562                 TestCaseGroup *group =
3563                     s_sequenceCases[caseNdx].containsSideEffects ? sequenceSideEffGroup : sequenceNoSideEffGroup;
3564                 group->addChild(new ShaderOperatorCase(m_context, name.c_str(), "", isVertexCase,
3565                                                        s_sequenceCases[caseNdx].evalFunc, expression.c_str(),
3566                                                        shaderSpec));
3567             }
3568         }
3569     }
3570 }
3571 
3572 } // namespace Functional
3573 } // namespace gles3
3574 } // namespace deqp
3575