1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Shader operators tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktShaderRenderOperatorTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "deStringUtil.hpp"
30 
31 #include <limits>
32 
33 using namespace tcu;
34 using namespace glu;
35 
36 namespace vkt
37 {
38 namespace sr
39 {
40 namespace
41 {
42 
43 using de::clamp;
44 using de::max;
45 using de::min;
46 
logicalAnd(bool a,bool b)47 inline bool logicalAnd(bool a, bool b)
48 {
49     return (a && b);
50 }
logicalOr(bool a,bool b)51 inline bool logicalOr(bool a, bool b)
52 {
53     return (a || b);
54 }
logicalXor(bool a,bool b)55 inline bool logicalXor(bool a, bool b)
56 {
57     return (a != b);
58 }
59 
60 // \note stdlib.h defines div() that is not compatible with the macros.
61 template <typename T>
div(T a,T b)62 inline T div(T a, T b)
63 {
64     return a / b;
65 }
66 
67 template <typename T>
leftShift(T value,int amount)68 inline T leftShift(T value, int amount)
69 {
70     return value << amount;
71 }
72 
rightShift(uint32_t value,int amount)73 inline uint32_t rightShift(uint32_t value, int amount)
74 {
75     return value >> amount;
76 }
rightShift(int value,int amount)77 inline int rightShift(int value, int amount)
78 {
79     return (value >> amount) | (value >= 0 ? 0 : ~(~0U >> amount));
80 } // \note Arithmetic shift.
81 
82 template <typename T, int Size>
leftShift(const Vector<T,Size> & value,const Vector<int,Size> & amount)83 Vector<T, Size> leftShift(const Vector<T, Size> &value, const Vector<int, Size> &amount)
84 {
85     Vector<T, Size> result;
86     for (int i = 0; i < Size; i++)
87         result[i] = leftShift(value[i], amount[i]);
88     return result;
89 }
90 
91 template <typename T, int Size>
rightShift(const Vector<T,Size> & value,const Vector<int,Size> & amount)92 Vector<T, Size> rightShift(const Vector<T, Size> &value, const Vector<int, Size> &amount)
93 {
94     Vector<T, Size> result;
95     for (int i = 0; i < Size; i++)
96         result[i] = rightShift(value[i], amount[i]);
97     return result;
98 }
99 
100 template <typename T, int Size>
leftShiftVecScalar(const Vector<T,Size> & value,int amount)101 Vector<T, Size> leftShiftVecScalar(const Vector<T, Size> &value, int amount)
102 {
103     return leftShift(value, Vector<int, Size>(amount));
104 }
105 template <typename T, int Size>
rightShiftVecScalar(const Vector<T,Size> & value,int amount)106 Vector<T, Size> rightShiftVecScalar(const Vector<T, Size> &value, int amount)
107 {
108     return rightShift(value, Vector<int, Size>(amount));
109 }
110 
111 template <typename T, int Size>
minVecScalar(const Vector<T,Size> & v,T s)112 inline Vector<T, Size> minVecScalar(const Vector<T, Size> &v, T s)
113 {
114     Vector<T, Size> res;
115     for (int i = 0; i < Size; i++)
116         res[i] = min(v[i], s);
117     return res;
118 }
119 
120 template <typename T, int Size>
maxVecScalar(const Vector<T,Size> & v,T s)121 inline Vector<T, Size> maxVecScalar(const Vector<T, Size> &v, T s)
122 {
123     Vector<T, Size> res;
124     for (int i = 0; i < Size; i++)
125         res[i] = max(v[i], s);
126     return res;
127 }
128 
129 template <typename T, int Size>
clampVecScalarScalar(const Vector<T,Size> & v,T s0,T s1)130 inline Vector<T, Size> clampVecScalarScalar(const Vector<T, Size> &v, T s0, T s1)
131 {
132     Vector<T, Size> res;
133     for (int i = 0; i < Size; i++)
134         res[i] = clamp(v[i], s0, s1);
135     return res;
136 }
137 
138 template <typename T, int Size>
mixVecVecScalar(const Vector<T,Size> & v0,const Vector<T,Size> & v1,T s)139 inline Vector<T, Size> mixVecVecScalar(const Vector<T, Size> &v0, const Vector<T, Size> &v1, T s)
140 {
141     Vector<T, Size> res;
142     for (int i = 0; i < Size; i++)
143         res[i] = mix(v0[i], v1[i], s);
144     return res;
145 }
146 
147 template <typename T, int Size>
stepScalarVec(T s,const Vector<T,Size> & v)148 inline Vector<T, Size> stepScalarVec(T s, const Vector<T, Size> &v)
149 {
150     Vector<T, Size> res;
151     for (int i = 0; i < Size; i++)
152         res[i] = step(s, v[i]);
153     return res;
154 }
155 
156 template <typename T, int Size>
smoothStepScalarScalarVec(T s0,T s1,const Vector<T,Size> & v)157 inline Vector<T, Size> smoothStepScalarScalarVec(T s0, T s1, const Vector<T, Size> &v)
158 {
159     Vector<T, Size> res;
160     for (int i = 0; i < Size; i++)
161         res[i] = smoothStep(s0, s1, v[i]);
162     return res;
163 }
164 
addOne(int v)165 inline int addOne(int v)
166 {
167     return v + 1;
168 }
subOne(int v)169 inline int subOne(int v)
170 {
171     return v - 1;
172 }
addOne(uint32_t v)173 inline uint32_t addOne(uint32_t v)
174 {
175     return v + 1;
176 }
subOne(uint32_t v)177 inline uint32_t subOne(uint32_t v)
178 {
179     return v - 1;
180 }
181 
182 template <int Size>
addOne(const Vector<float,Size> & v)183 inline Vector<float, Size> addOne(const Vector<float, Size> &v)
184 {
185     return v + 1.0f;
186 }
187 template <int Size>
subOne(const Vector<float,Size> & v)188 inline Vector<float, Size> subOne(const Vector<float, Size> &v)
189 {
190     return v - 1.0f;
191 }
192 template <int Size>
addOne(const Vector<int,Size> & v)193 inline Vector<int, Size> addOne(const Vector<int, Size> &v)
194 {
195     return v + 1;
196 }
197 template <int Size>
subOne(const Vector<int,Size> & v)198 inline Vector<int, Size> subOne(const Vector<int, Size> &v)
199 {
200     return v - 1;
201 }
202 template <int Size>
addOne(const Vector<uint32_t,Size> & v)203 inline Vector<uint32_t, Size> addOne(const Vector<uint32_t, Size> &v)
204 {
205     return v + 1U;
206 }
207 template <int Size>
subOne(const Vector<uint32_t,Size> & v)208 inline Vector<uint32_t, Size> subOne(const Vector<uint32_t, Size> &v)
209 {
210     return (v.asInt() - 1).asUint();
211 }
212 
213 template <typename T>
selection(bool cond,T a,T b)214 inline T selection(bool cond, T a, T b)
215 {
216     return cond ? a : b;
217 }
218 
219 // Vec-scalar and scalar-vec binary operators.
220 
221 // \note This one is done separately due to how the overloaded minus operator is implemented for vector-scalar operands.
222 template <int Size>
subVecScalar(const Vector<uint32_t,Size> & v,uint32_t s)223 inline Vector<uint32_t, Size> subVecScalar(const Vector<uint32_t, Size> &v, uint32_t s)
224 {
225     return (v.asInt() - (int)s).asUint();
226 }
227 
228 template <typename T, int Size>
addVecScalar(const Vector<T,Size> & v,T s)229 inline Vector<T, Size> addVecScalar(const Vector<T, Size> &v, T s)
230 {
231     return v + s;
232 }
233 template <typename T, int Size>
subVecScalar(const Vector<T,Size> & v,T s)234 inline Vector<T, Size> subVecScalar(const Vector<T, Size> &v, T s)
235 {
236     return v - s;
237 }
238 template <typename T, int Size>
mulVecScalar(const Vector<T,Size> & v,T s)239 inline Vector<T, Size> mulVecScalar(const Vector<T, Size> &v, T s)
240 {
241     return v * s;
242 }
243 template <typename T, int Size>
divVecScalar(const Vector<T,Size> & v,T s)244 inline Vector<T, Size> divVecScalar(const Vector<T, Size> &v, T s)
245 {
246     return v / s;
247 }
248 template <typename T, int Size>
modVecScalar(const Vector<T,Size> & v,T s)249 inline Vector<T, Size> modVecScalar(const Vector<T, Size> &v, T s)
250 {
251     return mod(v, Vector<T, Size>(s));
252 }
253 template <typename T, int Size>
bitwiseAndVecScalar(const Vector<T,Size> & v,T s)254 inline Vector<T, Size> bitwiseAndVecScalar(const Vector<T, Size> &v, T s)
255 {
256     return bitwiseAnd(v, Vector<T, Size>(s));
257 }
258 template <typename T, int Size>
bitwiseOrVecScalar(const Vector<T,Size> & v,T s)259 inline Vector<T, Size> bitwiseOrVecScalar(const Vector<T, Size> &v, T s)
260 {
261     return bitwiseOr(v, Vector<T, Size>(s));
262 }
263 template <typename T, int Size>
bitwiseXorVecScalar(const Vector<T,Size> & v,T s)264 inline Vector<T, Size> bitwiseXorVecScalar(const Vector<T, Size> &v, T s)
265 {
266     return bitwiseXor(v, Vector<T, Size>(s));
267 }
268 
269 template <typename T, int Size>
addScalarVec(T s,const Vector<T,Size> & v)270 inline Vector<T, Size> addScalarVec(T s, const Vector<T, Size> &v)
271 {
272     return s + v;
273 }
274 template <typename T, int Size>
subScalarVec(T s,const Vector<T,Size> & v)275 inline Vector<T, Size> subScalarVec(T s, const Vector<T, Size> &v)
276 {
277     return s - v;
278 }
279 template <typename T, int Size>
mulScalarVec(T s,const Vector<T,Size> & v)280 inline Vector<T, Size> mulScalarVec(T s, const Vector<T, Size> &v)
281 {
282     return s * v;
283 }
284 template <typename T, int Size>
divScalarVec(T s,const Vector<T,Size> & v)285 inline Vector<T, Size> divScalarVec(T s, const Vector<T, Size> &v)
286 {
287     return s / v;
288 }
289 template <typename T, int Size>
modScalarVec(T s,const Vector<T,Size> & v)290 inline Vector<T, Size> modScalarVec(T s, const Vector<T, Size> &v)
291 {
292     return mod(Vector<T, Size>(s), v);
293 }
294 template <typename T, int Size>
bitwiseAndScalarVec(T s,const Vector<T,Size> & v)295 inline Vector<T, Size> bitwiseAndScalarVec(T s, const Vector<T, Size> &v)
296 {
297     return bitwiseAnd(Vector<T, Size>(s), v);
298 }
299 template <typename T, int Size>
bitwiseOrScalarVec(T s,const Vector<T,Size> & v)300 inline Vector<T, Size> bitwiseOrScalarVec(T s, const Vector<T, Size> &v)
301 {
302     return bitwiseOr(Vector<T, Size>(s), v);
303 }
304 template <typename T, int Size>
bitwiseXorScalarVec(T s,const Vector<T,Size> & v)305 inline Vector<T, Size> bitwiseXorScalarVec(T s, const Vector<T, Size> &v)
306 {
307     return bitwiseXor(Vector<T, Size>(s), v);
308 }
309 
310 // Reference functions for specific sequence operations for the sequence operator tests.
311 
312 // Reference for expression "in0, in2 + in1, in1 + in0"
sequenceNoSideEffCase0(const Vec4 & in0,const Vec4 & in1,const Vec4 & in2)313 inline Vec4 sequenceNoSideEffCase0(const Vec4 &in0, const Vec4 &in1, const Vec4 &in2)
314 {
315     DE_UNREF(in2);
316     return in1 + in0;
317 }
318 // Reference for expression "in0, in2 + in1, in1 + in0"
sequenceNoSideEffCase1(float in0,uint32_t in1,float in2)319 inline uint32_t sequenceNoSideEffCase1(float in0, uint32_t in1, float in2)
320 {
321     DE_UNREF(in0);
322     DE_UNREF(in2);
323     return in1 + in1;
324 }
325 // Reference for expression "in0 && in1, in0, ivec2(vec2(in0) + in2)"
sequenceNoSideEffCase2(bool in0,bool in1,const Vec2 & in2)326 inline IVec2 sequenceNoSideEffCase2(bool in0, bool in1, const Vec2 &in2)
327 {
328     DE_UNREF(in1);
329     return IVec2((int)((float)in0 + in2.x()), (int)((float)in0 + in2.y()));
330 }
331 // Reference for expression "in0 + vec4(in1), in2, in1"
sequenceNoSideEffCase3(const Vec4 & in0,const IVec4 & in1,const BVec4 & in2)332 inline IVec4 sequenceNoSideEffCase3(const Vec4 &in0, const IVec4 &in1, const BVec4 &in2)
333 {
334     DE_UNREF(in0);
335     DE_UNREF(in2);
336     return in1;
337 }
338 // Reference for expression "in0++, in1 = in0 + in2, in2 = in1"
sequenceSideEffCase0(const Vec4 & in0,const Vec4 & in1,const Vec4 & in2)339 inline Vec4 sequenceSideEffCase0(const Vec4 &in0, const Vec4 &in1, const Vec4 &in2)
340 {
341     DE_UNREF(in1);
342     return in0 + 1.0f + in2;
343 }
344 // Reference for expression "in1++, in0 = float(in1), in1 = uint(in0 + in2)"
sequenceSideEffCase1(float in0,uint32_t in1,float in2)345 inline uint32_t sequenceSideEffCase1(float in0, uint32_t in1, float in2)
346 {
347     DE_UNREF(in0);
348     return (uint32_t)(float(in1) + 1.0f + in2);
349 }
350 // Reference for expression "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)"
sequenceSideEffCase2(bool in0,bool in1,const Vec2 & in2)351 inline IVec2 sequenceSideEffCase2(bool in0, bool in1, const Vec2 &in2)
352 {
353     DE_UNREF(in1);
354     return (in2 + Vec2(1.0f) + Vec2((float)in0)).asInt();
355 }
356 // Reference for expression "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++"
sequenceSideEffCase3(const Vec4 & in0,const IVec4 & in1,const BVec4 & in2)357 inline IVec4 sequenceSideEffCase3(const Vec4 &in0, const IVec4 &in1, const BVec4 &in2)
358 {
359     return in1 + (in0 + Vec4((float)in2.x(), (float)in2.y(), (float)in2.z(), (float)in2.w())).asInt();
360 }
361 
362 // ShaderEvalFunc-type wrappers for the above functions.
evalSequenceNoSideEffCase0(ShaderEvalContext & ctx)363 void evalSequenceNoSideEffCase0(ShaderEvalContext &ctx)
364 {
365     ctx.color = sequenceNoSideEffCase0(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0),
366                                        ctx.in[2].swizzle(0, 3, 2, 1));
367 }
evalSequenceNoSideEffCase1(ShaderEvalContext & ctx)368 void evalSequenceNoSideEffCase1(ShaderEvalContext &ctx)
369 {
370     ctx.color.x() = (float)sequenceNoSideEffCase1(ctx.in[0].z(), (uint32_t)ctx.in[1].x(), ctx.in[2].y());
371 }
evalSequenceNoSideEffCase2(ShaderEvalContext & ctx)372 void evalSequenceNoSideEffCase2(ShaderEvalContext &ctx)
373 {
374     ctx.color.yz() =
375         sequenceNoSideEffCase2(ctx.in[0].z() > 0.0f, ctx.in[1].x() > 0.0f, ctx.in[2].swizzle(2, 1)).asFloat();
376 }
evalSequenceNoSideEffCase3(ShaderEvalContext & ctx)377 void evalSequenceNoSideEffCase3(ShaderEvalContext &ctx)
378 {
379     ctx.color = sequenceNoSideEffCase3(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0).asInt(),
380                                        greaterThan(ctx.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f)))
381                     .asFloat();
382 }
evalSequenceSideEffCase0(ShaderEvalContext & ctx)383 void evalSequenceSideEffCase0(ShaderEvalContext &ctx)
384 {
385     ctx.color = sequenceSideEffCase0(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0),
386                                      ctx.in[2].swizzle(0, 3, 2, 1));
387 }
evalSequenceSideEffCase1(ShaderEvalContext & ctx)388 void evalSequenceSideEffCase1(ShaderEvalContext &ctx)
389 {
390     ctx.color.x() = (float)sequenceSideEffCase1(ctx.in[0].z(), (uint32_t)ctx.in[1].x(), ctx.in[2].y());
391 }
evalSequenceSideEffCase2(ShaderEvalContext & ctx)392 void evalSequenceSideEffCase2(ShaderEvalContext &ctx)
393 {
394     ctx.color.yz() =
395         sequenceSideEffCase2(ctx.in[0].z() > 0.0f, ctx.in[1].x() > 0.0f, ctx.in[2].swizzle(2, 1)).asFloat();
396 }
evalSequenceSideEffCase3(ShaderEvalContext & ctx)397 void evalSequenceSideEffCase3(ShaderEvalContext &ctx)
398 {
399     ctx.color = sequenceSideEffCase3(ctx.in[0].swizzle(1, 2, 3, 0), ctx.in[1].swizzle(3, 2, 1, 0).asInt(),
400                                      greaterThan(ctx.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f)))
401                     .asFloat();
402 }
403 
stringJoin(const std::vector<std::string> & elems,const std::string & delim)404 static std::string stringJoin(const std::vector<std::string> &elems, const std::string &delim)
405 {
406     std::string result;
407     for (int i = 0; i < (int)elems.size(); i++)
408         result += (i > 0 ? delim : "") + elems[i];
409     return result;
410 }
411 
twoValuedVec4(const std::string & first,const std::string & second,const BVec4 & firstMask)412 static std::string twoValuedVec4(const std::string &first, const std::string &second, const BVec4 &firstMask)
413 {
414     std::vector<std::string> elems(4);
415     for (int i = 0; i < 4; i++)
416         elems[i] = firstMask[i] ? first : second;
417 
418     return "vec4(" + stringJoin(elems, ", ") + ")";
419 }
420 
421 enum
422 {
423     MAX_INPUTS = 3
424 };
425 
426 enum PrecisionMask
427 {
428     PRECMASK_NA      = 0, //!< Precision not applicable (booleans)
429     PRECMASK_MEDIUMP = (1 << PRECISION_MEDIUMP),
430     PRECMASK_HIGHP   = (1 << PRECISION_HIGHP),
431 
432     PRECMASK_ALL = PRECMASK_MEDIUMP | PRECMASK_HIGHP
433 };
434 
435 enum ValueType
436 {
437     VALUE_NONE          = 0,
438     VALUE_FLOAT         = (1 << 0),  // float scalar
439     VALUE_FLOAT_VEC     = (1 << 1),  // float vector
440     VALUE_FLOAT_GENTYPE = (1 << 2),  // float scalar/vector
441     VALUE_VEC3          = (1 << 3),  // vec3 only
442     VALUE_MATRIX        = (1 << 4),  // matrix
443     VALUE_BOOL          = (1 << 5),  // boolean scalar
444     VALUE_BOOL_VEC      = (1 << 6),  // boolean vector
445     VALUE_BOOL_GENTYPE  = (1 << 7),  // boolean scalar/vector
446     VALUE_INT           = (1 << 8),  // int scalar
447     VALUE_INT_VEC       = (1 << 9),  // int vector
448     VALUE_INT_GENTYPE   = (1 << 10), // int scalar/vector
449     VALUE_UINT          = (1 << 11), // uint scalar
450     VALUE_UINT_VEC      = (1 << 12), // uint vector
451     VALUE_UINT_GENTYPE  = (1 << 13), // uint scalar/vector
452 
453     // Shorthands.
454     F   = VALUE_FLOAT,
455     FV  = VALUE_FLOAT_VEC,
456     GT  = VALUE_FLOAT_GENTYPE,
457     V3  = VALUE_VEC3,
458     M   = VALUE_MATRIX,
459     B   = VALUE_BOOL,
460     BV  = VALUE_BOOL_VEC,
461     BGT = VALUE_BOOL_GENTYPE,
462     I   = VALUE_INT,
463     IV  = VALUE_INT_VEC,
464     IGT = VALUE_INT_GENTYPE,
465     U   = VALUE_UINT,
466     UV  = VALUE_UINT_VEC,
467     UGT = VALUE_UINT_GENTYPE
468 };
469 
isScalarType(ValueType type)470 static inline bool isScalarType(ValueType type)
471 {
472     return type == VALUE_FLOAT || type == VALUE_BOOL || type == VALUE_INT || type == VALUE_UINT;
473 }
474 
isFloatType(ValueType type)475 static inline bool isFloatType(ValueType type)
476 {
477     return (type & (VALUE_FLOAT | VALUE_FLOAT_VEC | VALUE_FLOAT_GENTYPE)) != 0;
478 }
479 
isIntType(ValueType type)480 static inline bool isIntType(ValueType type)
481 {
482     return (type & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
483 }
484 
isUintType(ValueType type)485 static inline bool isUintType(ValueType type)
486 {
487     return (type & (VALUE_UINT | VALUE_UINT_VEC | VALUE_UINT_GENTYPE)) != 0;
488 }
489 
isBoolType(ValueType type)490 static inline bool isBoolType(ValueType type)
491 {
492     return (type & (VALUE_BOOL | VALUE_BOOL_VEC | VALUE_BOOL_GENTYPE)) != 0;
493 }
494 
495 struct Value
496 {
Valuevkt::sr::__anoncb2548460111::Value497     Value(ValueType valueType_, const float rangeMin_, const float rangeMax_)
498         : valueType(valueType_)
499         , rangeMin(rangeMin_)
500         , rangeMax(rangeMax_)
501     {
502     }
503 
504     ValueType valueType;
505     float rangeMin;
506     float rangeMax;
507 };
508 
509 enum OperationType
510 {
511     FUNCTION = 0,
512     OPERATOR,
513     SIDE_EFFECT_OPERATOR // Test the side-effect (as opposed to the result) of a side-effect operator.
514 };
515 
516 struct BuiltinFuncInfo
517 {
BuiltinFuncInfovkt::sr::__anoncb2548460111::BuiltinFuncInfo518     BuiltinFuncInfo(const char *caseName_, const char *shaderFuncName_, ValueType outValue_, Value input0_,
519                     Value input1_, Value input2_, const float resultScale_, const float resultBias_,
520                     uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_,
521                     ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_, OperationType type_ = FUNCTION,
522                     bool isUnaryPrefix_ = true)
523         : caseName(caseName_)
524         , shaderFuncName(shaderFuncName_)
525         , outValue(outValue_)
526         , input0(input0_)
527         , input1(input1_)
528         , input2(input2_)
529         , resultScale(resultScale_)
530         , resultBias(resultBias_)
531         , referenceScale(resultScale_)
532         , referenceBias(resultBias_)
533         , precisionMask(precisionMask_)
534         , evalFuncScalar(evalFuncScalar_)
535         , evalFuncVec2(evalFuncVec2_)
536         , evalFuncVec3(evalFuncVec3_)
537         , evalFuncVec4(evalFuncVec4_)
538         , type(type_)
539         , isUnaryPrefix(isUnaryPrefix_)
540     {
541     }
542 
BuiltinFuncInfovkt::sr::__anoncb2548460111::BuiltinFuncInfo543     BuiltinFuncInfo(const char *caseName_, const char *shaderFuncName_, ValueType outValue_, Value input0_,
544                     Value input1_, Value input2_, const float resultScale_, const float resultBias_,
545                     const float referenceScale_, const float referenceBias_, uint32_t precisionMask_,
546                     ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
547                     ShaderEvalFunc evalFuncVec4_, OperationType type_ = FUNCTION, bool isUnaryPrefix_ = true)
548         : caseName(caseName_)
549         , shaderFuncName(shaderFuncName_)
550         , outValue(outValue_)
551         , input0(input0_)
552         , input1(input1_)
553         , input2(input2_)
554         , resultScale(resultScale_)
555         , resultBias(resultBias_)
556         , referenceScale(referenceScale_)
557         , referenceBias(referenceBias_)
558         , precisionMask(precisionMask_)
559         , evalFuncScalar(evalFuncScalar_)
560         , evalFuncVec2(evalFuncVec2_)
561         , evalFuncVec3(evalFuncVec3_)
562         , evalFuncVec4(evalFuncVec4_)
563         , type(type_)
564         , isUnaryPrefix(isUnaryPrefix_)
565     {
566     }
567 
568     const char *caseName;       //!< Name of case.
569     const char *shaderFuncName; //!< Name in shading language.
570     ValueType outValue;
571     Value input0;
572     Value input1;
573     Value input2;
574     float resultScale;
575     float resultBias;
576     float referenceScale;
577     float referenceBias;
578     uint32_t precisionMask;
579     ShaderEvalFunc evalFuncScalar;
580     ShaderEvalFunc evalFuncVec2;
581     ShaderEvalFunc evalFuncVec3;
582     ShaderEvalFunc evalFuncVec4;
583     OperationType type;
584     bool isUnaryPrefix; //!< Whether a unary operator is a prefix operator; redundant unless unary.
585 };
586 
BuiltinOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,const float resultScale_,const float resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)587 static inline BuiltinFuncInfo BuiltinOperInfo(const char *caseName_, const char *shaderFuncName_, ValueType outValue_,
588                                               Value input0_, Value input1_, Value input2_, const float resultScale_,
589                                               const float resultBias_, uint32_t precisionMask_,
590                                               ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_,
591                                               ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
592 {
593     return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
594                            resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_,
595                            evalFuncVec4_, OPERATOR);
596 }
597 
598 // For postfix (unary) operators.
BuiltinPostOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,const float resultScale_,const float resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)599 static inline BuiltinFuncInfo BuiltinPostOperInfo(const char *caseName_, const char *shaderFuncName_,
600                                                   ValueType outValue_, Value input0_, Value input1_, Value input2_,
601                                                   const float resultScale_, const float resultBias_,
602                                                   uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_,
603                                                   ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
604                                                   ShaderEvalFunc evalFuncVec4_)
605 {
606     return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
607                            resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_,
608                            evalFuncVec4_, OPERATOR, false);
609 }
610 
BuiltinSideEffOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,const float resultScale_,const float resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)611 static inline BuiltinFuncInfo BuiltinSideEffOperInfo(const char *caseName_, const char *shaderFuncName_,
612                                                      ValueType outValue_, Value input0_, Value input1_, Value input2_,
613                                                      const float resultScale_, const float resultBias_,
614                                                      uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_,
615                                                      ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
616                                                      ShaderEvalFunc evalFuncVec4_)
617 {
618     return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
619                            resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_,
620                            evalFuncVec4_, SIDE_EFFECT_OPERATOR);
621 }
622 
623 // For postfix (unary) operators, testing side-effect.
BuiltinPostSideEffOperInfo(const char * caseName_,const char * shaderFuncName_,ValueType outValue_,Value input0_,Value input1_,Value input2_,const float resultScale_,const float resultBias_,uint32_t precisionMask_,ShaderEvalFunc evalFuncScalar_,ShaderEvalFunc evalFuncVec2_,ShaderEvalFunc evalFuncVec3_,ShaderEvalFunc evalFuncVec4_)624 static inline BuiltinFuncInfo BuiltinPostSideEffOperInfo(const char *caseName_, const char *shaderFuncName_,
625                                                          ValueType outValue_, Value input0_, Value input1_,
626                                                          Value input2_, const float resultScale_,
627                                                          const float resultBias_, uint32_t precisionMask_,
628                                                          ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_,
629                                                          ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
630 {
631     return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
632                            resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_,
633                            evalFuncVec4_, SIDE_EFFECT_OPERATOR, false);
634 }
635 
636 // BuiltinFuncGroup
637 
638 struct BuiltinFuncGroup
639 {
BuiltinFuncGroupvkt::sr::__anoncb2548460111::BuiltinFuncGroup640     BuiltinFuncGroup(const char *name_, const char *description_) : name(name_), description(description_)
641     {
642     }
operator <<vkt::sr::__anoncb2548460111::BuiltinFuncGroup643     BuiltinFuncGroup &operator<<(const BuiltinFuncInfo &info)
644     {
645         funcInfos.push_back(info);
646         return *this;
647     }
648 
649     const char *name;
650     const char *description;
651     std::vector<BuiltinFuncInfo> funcInfos;
652 };
653 
654 static const char *s_inSwizzles[MAX_INPUTS][4] = {{"z", "wy", "zxy", "yzwx"},
655                                                   {"x", "yx", "yzx", "wzyx"},
656                                                   {"y", "zy", "wyz", "xwzy"}};
657 
658 static const char *s_outSwizzles[] = {"x", "yz", "xyz", "xyzw"};
659 
660 static const BVec4 s_outSwizzleChannelMasks[] = {BVec4(true, false, false, false), BVec4(false, true, true, false),
661                                                  BVec4(true, true, true, false), BVec4(true, true, true, true)};
662 
663 // OperatorShaderEvaluator
664 
665 class OperatorShaderEvaluator : public ShaderEvaluator
666 {
667 public:
OperatorShaderEvaluator(const ShaderEvalFunc evalFunc,const float scale,const float bias,int resultScalarSize)668     OperatorShaderEvaluator(const ShaderEvalFunc evalFunc, const float scale, const float bias, int resultScalarSize)
669         : m_evalFunc(evalFunc)
670         , m_resultScalarSize(resultScalarSize)
671         , m_evaluatedScale(scale)
672         , m_evaluatedBias(bias)
673     {
674         DE_ASSERT(de::inRange(resultScalarSize, 1, 4));
675     }
676 
~OperatorShaderEvaluator(void)677     virtual ~OperatorShaderEvaluator(void)
678     {
679     }
680 
evaluate(ShaderEvalContext & ctx) const681     virtual void evaluate(ShaderEvalContext &ctx) const
682     {
683         m_evalFunc(ctx);
684 
685         for (int channelNdx = 0; channelNdx < 4; channelNdx++)
686             if (s_outSwizzleChannelMasks[m_resultScalarSize - 1][channelNdx])
687                 ctx.color[channelNdx] = ctx.color[channelNdx] * m_evaluatedScale + m_evaluatedBias;
688     }
689 
690 private:
691     const ShaderEvalFunc m_evalFunc;
692     const int m_resultScalarSize;
693 
694     const float m_evaluatedScale;
695     const float m_evaluatedBias;
696 };
697 
698 // Concrete value.
699 
700 struct ShaderValue
701 {
ShaderValuevkt::sr::__anoncb2548460111::ShaderValue702     ShaderValue(DataType type_, const float rangeMin_, const float rangeMax_)
703         : type(type_)
704         , rangeMin(rangeMin_)
705         , rangeMax(rangeMax_)
706     {
707     }
708 
ShaderValuevkt::sr::__anoncb2548460111::ShaderValue709     ShaderValue(void) : type(TYPE_LAST), rangeMin(0.0f), rangeMax(0.0f)
710     {
711     }
712 
713     DataType type;
714     float rangeMin;
715     float rangeMax;
716 };
717 
718 struct ShaderDataSpec
719 {
ShaderDataSpecvkt::sr::__anoncb2548460111::ShaderDataSpec720     ShaderDataSpec(void)
721         : resultScale(1.0f)
722         , resultBias(0.0f)
723         , referenceScale(1.0f)
724         , referenceBias(0.0f)
725         , precision(PRECISION_LAST)
726         , output(TYPE_LAST)
727         , numInputs(0)
728     {
729     }
730 
731     float resultScale;
732     float resultBias;
733     float referenceScale;
734     float referenceBias;
735     Precision precision;
736     DataType output;
737     int numInputs;
738     ShaderValue inputs[MAX_INPUTS];
739 };
740 
741 // ShaderOperatorInstance
742 
743 class ShaderOperatorCaseInstance : public ShaderRenderCaseInstance
744 {
745 public:
746     ShaderOperatorCaseInstance(Context &context, const bool isVertexCase, const ShaderEvaluator &evaluator,
747                                const UniformSetup &uniformSetup, const ShaderDataSpec spec);
748     virtual ~ShaderOperatorCaseInstance(void);
749 
750 private:
751     const ShaderDataSpec m_spec;
752 };
753 
ShaderOperatorCaseInstance(Context & context,const bool isVertexCase,const ShaderEvaluator & evaluator,const UniformSetup & uniformSetup,const ShaderDataSpec spec)754 ShaderOperatorCaseInstance::ShaderOperatorCaseInstance(Context &context, const bool isVertexCase,
755                                                        const ShaderEvaluator &evaluator,
756                                                        const UniformSetup &uniformSetup, const ShaderDataSpec spec)
757     : ShaderRenderCaseInstance(context, isVertexCase, evaluator, uniformSetup, DE_NULL, IMAGE_BACKING_MODE_REGULAR,
758                                (isVertexCase ? 92 : GRID_SIZE_DEFAULT_FRAGMENT))
759     , m_spec(spec)
760 {
761     // Setup the user attributes.
762     m_userAttribTransforms.resize(m_spec.numInputs);
763     for (int inputNdx = 0; inputNdx < m_spec.numInputs; inputNdx++)
764     {
765         const ShaderValue &v = m_spec.inputs[inputNdx];
766         DE_ASSERT(v.type != TYPE_LAST);
767 
768         const float rangeMin = v.rangeMin;
769         const float rangeMax = v.rangeMax;
770         const float scale    = rangeMax - rangeMin;
771         const float minBias  = rangeMin;
772         const float maxBias  = rangeMax;
773         Mat4 attribMatrix;
774 
775         for (int rowNdx = 0; rowNdx < 4; rowNdx++)
776         {
777             Vec4 row;
778 
779             switch ((rowNdx + inputNdx) % 4)
780             {
781             case 0:
782                 row = Vec4(scale, 0.0f, 0.0f, minBias);
783                 break;
784             case 1:
785                 row = Vec4(0.0f, scale, 0.0f, minBias);
786                 break;
787             case 2:
788                 row = Vec4(-scale, 0.0f, 0.0f, maxBias);
789                 break;
790             case 3:
791                 row = Vec4(0.0f, -scale, 0.0f, maxBias);
792                 break;
793             default:
794                 DE_ASSERT(false);
795             }
796 
797             attribMatrix.setRow(rowNdx, row);
798         }
799 
800         m_userAttribTransforms[inputNdx] = attribMatrix;
801 
802         const uint32_t location = 4u + inputNdx;
803         switch (inputNdx)
804         {
805         case 0:
806             useAttribute(location, A_IN0);
807             break;
808         case 1:
809             useAttribute(location, A_IN1);
810             break;
811         case 2:
812             useAttribute(location, A_IN2);
813             break;
814         case 3:
815             useAttribute(location, A_IN3);
816             break;
817         default:
818             DE_ASSERT(false);
819         }
820     }
821 }
822 
~ShaderOperatorCaseInstance(void)823 ShaderOperatorCaseInstance::~ShaderOperatorCaseInstance(void)
824 {
825 }
826 
827 // ShaderOperatorCase
828 
829 class ShaderOperatorCase : public ShaderRenderCase
830 {
831 public:
832     ShaderOperatorCase(tcu::TestContext &testCtx, const char *caseName, const bool isVertexCase,
833                        const ShaderEvalFunc evalFunc, const std::string &shaderOp, const ShaderDataSpec &spec);
834     virtual ~ShaderOperatorCase(void);
835 
836     virtual TestInstance *createInstance(Context &context) const;
837 
838 protected:
839     void setupShaderData(void);
840 
841 private:
842     ShaderOperatorCase(const ShaderOperatorCase &);            // not allowed!
843     ShaderOperatorCase &operator=(const ShaderOperatorCase &); // not allowed!
844 
845     const ShaderDataSpec m_spec;
846     const std::string m_shaderOp;
847 };
848 
ShaderOperatorCase(tcu::TestContext & testCtx,const char * caseName,const bool isVertexCase,const ShaderEvalFunc evalFunc,const std::string & shaderOp,const ShaderDataSpec & spec)849 ShaderOperatorCase::ShaderOperatorCase(tcu::TestContext &testCtx, const char *caseName, const bool isVertexCase,
850                                        const ShaderEvalFunc evalFunc, const std::string &shaderOp,
851                                        const ShaderDataSpec &spec)
852     : ShaderRenderCase(testCtx, caseName, isVertexCase,
853                        new OperatorShaderEvaluator(evalFunc, spec.referenceScale, spec.referenceBias,
854                                                    getDataTypeScalarSize(spec.output)),
855                        DE_NULL, DE_NULL)
856     , m_spec(spec)
857     , m_shaderOp(shaderOp)
858 {
859     setupShaderData();
860 }
861 
createInstance(Context & context) const862 TestInstance *ShaderOperatorCase::createInstance(Context &context) const
863 {
864     DE_ASSERT(m_evaluator != DE_NULL);
865     DE_ASSERT(m_uniformSetup != DE_NULL);
866     return new ShaderOperatorCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_spec);
867 }
868 
setupShaderData(void)869 void ShaderOperatorCase::setupShaderData(void)
870 {
871     const char *precision = m_spec.precision != PRECISION_LAST ? getPrecisionName(m_spec.precision) : DE_NULL;
872     const char *inputPrecision[MAX_INPUTS];
873 
874     std::ostringstream vtx;
875     std::ostringstream frag;
876     std::ostringstream &op = m_isVertexCase ? vtx : frag;
877 
878     std::string header = "#version 310 es\n";
879 
880     vtx << header;
881     frag << header;
882 
883     // Compute precision for inputs.
884     for (int inputNdx = 0; inputNdx < m_spec.numInputs; inputNdx++)
885     {
886         const bool isBoolVal = de::inRange<int>(m_spec.inputs[inputNdx].type, TYPE_BOOL, TYPE_BOOL_VEC4);
887         const bool isIntVal  = de::inRange<int>(m_spec.inputs[inputNdx].type, TYPE_INT, TYPE_INT_VEC4);
888         const bool isUintVal = de::inRange<int>(m_spec.inputs[inputNdx].type, TYPE_UINT, TYPE_UINT_VEC4);
889         // \note Mediump interpolators are used for booleans, and highp for integers.
890         const Precision prec     = isBoolVal             ? PRECISION_MEDIUMP :
891                                    isIntVal || isUintVal ? PRECISION_HIGHP :
892                                                            m_spec.precision;
893         inputPrecision[inputNdx] = getPrecisionName(prec);
894     }
895 
896     // Attributes.
897     vtx << "layout(location = 0) in highp vec4 a_position;\n";
898     for (int inputNdx = 0; inputNdx < m_spec.numInputs; inputNdx++)
899         vtx << "layout(location = " << 4 + inputNdx << ") in " << inputPrecision[inputNdx] << " vec4 a_in" << inputNdx
900             << ";\n";
901 
902     // Color output.
903     frag << "layout(location = 0) out mediump vec4 o_color;\n";
904 
905     if (m_isVertexCase)
906     {
907         vtx << "layout(location = 0) out mediump vec4 v_color;\n";
908         frag << "layout(location = 0) in mediump vec4 v_color;\n";
909     }
910     else
911     {
912         for (int inputNdx = 0; inputNdx < m_spec.numInputs; inputNdx++)
913         {
914             vtx << "layout(location = " << inputNdx + 1 << ") out " << inputPrecision[inputNdx] << " vec4 v_in"
915                 << inputNdx << ";\n";
916             frag << "layout(location = " << inputNdx + 1 << ") in " << inputPrecision[inputNdx] << " vec4 v_in"
917                  << inputNdx << ";\n";
918         }
919     }
920 
921     vtx << "\n";
922     vtx << "void main()\n";
923     vtx << "{\n";
924     vtx << "    gl_Position = a_position;\n";
925 
926     frag << "\n";
927     frag << "void main()\n";
928     frag << "{\n";
929 
930     // Expression inputs.
931     const std::string prefix = m_isVertexCase ? "a_" : "v_";
932     for (int inputNdx = 0; inputNdx < m_spec.numInputs; inputNdx++)
933     {
934         const DataType inType = m_spec.inputs[inputNdx].type;
935         const int inSize      = getDataTypeScalarSize(inType);
936         const bool isInt      = de::inRange<int>(inType, TYPE_INT, TYPE_INT_VEC4);
937         const bool isUint     = de::inRange<int>(inType, TYPE_UINT, TYPE_UINT_VEC4);
938         const bool isBool     = de::inRange<int>(inType, TYPE_BOOL, TYPE_BOOL_VEC4);
939         const char *typeName  = getDataTypeName(inType);
940         const char *swizzle   = s_inSwizzles[inputNdx][inSize - 1];
941 
942         op << "\t";
943         if (precision && !isBool)
944             op << precision << " ";
945 
946         op << typeName << " in" << inputNdx << " = ";
947 
948         if (isBool)
949         {
950             if (inSize == 1)
951                 op << "(";
952             else
953                 op << "greaterThan(";
954         }
955         else if (isInt || isUint)
956             op << typeName << "(";
957 
958         op << prefix << "in" << inputNdx << "." << swizzle;
959 
960         if (isBool)
961         {
962             if (inSize == 1)
963                 op << " > 0.0)";
964             else
965                 op << ", vec" << inSize << "(0.0))";
966         }
967         else if (isInt || isUint)
968             op << ")";
969 
970         op << ";\n";
971     }
972 
973     // Result variable.
974     {
975         const char *outTypeName = getDataTypeName(m_spec.output);
976         const bool isBoolOut    = de::inRange<int>(m_spec.output, TYPE_BOOL, TYPE_BOOL_VEC4);
977 
978         op << "\t";
979         if (precision && !isBoolOut)
980             op << precision << " ";
981         op << outTypeName << " res = " << outTypeName << "(0.0);\n\n";
982     }
983 
984     // Expression.
985     op << "\t" << m_shaderOp << "\n\n";
986 
987     // Convert to color.
988     const bool isResFloatVec = de::inRange<int>(m_spec.output, TYPE_FLOAT, TYPE_FLOAT_VEC4);
989     const int outScalarSize  = getDataTypeScalarSize(m_spec.output);
990 
991     op << "\thighp vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n";
992     op << "\tcolor." << s_outSwizzles[outScalarSize - 1] << " = ";
993 
994     if (!isResFloatVec && outScalarSize == 1)
995         op << "float(res)";
996     else if (!isResFloatVec)
997         op << "vec" << outScalarSize << "(res)";
998     else
999         op << "res";
1000 
1001     op << ";\n";
1002 
1003     // Scale & bias.
1004     const float resultScale = m_spec.resultScale;
1005     const float resultBias  = m_spec.resultBias;
1006     if ((resultScale != 1.0f) || (resultBias != 0.0f))
1007     {
1008         op << "\tcolor = color";
1009         if (resultScale != 1.0f)
1010             op << " * " << twoValuedVec4(de::toString(resultScale), "1.0", s_outSwizzleChannelMasks[outScalarSize - 1]);
1011         if (resultBias != 0.0f)
1012             op << " + "
1013                << twoValuedVec4(de::floatToString(resultBias, 2), "0.0", s_outSwizzleChannelMasks[outScalarSize - 1]);
1014         op << ";\n";
1015     }
1016 
1017     // ..
1018     if (m_isVertexCase)
1019     {
1020         vtx << "    v_color = color;\n";
1021         frag << "    o_color = v_color;\n";
1022     }
1023     else
1024     {
1025         for (int inputNdx = 0; inputNdx < m_spec.numInputs; inputNdx++)
1026             vtx << "    v_in" << inputNdx << " = a_in" << inputNdx << ";\n";
1027         frag << "    o_color = color;\n";
1028     }
1029 
1030     vtx << "}\n";
1031     frag << "}\n";
1032 
1033     m_vertShaderSource = vtx.str();
1034     m_fragShaderSource = frag.str();
1035 }
1036 
~ShaderOperatorCase(void)1037 ShaderOperatorCase::~ShaderOperatorCase(void)
1038 {
1039 }
1040 
1041 // Vector math functions.
1042 template <typename T>
nop(T f)1043 inline T nop(T f)
1044 {
1045     return f;
1046 }
1047 
1048 template <typename T, int Size>
nop(const Vector<T,Size> & v)1049 Vector<T, Size> nop(const Vector<T, Size> &v)
1050 {
1051     return v;
1052 }
1053 
1054 #define DECLARE_UNARY_GENTYPE_FUNCS(FUNC_NAME)               \
1055     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)      \
1056     {                                                        \
1057         c.color.x() = FUNC_NAME(c.in[0].swizzle(2)).x();     \
1058     }                                                        \
1059     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)       \
1060     {                                                        \
1061         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1));     \
1062     }                                                        \
1063     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)       \
1064     {                                                        \
1065         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1)); \
1066     }                                                        \
1067     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)       \
1068     {                                                        \
1069         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0));    \
1070     }
1071 
1072 #define DECLARE_BINARY_GENTYPE_FUNCS(FUNC_NAME)                                        \
1073     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)                                \
1074     {                                                                                  \
1075         c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0)).x();           \
1076     }                                                                                  \
1077     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                 \
1078     {                                                                                  \
1079         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0));        \
1080     }                                                                                  \
1081     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                 \
1082     {                                                                                  \
1083         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)); \
1084     }                                                                                  \
1085     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                 \
1086     {                                                                                  \
1087         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); \
1088     }
1089 
1090 #define DECLARE_TERNARY_GENTYPE_FUNCS(FUNC_NAME)                                                                    \
1091     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)                                                             \
1092     {                                                                                                               \
1093         c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0), c.in[2].swizzle(1)).x();                    \
1094     }                                                                                                               \
1095     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                                              \
1096     {                                                                                                               \
1097         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0), c.in[2].swizzle(2, 1));              \
1098     }                                                                                                               \
1099     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                                              \
1100     {                                                                                                               \
1101         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));    \
1102     }                                                                                                               \
1103     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                                              \
1104     {                                                                                                               \
1105         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)); \
1106     }
1107 
1108 #define DECLARE_UNARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME)         \
1109     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)       \
1110     {                                                         \
1111         c.color.x() = FUNC_NAME(c.in[0].swizzle(2));          \
1112     }                                                         \
1113     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)        \
1114     {                                                         \
1115         c.color.x() = FUNC_NAME(c.in[0].swizzle(3, 1));       \
1116     }                                                         \
1117     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)        \
1118     {                                                         \
1119         c.color.x() = FUNC_NAME(c.in[0].swizzle(2, 0, 1));    \
1120     }                                                         \
1121     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)        \
1122     {                                                         \
1123         c.color.x() = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0)); \
1124     }
1125 
1126 #define DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME)                                     \
1127     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)                                    \
1128     {                                                                                      \
1129         c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0));                   \
1130     }                                                                                      \
1131     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                     \
1132     {                                                                                      \
1133         c.color.x() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0));             \
1134     }                                                                                      \
1135     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                     \
1136     {                                                                                      \
1137         c.color.x() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0));       \
1138     }                                                                                      \
1139     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                     \
1140     {                                                                                      \
1141         c.color.x() = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); \
1142     }
1143 
1144 #define DECLARE_BINARY_BOOL_FUNCS(FUNC_NAME)                                    \
1145     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                          \
1146     {                                                                           \
1147         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f); \
1148     }
1149 
1150 #define DECLARE_UNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME)                                             \
1151     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                                          \
1152     {                                                                                           \
1153         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f);                                     \
1154     }                                                                                           \
1155     void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c)                                         \
1156     {                                                                                           \
1157         c.color.yz() = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat();     \
1158     }                                                                                           \
1159     void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c)                                         \
1160     {                                                                                           \
1161         c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat(); \
1162     }                                                                                           \
1163     void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c)                                         \
1164     {                                                                                           \
1165         c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f))).asFloat();    \
1166     }
1167 
1168 #define DECLARE_TERNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME)                                                                 \
1169     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                                                                \
1170     {                                                                                                                 \
1171         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f, c.in[2].y() > 0.0f);                   \
1172     }                                                                                                                 \
1173     void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c)                                                               \
1174     {                                                                                                                 \
1175         c.color.yz() =                                                                                                \
1176             FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)), greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f)), \
1177                       greaterThan(c.in[2].swizzle(2, 1), Vec2(0.0f)))                                                 \
1178                 .asFloat();                                                                                           \
1179     }                                                                                                                 \
1180     void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c)                                                               \
1181     {                                                                                                                 \
1182         c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)),                                  \
1183                                   greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f)),                                  \
1184                                   greaterThan(c.in[2].swizzle(3, 1, 2), Vec3(0.0f)))                                  \
1185                             .asFloat();                                                                               \
1186     }                                                                                                                 \
1187     void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c)                                                               \
1188     {                                                                                                                 \
1189         c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)),                                     \
1190                             greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f)),                                     \
1191                             greaterThan(c.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f)))                                     \
1192                       .asFloat();                                                                                     \
1193     }
1194 
1195 #define DECLARE_UNARY_INT_GENTYPE_FUNCS(FUNC_NAME)                             \
1196     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                          \
1197     {                                                                          \
1198         c.color.x() = (float)FUNC_NAME((int)c.in[0].z());                      \
1199     }                                                                          \
1200     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                        \
1201     {                                                                          \
1202         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt()).asFloat();     \
1203     }                                                                          \
1204     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                        \
1205     {                                                                          \
1206         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt()).asFloat(); \
1207     }                                                                          \
1208     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                        \
1209     {                                                                          \
1210         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt()).asFloat();    \
1211     }
1212 
1213 #define DECLARE_BINARY_INT_GENTYPE_FUNCS(FUNC_NAME)                                                              \
1214     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                                                            \
1215     {                                                                                                            \
1216         c.color.x() = (float)FUNC_NAME((int)c.in[0].z(), (int)c.in[1].x());                                      \
1217     }                                                                                                            \
1218     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                          \
1219     {                                                                                                            \
1220         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), c.in[1].swizzle(1, 0).asInt()).asFloat();        \
1221     }                                                                                                            \
1222     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                          \
1223     {                                                                                                            \
1224         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
1225     }                                                                                                            \
1226     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                          \
1227     {                                                                                                            \
1228         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); \
1229     }
1230 
1231 #define DECLARE_UNARY_UINT_GENTYPE_FUNCS(FUNC_NAME)                             \
1232     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                          \
1233     {                                                                           \
1234         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z());                  \
1235     }                                                                           \
1236     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                         \
1237     {                                                                           \
1238         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint()).asFloat();     \
1239     }                                                                           \
1240     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                         \
1241     {                                                                           \
1242         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint()).asFloat(); \
1243     }                                                                           \
1244     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                         \
1245     {                                                                           \
1246         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint()).asFloat();    \
1247     }
1248 
1249 #define DECLARE_BINARY_UINT_GENTYPE_FUNCS(FUNC_NAME)                                                               \
1250     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                                             \
1251     {                                                                                                              \
1252         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x());                              \
1253     }                                                                                                              \
1254     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                            \
1255     {                                                                                                              \
1256         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()).asFloat();        \
1257     }                                                                                                              \
1258     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                            \
1259     {                                                                                                              \
1260         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
1261     }                                                                                                              \
1262     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                            \
1263     {                                                                                                              \
1264         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat(); \
1265     }
1266 
1267 #define DECLARE_TERNARY_INT_GENTYPE_FUNCS(FUNC_NAME)                                                               \
1268     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                                                              \
1269     {                                                                                                              \
1270         c.color.x() = (float)FUNC_NAME((int)c.in[0].z(), (int)c.in[1].x(), (int)c.in[2].y());                      \
1271     }                                                                                                              \
1272     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                            \
1273     {                                                                                                              \
1274         c.color.yz() =                                                                                             \
1275             FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), c.in[1].swizzle(1, 0).asInt(), c.in[2].swizzle(2, 1).asInt()) \
1276                 .asFloat();                                                                                        \
1277     }                                                                                                              \
1278     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                            \
1279     {                                                                                                              \
1280         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), c.in[1].swizzle(1, 2, 0).asInt(),              \
1281                                   c.in[2].swizzle(3, 1, 2).asInt())                                                \
1282                             .asFloat();                                                                            \
1283     }                                                                                                              \
1284     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                            \
1285     {                                                                                                              \
1286         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), c.in[1].swizzle(3, 2, 1, 0).asInt(),              \
1287                             c.in[2].swizzle(0, 3, 2, 1).asInt())                                                   \
1288                       .asFloat();                                                                                  \
1289     }
1290 
1291 #define DECLARE_TERNARY_UINT_GENTYPE_FUNCS(FUNC_NAME)                                                                 \
1292     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                                                \
1293     {                                                                                                                 \
1294         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y());          \
1295     }                                                                                                                 \
1296     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                               \
1297     {                                                                                                                 \
1298         c.color.yz() =                                                                                                \
1299             FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint(), c.in[2].swizzle(2, 1).asUint()) \
1300                 .asFloat();                                                                                           \
1301     }                                                                                                                 \
1302     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                               \
1303     {                                                                                                                 \
1304         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint(),               \
1305                                   c.in[2].swizzle(3, 1, 2).asUint())                                                  \
1306                             .asFloat();                                                                               \
1307     }                                                                                                                 \
1308     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                               \
1309     {                                                                                                                 \
1310         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint(),               \
1311                             c.in[2].swizzle(0, 3, 2, 1).asUint())                                                     \
1312                       .asFloat();                                                                                     \
1313     }
1314 
1315 #define DECLARE_VEC_FLOAT_FUNCS(FUNC_NAME)                                \
1316     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                    \
1317     {                                                                     \
1318         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].x());     \
1319     }                                                                     \
1320     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                    \
1321     {                                                                     \
1322         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].x()); \
1323     }                                                                     \
1324     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                    \
1325     {                                                                     \
1326         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].x());    \
1327     }
1328 
1329 #define DECLARE_VEC_FLOAT_FLOAT_FUNCS(FUNC_NAME)                                       \
1330     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                 \
1331     {                                                                                  \
1332         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].x(), c.in[2].y());     \
1333     }                                                                                  \
1334     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                 \
1335     {                                                                                  \
1336         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].x(), c.in[2].y()); \
1337     }                                                                                  \
1338     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                 \
1339     {                                                                                  \
1340         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].x(), c.in[2].y());    \
1341     }
1342 
1343 #define DECLARE_VEC_VEC_FLOAT_FUNCS(FUNC_NAME)                                                      \
1344     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                              \
1345     {                                                                                               \
1346         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0), c.in[2].y());        \
1347     }                                                                                               \
1348     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                              \
1349     {                                                                                               \
1350         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0), c.in[2].y()); \
1351     }                                                                                               \
1352     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                              \
1353     {                                                                                               \
1354         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0), c.in[2].y()); \
1355     }
1356 
1357 #define DECLARE_FLOAT_FLOAT_VEC_FUNCS(FUNC_NAME)                                       \
1358     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                 \
1359     {                                                                                  \
1360         c.color.yz() = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(2, 1));     \
1361     }                                                                                  \
1362     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                 \
1363     {                                                                                  \
1364         c.color.xyz() = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(3, 1, 2)); \
1365     }                                                                                  \
1366     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                 \
1367     {                                                                                  \
1368         c.color = FUNC_NAME(c.in[0].z(), c.in[1].x(), c.in[2].swizzle(0, 3, 2, 1));    \
1369     }
1370 
1371 #define DECLARE_FLOAT_VEC_FUNCS(FUNC_NAME)                                \
1372     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                    \
1373     {                                                                     \
1374         c.color.yz() = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(1, 0));     \
1375     }                                                                     \
1376     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                    \
1377     {                                                                     \
1378         c.color.xyz() = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(1, 2, 0)); \
1379     }                                                                     \
1380     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                    \
1381     {                                                                     \
1382         c.color = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0));    \
1383     }
1384 
1385 #define DECLARE_IVEC_INT_FUNCS(FUNC_NAME)                                                        \
1386     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                          \
1387     {                                                                                            \
1388         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), (int)c.in[1].x()).asFloat();     \
1389     }                                                                                            \
1390     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                          \
1391     {                                                                                            \
1392         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), (int)c.in[1].x()).asFloat(); \
1393     }                                                                                            \
1394     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                          \
1395     {                                                                                            \
1396         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), (int)c.in[1].x()).asFloat();    \
1397     }
1398 
1399 #define DECLARE_IVEC_INT_INT_FUNCS(FUNC_NAME)                                                                      \
1400     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                            \
1401     {                                                                                                              \
1402         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), (int)c.in[1].x(), (int)c.in[2].y()).asFloat();     \
1403     }                                                                                                              \
1404     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                            \
1405     {                                                                                                              \
1406         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), (int)c.in[1].x(), (int)c.in[2].y()).asFloat(); \
1407     }                                                                                                              \
1408     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                            \
1409     {                                                                                                              \
1410         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), (int)c.in[1].x(), (int)c.in[2].y()).asFloat();    \
1411     }
1412 
1413 #define DECLARE_INT_IVEC_FUNCS(FUNC_NAME)                                                        \
1414     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                          \
1415     {                                                                                            \
1416         c.color.yz() = FUNC_NAME((int)c.in[0].z(), c.in[1].swizzle(1, 0).asInt()).asFloat();     \
1417     }                                                                                            \
1418     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                          \
1419     {                                                                                            \
1420         c.color.xyz() = FUNC_NAME((int)c.in[0].z(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
1421     }                                                                                            \
1422     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                          \
1423     {                                                                                            \
1424         c.color = FUNC_NAME((int)c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat();    \
1425     }
1426 
1427 #define DECLARE_UVEC_UINT_FUNCS(FUNC_NAME)                                                             \
1428     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                \
1429     {                                                                                                  \
1430         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), (uint32_t)c.in[1].x()).asFloat();     \
1431     }                                                                                                  \
1432     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                \
1433     {                                                                                                  \
1434         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), (uint32_t)c.in[1].x()).asFloat(); \
1435     }                                                                                                  \
1436     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                \
1437     {                                                                                                  \
1438         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), (uint32_t)c.in[1].x()).asFloat();    \
1439     }
1440 
1441 #define DECLARE_UVEC_UINT_UINT_FUNCS(FUNC_NAME)                                                                      \
1442     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                              \
1443     {                                                                                                                \
1444         c.color.yz() =                                                                                               \
1445             FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()).asFloat();       \
1446     }                                                                                                                \
1447     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                              \
1448     {                                                                                                                \
1449         c.color.xyz() =                                                                                              \
1450             FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()).asFloat();    \
1451     }                                                                                                                \
1452     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                              \
1453     {                                                                                                                \
1454         c.color =                                                                                                    \
1455             FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()).asFloat(); \
1456     }
1457 
1458 #define DECLARE_UINT_UVEC_FUNCS(FUNC_NAME)                                                             \
1459     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                \
1460     {                                                                                                  \
1461         c.color.yz() = FUNC_NAME((uint32_t)c.in[0].z(), c.in[1].swizzle(1, 0).asUint()).asFloat();     \
1462     }                                                                                                  \
1463     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                \
1464     {                                                                                                  \
1465         c.color.xyz() = FUNC_NAME((uint32_t)c.in[0].z(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
1466     }                                                                                                  \
1467     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                \
1468     {                                                                                                  \
1469         c.color = FUNC_NAME((uint32_t)c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat();    \
1470     }
1471 
1472 #define DECLARE_BINARY_INT_VEC_FUNCS(FUNC_NAME)                                                                  \
1473     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                          \
1474     {                                                                                                            \
1475         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt(), c.in[1].swizzle(1, 0).asInt()).asFloat();        \
1476     }                                                                                                            \
1477     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                          \
1478     {                                                                                                            \
1479         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
1480     }                                                                                                            \
1481     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                          \
1482     {                                                                                                            \
1483         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); \
1484     }
1485 
1486 #define DECLARE_BINARY_UINT_VEC_FUNCS(FUNC_NAME)                                                                   \
1487     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                            \
1488     {                                                                                                              \
1489         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()).asFloat();        \
1490     }                                                                                                              \
1491     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                            \
1492     {                                                                                                              \
1493         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
1494     }                                                                                                              \
1495     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                            \
1496     {                                                                                                              \
1497         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat(); \
1498     }
1499 
1500 #define DECLARE_UINT_INT_GENTYPE_FUNCS(FUNC_NAME)                                                                 \
1501     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                                            \
1502     {                                                                                                             \
1503         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (int)c.in[1].x());                                  \
1504     }                                                                                                             \
1505     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                           \
1506     {                                                                                                             \
1507         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asInt()).asFloat();        \
1508     }                                                                                                             \
1509     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                           \
1510     {                                                                                                             \
1511         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
1512     }                                                                                                             \
1513     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                           \
1514     {                                                                                                             \
1515         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); \
1516     }
1517 
1518 #define DECLARE_UVEC_INT_FUNCS(FUNC_NAME)                                                         \
1519     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                           \
1520     {                                                                                             \
1521         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), (int)c.in[1].x()).asFloat();     \
1522     }                                                                                             \
1523     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                           \
1524     {                                                                                             \
1525         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), (int)c.in[1].x()).asFloat(); \
1526     }                                                                                             \
1527     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                           \
1528     {                                                                                             \
1529         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), (int)c.in[1].x()).asFloat();    \
1530     }
1531 
1532 // Operators.
1533 
1534 DECLARE_UNARY_GENTYPE_FUNCS(nop)
DECLARE_UNARY_GENTYPE_FUNCS(negate)1535 DECLARE_UNARY_GENTYPE_FUNCS(negate)
1536 DECLARE_UNARY_GENTYPE_FUNCS(addOne)
1537 DECLARE_UNARY_GENTYPE_FUNCS(subOne)
1538 DECLARE_BINARY_GENTYPE_FUNCS(add)
1539 DECLARE_BINARY_GENTYPE_FUNCS(sub)
1540 DECLARE_BINARY_GENTYPE_FUNCS(mul)
1541 DECLARE_BINARY_GENTYPE_FUNCS(div)
1542 
1543 void eval_selection_float(ShaderEvalContext &c)
1544 {
1545     c.color.x() = selection(c.in[0].z() > 0.0f, c.in[1].x(), c.in[2].y());
1546 }
eval_selection_vec2(ShaderEvalContext & c)1547 void eval_selection_vec2(ShaderEvalContext &c)
1548 {
1549     c.color.yz() = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 0), c.in[2].swizzle(2, 1));
1550 }
eval_selection_vec3(ShaderEvalContext & c)1551 void eval_selection_vec3(ShaderEvalContext &c)
1552 {
1553     c.color.xyz() = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 2, 0), c.in[2].swizzle(3, 1, 2));
1554 }
eval_selection_vec4(ShaderEvalContext & c)1555 void eval_selection_vec4(ShaderEvalContext &c)
1556 {
1557     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));
1558 }
1559 
1560 DECLARE_UNARY_INT_GENTYPE_FUNCS(nop)
DECLARE_UNARY_INT_GENTYPE_FUNCS(negate)1561 DECLARE_UNARY_INT_GENTYPE_FUNCS(negate)
1562 DECLARE_UNARY_INT_GENTYPE_FUNCS(addOne)
1563 DECLARE_UNARY_INT_GENTYPE_FUNCS(subOne)
1564 DECLARE_UNARY_INT_GENTYPE_FUNCS(bitwiseNot)
1565 DECLARE_BINARY_INT_GENTYPE_FUNCS(add)
1566 DECLARE_BINARY_INT_GENTYPE_FUNCS(sub)
1567 DECLARE_BINARY_INT_GENTYPE_FUNCS(mul)
1568 DECLARE_BINARY_INT_GENTYPE_FUNCS(div)
1569 DECLARE_BINARY_INT_GENTYPE_FUNCS(mod)
1570 DECLARE_BINARY_INT_GENTYPE_FUNCS(bitwiseAnd)
1571 DECLARE_BINARY_INT_GENTYPE_FUNCS(bitwiseOr)
1572 DECLARE_BINARY_INT_GENTYPE_FUNCS(bitwiseXor)
1573 
1574 void eval_leftShift_int(ShaderEvalContext &c)
1575 {
1576     c.color.x() = (float)leftShift((int)c.in[0].z(), (int)c.in[1].x());
1577 }
DECLARE_BINARY_INT_VEC_FUNCS(leftShift)1578 DECLARE_BINARY_INT_VEC_FUNCS(leftShift)
1579 void eval_rightShift_int(ShaderEvalContext &c)
1580 {
1581     c.color.x() = (float)rightShift((int)c.in[0].z(), (int)c.in[1].x());
1582 }
1583 DECLARE_BINARY_INT_VEC_FUNCS(rightShift)
DECLARE_IVEC_INT_FUNCS(leftShiftVecScalar)1584 DECLARE_IVEC_INT_FUNCS(leftShiftVecScalar)
1585 DECLARE_IVEC_INT_FUNCS(rightShiftVecScalar)
1586 
1587 void eval_selection_int(ShaderEvalContext &c)
1588 {
1589     c.color.x() = (float)selection(c.in[0].z() > 0.0f, (int)c.in[1].x(), (int)c.in[2].y());
1590 }
eval_selection_ivec2(ShaderEvalContext & c)1591 void eval_selection_ivec2(ShaderEvalContext &c)
1592 {
1593     c.color.yz() =
1594         selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 0).asInt(), c.in[2].swizzle(2, 1).asInt()).asFloat();
1595 }
eval_selection_ivec3(ShaderEvalContext & c)1596 void eval_selection_ivec3(ShaderEvalContext &c)
1597 {
1598     c.color.xyz() =
1599         selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 2, 0).asInt(), c.in[2].swizzle(3, 1, 2).asInt()).asFloat();
1600 }
eval_selection_ivec4(ShaderEvalContext & c)1601 void eval_selection_ivec4(ShaderEvalContext &c)
1602 {
1603     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())
1604                   .asFloat();
1605 }
1606 
1607 DECLARE_UNARY_UINT_GENTYPE_FUNCS(nop)
DECLARE_UNARY_UINT_GENTYPE_FUNCS(negate)1608 DECLARE_UNARY_UINT_GENTYPE_FUNCS(negate)
1609 DECLARE_UNARY_UINT_GENTYPE_FUNCS(bitwiseNot)
1610 DECLARE_UNARY_UINT_GENTYPE_FUNCS(addOne)
1611 DECLARE_UNARY_UINT_GENTYPE_FUNCS(subOne)
1612 DECLARE_BINARY_UINT_GENTYPE_FUNCS(add)
1613 DECLARE_BINARY_UINT_GENTYPE_FUNCS(sub)
1614 DECLARE_BINARY_UINT_GENTYPE_FUNCS(mul)
1615 DECLARE_BINARY_UINT_GENTYPE_FUNCS(div)
1616 DECLARE_BINARY_UINT_GENTYPE_FUNCS(mod)
1617 DECLARE_BINARY_UINT_GENTYPE_FUNCS(bitwiseAnd)
1618 DECLARE_BINARY_UINT_GENTYPE_FUNCS(bitwiseOr)
1619 DECLARE_BINARY_UINT_GENTYPE_FUNCS(bitwiseXor)
1620 
1621 DECLARE_UINT_INT_GENTYPE_FUNCS(leftShift)
1622 DECLARE_UINT_INT_GENTYPE_FUNCS(rightShift)
1623 DECLARE_UVEC_INT_FUNCS(leftShiftVecScalar)
1624 DECLARE_UVEC_INT_FUNCS(rightShiftVecScalar)
1625 
1626 void eval_selection_uint(ShaderEvalContext &c)
1627 {
1628     c.color.x() = (float)selection(c.in[0].z() > 0.0f, (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y());
1629 }
eval_selection_uvec2(ShaderEvalContext & c)1630 void eval_selection_uvec2(ShaderEvalContext &c)
1631 {
1632     c.color.yz() =
1633         selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 0).asUint(), c.in[2].swizzle(2, 1).asUint()).asFloat();
1634 }
eval_selection_uvec3(ShaderEvalContext & c)1635 void eval_selection_uvec3(ShaderEvalContext &c)
1636 {
1637     c.color.xyz() =
1638         selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 2, 0).asUint(), c.in[2].swizzle(3, 1, 2).asUint()).asFloat();
1639 }
eval_selection_uvec4(ShaderEvalContext & c)1640 void eval_selection_uvec4(ShaderEvalContext &c)
1641 {
1642     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())
1643                   .asFloat();
1644 }
1645 
1646 DECLARE_UNARY_BOOL_GENTYPE_FUNCS(boolNot)
DECLARE_BINARY_BOOL_FUNCS(logicalAnd)1647 DECLARE_BINARY_BOOL_FUNCS(logicalAnd)
1648 DECLARE_BINARY_BOOL_FUNCS(logicalOr)
1649 DECLARE_BINARY_BOOL_FUNCS(logicalXor)
1650 
1651 void eval_selection_bool(ShaderEvalContext &c)
1652 {
1653     c.color.x() = (float)selection(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f, c.in[2].y() > 0.0f);
1654 }
eval_selection_bvec2(ShaderEvalContext & c)1655 void eval_selection_bvec2(ShaderEvalContext &c)
1656 {
1657     c.color.yz() = selection(c.in[0].z() > 0.0f, greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f, 0.0f)),
1658                              greaterThan(c.in[2].swizzle(2, 1), Vec2(0.0f, 0.0f)))
1659                        .asFloat();
1660 }
eval_selection_bvec3(ShaderEvalContext & c)1661 void eval_selection_bvec3(ShaderEvalContext &c)
1662 {
1663     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)),
1664                               greaterThan(c.in[2].swizzle(3, 1, 2), Vec3(0.0f, 0.0f, 0.0f)))
1665                         .asFloat();
1666 }
eval_selection_bvec4(ShaderEvalContext & c)1667 void eval_selection_bvec4(ShaderEvalContext &c)
1668 {
1669     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)),
1670                         greaterThan(c.in[2].swizzle(0, 3, 2, 1), Vec4(0.0f, 0.0f, 0.0f, 0.0f)))
1671                   .asFloat();
1672 }
1673 
1674 DECLARE_VEC_FLOAT_FUNCS(addVecScalar)
1675 DECLARE_VEC_FLOAT_FUNCS(subVecScalar)
1676 DECLARE_VEC_FLOAT_FUNCS(mulVecScalar)
1677 DECLARE_VEC_FLOAT_FUNCS(divVecScalar)
1678 
1679 DECLARE_FLOAT_VEC_FUNCS(addScalarVec)
1680 DECLARE_FLOAT_VEC_FUNCS(subScalarVec)
1681 DECLARE_FLOAT_VEC_FUNCS(mulScalarVec)
1682 DECLARE_FLOAT_VEC_FUNCS(divScalarVec)
1683 
1684 DECLARE_IVEC_INT_FUNCS(addVecScalar)
1685 DECLARE_IVEC_INT_FUNCS(subVecScalar)
1686 DECLARE_IVEC_INT_FUNCS(mulVecScalar)
1687 DECLARE_IVEC_INT_FUNCS(divVecScalar)
1688 DECLARE_IVEC_INT_FUNCS(modVecScalar)
1689 DECLARE_IVEC_INT_FUNCS(bitwiseAndVecScalar)
1690 DECLARE_IVEC_INT_FUNCS(bitwiseOrVecScalar)
1691 DECLARE_IVEC_INT_FUNCS(bitwiseXorVecScalar)
1692 
1693 DECLARE_INT_IVEC_FUNCS(addScalarVec)
1694 DECLARE_INT_IVEC_FUNCS(subScalarVec)
1695 DECLARE_INT_IVEC_FUNCS(mulScalarVec)
1696 DECLARE_INT_IVEC_FUNCS(divScalarVec)
1697 DECLARE_INT_IVEC_FUNCS(modScalarVec)
1698 DECLARE_INT_IVEC_FUNCS(bitwiseAndScalarVec)
1699 DECLARE_INT_IVEC_FUNCS(bitwiseOrScalarVec)
1700 DECLARE_INT_IVEC_FUNCS(bitwiseXorScalarVec)
1701 
1702 DECLARE_UVEC_UINT_FUNCS(addVecScalar)
1703 DECLARE_UVEC_UINT_FUNCS(subVecScalar)
1704 DECLARE_UVEC_UINT_FUNCS(mulVecScalar)
1705 DECLARE_UVEC_UINT_FUNCS(divVecScalar)
1706 DECLARE_UVEC_UINT_FUNCS(modVecScalar)
1707 DECLARE_UVEC_UINT_FUNCS(bitwiseAndVecScalar)
1708 DECLARE_UVEC_UINT_FUNCS(bitwiseOrVecScalar)
1709 DECLARE_UVEC_UINT_FUNCS(bitwiseXorVecScalar)
1710 
1711 DECLARE_UINT_UVEC_FUNCS(addScalarVec)
1712 DECLARE_UINT_UVEC_FUNCS(subScalarVec)
1713 DECLARE_UINT_UVEC_FUNCS(mulScalarVec)
1714 DECLARE_UINT_UVEC_FUNCS(divScalarVec)
1715 DECLARE_UINT_UVEC_FUNCS(modScalarVec)
1716 DECLARE_UINT_UVEC_FUNCS(bitwiseAndScalarVec)
1717 DECLARE_UINT_UVEC_FUNCS(bitwiseOrScalarVec)
1718 DECLARE_UINT_UVEC_FUNCS(bitwiseXorScalarVec)
1719 
1720 // Built-in functions.
1721 DECLARE_BINARY_INT_GENTYPE_FUNCS(min)
1722 DECLARE_IVEC_INT_FUNCS(minVecScalar)
1723 DECLARE_BINARY_UINT_GENTYPE_FUNCS(min)
1724 DECLARE_UVEC_UINT_FUNCS(minVecScalar)
1725 DECLARE_BINARY_INT_GENTYPE_FUNCS(max)
1726 DECLARE_IVEC_INT_FUNCS(maxVecScalar)
1727 DECLARE_BINARY_UINT_GENTYPE_FUNCS(max)
1728 DECLARE_UVEC_UINT_FUNCS(maxVecScalar)
1729 DECLARE_TERNARY_INT_GENTYPE_FUNCS(clamp)
1730 DECLARE_IVEC_INT_INT_FUNCS(clampVecScalarScalar)
1731 DECLARE_TERNARY_UINT_GENTYPE_FUNCS(clamp)
1732 DECLARE_UVEC_UINT_UINT_FUNCS(clampVecScalarScalar)
1733 
1734 // Compare functions.
1735 
1736 #define DECLARE_FLOAT_COMPARE_FUNCS(FUNC_NAME)                                                    \
1737     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)                                           \
1738     {                                                                                             \
1739         c.color.x() = (float)FUNC_NAME(c.in[0].z(), c.in[1].x());                                 \
1740     }                                                                                             \
1741     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                            \
1742     {                                                                                             \
1743         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0));             \
1744     }                                                                                             \
1745     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                            \
1746     {                                                                                             \
1747         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0));       \
1748     }                                                                                             \
1749     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                            \
1750     {                                                                                             \
1751         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)); \
1752     }
1753 
1754 #define DECLARE_FLOAT_CWISE_COMPARE_FUNCS(FUNC_NAME)              \
1755     void eval_##FUNC_NAME##_float(ShaderEvalContext &c)           \
1756     {                                                             \
1757         c.color.x() = (float)FUNC_NAME(c.in[0].z(), c.in[1].x()); \
1758     }                                                             \
1759     DECLARE_FLOAT_VEC_CWISE_COMPARE_FUNCS(FUNC_NAME)
1760 
1761 #define DECLARE_FLOAT_VEC_CWISE_COMPARE_FUNCS(FUNC_NAME)                                         \
1762     void eval_##FUNC_NAME##_vec2(ShaderEvalContext &c)                                           \
1763     {                                                                                            \
1764         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0)).asFloat();        \
1765     }                                                                                            \
1766     void eval_##FUNC_NAME##_vec3(ShaderEvalContext &c)                                           \
1767     {                                                                                            \
1768         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)).asFloat(); \
1769     }                                                                                            \
1770     void eval_##FUNC_NAME##_vec4(ShaderEvalContext &c)                                           \
1771     {                                                                                            \
1772         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].swizzle(3, 2, 1, 0)).asFloat(); \
1773     }
1774 
1775 #define DECLARE_INT_COMPARE_FUNCS(FUNC_NAME)                                                                      \
1776     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                                                             \
1777     {                                                                                                             \
1778         c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x()));                           \
1779     }                                                                                                             \
1780     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                           \
1781     {                                                                                                             \
1782         c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].swizzle(3, 1)), chopToInt(c.in[1].swizzle(1, 0)));       \
1783     }                                                                                                             \
1784     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                           \
1785     {                                                                                                             \
1786         c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].swizzle(2, 0, 1)), chopToInt(c.in[1].swizzle(1, 2, 0))); \
1787     }                                                                                                             \
1788     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                           \
1789     {                                                                                                             \
1790         c.color.x() =                                                                                             \
1791             (float)FUNC_NAME(chopToInt(c.in[0].swizzle(1, 2, 3, 0)), chopToInt(c.in[1].swizzle(3, 2, 1, 0)));     \
1792     }
1793 
1794 #define DECLARE_INT_CWISE_COMPARE_FUNCS(FUNC_NAME)                                      \
1795     void eval_##FUNC_NAME##_int(ShaderEvalContext &c)                                   \
1796     {                                                                                   \
1797         c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x())); \
1798     }                                                                                   \
1799     DECLARE_INT_VEC_CWISE_COMPARE_FUNCS(FUNC_NAME)
1800 
1801 #define DECLARE_INT_VEC_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                                 \
1802     void eval_##FUNC_NAME##_ivec2(ShaderEvalContext &c)                                                                \
1803     {                                                                                                                  \
1804         c.color.yz() = FUNC_NAME(chopToInt(c.in[0].swizzle(3, 1)), chopToInt(c.in[1].swizzle(1, 0))).asFloat();        \
1805     }                                                                                                                  \
1806     void eval_##FUNC_NAME##_ivec3(ShaderEvalContext &c)                                                                \
1807     {                                                                                                                  \
1808         c.color.xyz() = FUNC_NAME(chopToInt(c.in[0].swizzle(2, 0, 1)), chopToInt(c.in[1].swizzle(1, 2, 0))).asFloat(); \
1809     }                                                                                                                  \
1810     void eval_##FUNC_NAME##_ivec4(ShaderEvalContext &c)                                                                \
1811     {                                                                                                                  \
1812         c.color = FUNC_NAME(chopToInt(c.in[0].swizzle(1, 2, 3, 0)), chopToInt(c.in[1].swizzle(3, 2, 1, 0))).asFloat(); \
1813     }
1814 
1815 #define DECLARE_UINT_COMPARE_FUNCS(FUNC_NAME)                                                                       \
1816     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                                              \
1817     {                                                                                                               \
1818         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x());                               \
1819     }                                                                                                               \
1820     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                             \
1821     {                                                                                                               \
1822         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint());             \
1823     }                                                                                                               \
1824     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                             \
1825     {                                                                                                               \
1826         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint());       \
1827     }                                                                                                               \
1828     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                             \
1829     {                                                                                                               \
1830         c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()); \
1831     }
1832 
1833 #define DECLARE_UINT_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                                \
1834     DECLARE_UINT_SCALAR_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                             \
1835     void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c)                                                            \
1836     {                                                                                                              \
1837         c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()).asFloat();        \
1838     }                                                                                                              \
1839     void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c)                                                            \
1840     {                                                                                                              \
1841         c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
1842     }                                                                                                              \
1843     void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c)                                                            \
1844     {                                                                                                              \
1845         c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat(); \
1846     }
1847 
1848 #define DECLARE_UINT_SCALAR_CWISE_COMPARE_FUNCS(FUNC_NAME)                            \
1849     void eval_##FUNC_NAME##_uint(ShaderEvalContext &c)                                \
1850     {                                                                                 \
1851         c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x()); \
1852     }
1853 
1854 #define DECLARE_BOOL_COMPARE_FUNCS(FUNC_NAME)                                                 \
1855     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                                        \
1856     {                                                                                         \
1857         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f);               \
1858     }                                                                                         \
1859     void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c)                                       \
1860     {                                                                                         \
1861         c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)),        \
1862                                        greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f)));       \
1863     }                                                                                         \
1864     void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c)                                       \
1865     {                                                                                         \
1866         c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)),     \
1867                                        greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f)));    \
1868     }                                                                                         \
1869     void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c)                                       \
1870     {                                                                                         \
1871         c.color.x() = (float)FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)),  \
1872                                        greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f))); \
1873     }
1874 
1875 #define DECLARE_BOOL_CWISE_COMPARE_FUNCS(FUNC_NAME)                             \
1876     void eval_##FUNC_NAME##_bool(ShaderEvalContext &c)                          \
1877     {                                                                           \
1878         c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f, c.in[1].x() > 0.0f); \
1879     }                                                                           \
1880     DECLARE_BOOL_VEC_CWISE_COMPARE_FUNCS(FUNC_NAME)
1881 
1882 #define DECLARE_BOOL_VEC_CWISE_COMPARE_FUNCS(FUNC_NAME)                                                               \
1883     void eval_##FUNC_NAME##_bvec2(ShaderEvalContext &c)                                                               \
1884     {                                                                                                                 \
1885         c.color.yz() =                                                                                                \
1886             FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)), greaterThan(c.in[1].swizzle(1, 0), Vec2(0.0f))) \
1887                 .asFloat();                                                                                           \
1888     }                                                                                                                 \
1889     void eval_##FUNC_NAME##_bvec3(ShaderEvalContext &c)                                                               \
1890     {                                                                                                                 \
1891         c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)),                                  \
1892                                   greaterThan(c.in[1].swizzle(1, 2, 0), Vec3(0.0f)))                                  \
1893                             .asFloat();                                                                               \
1894     }                                                                                                                 \
1895     void eval_##FUNC_NAME##_bvec4(ShaderEvalContext &c)                                                               \
1896     {                                                                                                                 \
1897         c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)),                                     \
1898                             greaterThan(c.in[1].swizzle(3, 2, 1, 0), Vec4(0.0f)))                                     \
1899                       .asFloat();                                                                                     \
1900     }
1901 
1902 DECLARE_FLOAT_COMPARE_FUNCS(allEqual)
1903 DECLARE_FLOAT_COMPARE_FUNCS(anyNotEqual)
1904 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThan)
1905 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThanEqual)
1906 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThan)
1907 DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThanEqual)
1908 DECLARE_FLOAT_VEC_CWISE_COMPARE_FUNCS(equal)
1909 DECLARE_FLOAT_VEC_CWISE_COMPARE_FUNCS(notEqual)
1910 
1911 DECLARE_INT_COMPARE_FUNCS(allEqual)
1912 DECLARE_INT_COMPARE_FUNCS(anyNotEqual)
1913 DECLARE_INT_CWISE_COMPARE_FUNCS(lessThan)
1914 DECLARE_INT_CWISE_COMPARE_FUNCS(lessThanEqual)
1915 DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThan)
1916 DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThanEqual)
1917 DECLARE_INT_VEC_CWISE_COMPARE_FUNCS(equal)
1918 DECLARE_INT_VEC_CWISE_COMPARE_FUNCS(notEqual)
1919 
1920 DECLARE_UINT_COMPARE_FUNCS(allEqual)
1921 DECLARE_UINT_COMPARE_FUNCS(anyNotEqual)
1922 DECLARE_UINT_SCALAR_CWISE_COMPARE_FUNCS(lessThan)
1923 DECLARE_UINT_SCALAR_CWISE_COMPARE_FUNCS(lessThanEqual)
1924 DECLARE_UINT_SCALAR_CWISE_COMPARE_FUNCS(greaterThan)
1925 DECLARE_UINT_SCALAR_CWISE_COMPARE_FUNCS(greaterThanEqual)
1926 
1927 DECLARE_BOOL_COMPARE_FUNCS(allEqual)
1928 DECLARE_BOOL_COMPARE_FUNCS(anyNotEqual)
1929 DECLARE_BOOL_VEC_CWISE_COMPARE_FUNCS(equal)
1930 DECLARE_BOOL_VEC_CWISE_COMPARE_FUNCS(notEqual)
1931 
1932 // Boolean functions.
1933 
1934 #define DECLARE_UNARY_SCALAR_BVEC_FUNCS(GLSL_NAME, FUNC_NAME)                                 \
1935     void eval_##GLSL_NAME##_bvec2(ShaderEvalContext &c)                                       \
1936     {                                                                                         \
1937         c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))));       \
1938     }                                                                                         \
1939     void eval_##GLSL_NAME##_bvec3(ShaderEvalContext &c)                                       \
1940     {                                                                                         \
1941         c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))));    \
1942     }                                                                                         \
1943     void eval_##GLSL_NAME##_bvec4(ShaderEvalContext &c)                                       \
1944     {                                                                                         \
1945         c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f)))); \
1946     }
1947 
1948 #define DECLARE_UNARY_BVEC_BVEC_FUNCS(GLSL_NAME, FUNC_NAME)                                         \
1949     void eval_##GLSL_NAME##_bvec2(ShaderEvalContext &c)                                             \
1950     {                                                                                               \
1951         c.color.yz() = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat();         \
1952     }                                                                                               \
1953     void eval_##GLSL_NAME##_bvec3(ShaderEvalContext &c)                                             \
1954     {                                                                                               \
1955         c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat();     \
1956     }                                                                                               \
1957     void eval_##GLSL_NAME##_bvec4(ShaderEvalContext &c)                                             \
1958     {                                                                                               \
1959         c.color.xyzw() = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f))).asFloat(); \
1960     }
1961 
1962 DECLARE_UNARY_SCALAR_BVEC_FUNCS(any, boolAny)
1963 DECLARE_UNARY_SCALAR_BVEC_FUNCS(all, boolAll)
1964 
1965 // ShaderOperatorTests.
1966 
1967 class ShaderOperatorTests : public tcu::TestCaseGroup
1968 {
1969 public:
1970     ShaderOperatorTests(tcu::TestContext &context);
1971     virtual ~ShaderOperatorTests(void);
1972 
1973     virtual void init(void);
1974 
1975 private:
1976     ShaderOperatorTests(const ShaderOperatorTests &);            // not allowed!
1977     ShaderOperatorTests &operator=(const ShaderOperatorTests &); // not allowed!
1978 };
1979 
ShaderOperatorTests(tcu::TestContext & testCtx)1980 ShaderOperatorTests::ShaderOperatorTests(tcu::TestContext &testCtx) : TestCaseGroup(testCtx, "operator")
1981 {
1982 }
1983 
~ShaderOperatorTests(void)1984 ShaderOperatorTests::~ShaderOperatorTests(void)
1985 {
1986 }
1987 
init(void)1988 void ShaderOperatorTests::init(void)
1989 {
1990 #define BOOL_FUNCS(FUNC_NAME) eval_##FUNC_NAME##_bool, DE_NULL, DE_NULL, DE_NULL
1991 
1992 #define FLOAT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
1993 #define INT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
1994 #define UINT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_uvec2, eval_##FUNC_NAME##_uvec3, eval_##FUNC_NAME##_uvec4
1995 #define BOOL_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
1996 
1997 #define FLOAT_GENTYPE_FUNCS(FUNC_NAME) \
1998     eval_##FUNC_NAME##_float, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
1999 #define INT_GENTYPE_FUNCS(FUNC_NAME) \
2000     eval_##FUNC_NAME##_int, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
2001 #define UINT_GENTYPE_FUNCS(FUNC_NAME) \
2002     eval_##FUNC_NAME##_uint, eval_##FUNC_NAME##_uvec2, eval_##FUNC_NAME##_uvec3, eval_##FUNC_NAME##_uvec4
2003 #define BOOL_GENTYPE_FUNCS(FUNC_NAME) \
2004     eval_##FUNC_NAME##_bool, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
2005 
2006     // Shorthands.
2007     Value notUsed = Value(VALUE_NONE, 0.0f, 0.0f);
2008 
2009     std::vector<BuiltinFuncGroup> funcInfoGroups;
2010 
2011     // Unary operators.
2012     funcInfoGroups.push_back(
2013         BuiltinFuncGroup("unary_operator", "Unary operator tests")
2014         << BuiltinOperInfo("minus", "-", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL,
2015                            FLOAT_GENTYPE_FUNCS(negate))
2016         << BuiltinOperInfo("minus", "-", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL,
2017                            INT_GENTYPE_FUNCS(negate))
2018         << BuiltinOperInfo("minus", "-", UGT, Value(UGT, 0.0f, 4e9f), notUsed, notUsed, 2e-10f, 0.0f, PRECMASK_HIGHP,
2019                            UINT_GENTYPE_FUNCS(negate))
2020         << BuiltinOperInfo("not", "!", B, Value(B, -1.0f, 1.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_NA,
2021                            eval_boolNot_bool, DE_NULL, DE_NULL, DE_NULL)
2022         << BuiltinOperInfo("bitwise_not", "~", IGT, Value(IGT, -1e5f, 1e5f), notUsed, notUsed, 5e-5f, 0.5f,
2023                            PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseNot))
2024         << BuiltinOperInfo("bitwise_not", "~", UGT, Value(UGT, 0.0f, 2e9f), notUsed, notUsed, 2e-10f, 0.0f,
2025                            PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseNot))
2026 
2027         // Pre/post incr/decr side effect cases.
2028         << BuiltinSideEffOperInfo("pre_increment_effect", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
2029                                   0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
2030         << BuiltinSideEffOperInfo("pre_increment_effect", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed, 0.1f,
2031                                   0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
2032         << BuiltinSideEffOperInfo("pre_increment_effect", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed, 0.1f,
2033                                   0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(addOne))
2034         << BuiltinSideEffOperInfo("pre_decrement_effect", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
2035                                   1.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
2036         << BuiltinSideEffOperInfo("pre_decrement_effect", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed, 0.1f,
2037                                   0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
2038         << BuiltinSideEffOperInfo("pre_decrement_effect", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed, 0.1f,
2039                                   0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(subOne))
2040         << BuiltinPostSideEffOperInfo("post_increment_effect", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
2041                                       0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
2042         << BuiltinPostSideEffOperInfo("post_increment_effect", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed,
2043                                       0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
2044         << BuiltinPostSideEffOperInfo("post_increment_effect", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed,
2045                                       0.1f, 0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(addOne))
2046         << BuiltinPostSideEffOperInfo("post_decrement_effect", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f,
2047                                       1.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
2048         << BuiltinPostSideEffOperInfo("post_decrement_effect", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed,
2049                                       0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
2050         << BuiltinPostSideEffOperInfo("post_decrement_effect", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed,
2051                                       0.1f, 0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(subOne))
2052 
2053         // Pre/post incr/decr result cases.
2054         << BuiltinOperInfo("pre_increment_result", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.0f,
2055                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
2056         << BuiltinOperInfo("pre_increment_result", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed, 0.1f, 0.5f,
2057                            PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
2058         << BuiltinOperInfo("pre_increment_result", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed, 0.1f, 0.0f,
2059                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(addOne))
2060         << BuiltinOperInfo("pre_decrement_result", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 1.0f,
2061                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
2062         << BuiltinOperInfo("pre_decrement_result", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed, 0.1f, 0.5f,
2063                            PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
2064         << BuiltinOperInfo("pre_decrement_result", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed, 0.1f, 0.0f,
2065                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(subOne))
2066         << BuiltinPostOperInfo("post_increment_result", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f,
2067                                PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(nop))
2068         << BuiltinPostOperInfo("post_increment_result", "++", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f,
2069                                0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(nop))
2070         << BuiltinPostOperInfo("post_increment_result", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed, 0.1f, 0.0f,
2071                                PRECMASK_ALL, UINT_GENTYPE_FUNCS(nop))
2072         << BuiltinPostOperInfo("post_decrement_result", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f,
2073                                PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(nop))
2074         << BuiltinPostOperInfo("post_decrement_result", "--", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f,
2075                                0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(nop))
2076         << BuiltinPostOperInfo("post_decrement_result", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed, 0.1f,
2077                                0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(nop)));
2078 
2079     BuiltinFuncGroup binaryOpGroup("binary_operator", "Binary operator tests");
2080 
2081     // Normal binary operations and their corresponding assignment operations have lots in common; generate both in the following loop.
2082 
2083     for (int binaryOperatorType = 0; binaryOperatorType <= 2;
2084          binaryOperatorType++) // 0: normal op test, 1: assignment op side-effect test, 2: assignment op result test
2085     {
2086         const bool isNormalOp  = binaryOperatorType == 0;
2087         const bool isAssignEff = binaryOperatorType == 1;
2088         const bool isAssignRes = binaryOperatorType == 2;
2089 
2090         DE_ASSERT(isNormalOp || isAssignEff || isAssignRes);
2091         DE_UNREF(isAssignRes);
2092 
2093         const char *addName        = isNormalOp ? "add" : isAssignEff ? "add_assign_effect" : "add_assign_result";
2094         const char *subName        = isNormalOp ? "sub" : isAssignEff ? "sub_assign_effect" : "sub_assign_result";
2095         const char *mulName        = isNormalOp ? "mul" : isAssignEff ? "mul_assign_effect" : "mul_assign_result";
2096         const char *divName        = isNormalOp ? "div" : isAssignEff ? "div_assign_effect" : "div_assign_result";
2097         const char *modName        = isNormalOp ? "mod" : isAssignEff ? "mod_assign_effect" : "mod_assign_result";
2098         const char *andName        = isNormalOp  ? "bitwise_and" :
2099                                      isAssignEff ? "bitwise_and_assign_effect" :
2100                                                    "bitwise_and_assign_result";
2101         const char *orName         = isNormalOp  ? "bitwise_or" :
2102                                      isAssignEff ? "bitwise_or_assign_effect" :
2103                                                    "bitwise_or_assign_result";
2104         const char *xorName        = isNormalOp  ? "bitwise_xor" :
2105                                      isAssignEff ? "bitwise_xor_assign_effect" :
2106                                                    "bitwise_xor_assign_result";
2107         const char *leftShiftName  = isNormalOp  ? "left_shift" :
2108                                      isAssignEff ? "left_shift_assign_effect" :
2109                                                    "left_shift_assign_result";
2110         const char *rightShiftName = isNormalOp  ? "right_shift" :
2111                                      isAssignEff ? "right_shift_assign_effect" :
2112                                                    "right_shift_assign_result";
2113         const char *addOp          = isNormalOp ? "+" : "+=";
2114         const char *subOp          = isNormalOp ? "-" : "-=";
2115         const char *mulOp          = isNormalOp ? "*" : "*=";
2116         const char *divOp          = isNormalOp ? "/" : "/=";
2117         const char *modOp          = isNormalOp ? "%" : "%=";
2118         const char *andOp          = isNormalOp ? "&" : "&=";
2119         const char *orOp           = isNormalOp ? "|" : "|=";
2120         const char *xorOp          = isNormalOp ? "^" : "^=";
2121         const char *leftShiftOp    = isNormalOp ? "<<" : "<<=";
2122         const char *rightShiftOp   = isNormalOp ? ">>" : ">>=";
2123 
2124         // Pointer to appropriate OperInfo function.
2125         BuiltinFuncInfo (*operInfoFunc)(const char *, const char *, ValueType, Value, Value, Value, const float,
2126                                         const float, uint32_t, ShaderEvalFunc, ShaderEvalFunc, ShaderEvalFunc,
2127                                         ShaderEvalFunc) = isAssignEff ? BuiltinSideEffOperInfo : BuiltinOperInfo;
2128 
2129         DE_ASSERT(operInfoFunc != DE_NULL);
2130 
2131         // The following cases will be added for each operator, precision and fundamental type (float, int, uint) combination, where applicable:
2132         // gentype <op> gentype
2133         // vector <op> scalar
2134         // For normal (non-assigning) operators only:
2135         //   scalar <op> vector
2136 
2137         // The add operator.
2138 
2139         binaryOpGroup << operInfoFunc(addName, addOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f,
2140                                       0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(add))
2141                       << operInfoFunc(addName, addOp, IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed,
2142                                       0.1f, 0.5f, PRECMASK_MEDIUMP, INT_GENTYPE_FUNCS(add))
2143                       << operInfoFunc(addName, addOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2144                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(add))
2145                       << operInfoFunc(addName, addOp, UGT, Value(UGT, 0.0f, 1e2f), Value(UGT, 0.0f, 1e2f), notUsed,
2146                                       5e-3f, 0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(add))
2147                       << operInfoFunc(addName, addOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2148                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(add))
2149                       << operInfoFunc(addName, addOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
2150                                       0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(addVecScalar))
2151                       << operInfoFunc(addName, addOp, IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f,
2152                                       0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(addVecScalar))
2153                       << operInfoFunc(addName, addOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
2154                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(addVecScalar))
2155                       << operInfoFunc(addName, addOp, UV, Value(UV, 0.0f, 1e2f), Value(U, 0.0f, 1e2f), notUsed, 5e-3f,
2156                                       0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(addVecScalar))
2157                       << operInfoFunc(addName, addOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2158                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(addVecScalar));
2159 
2160         if (isNormalOp)
2161             binaryOpGroup << operInfoFunc(addName, addOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
2162                                           1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(addScalarVec))
2163                           << operInfoFunc(addName, addOp, IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed,
2164                                           0.1f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(addScalarVec))
2165                           << operInfoFunc(addName, addOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2166                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(addScalarVec))
2167                           << operInfoFunc(addName, addOp, UV, Value(U, 0.0f, 1e2f), Value(UV, 0.0f, 1e2f), notUsed,
2168                                           5e-3f, 0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(addScalarVec))
2169                           << operInfoFunc(addName, addOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2170                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(addScalarVec));
2171 
2172         // The subtract operator.
2173 
2174         binaryOpGroup << operInfoFunc(subName, subOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f,
2175                                       0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(sub))
2176                       << operInfoFunc(subName, subOp, IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed,
2177                                       0.1f, 0.5f, PRECMASK_MEDIUMP, INT_GENTYPE_FUNCS(sub))
2178                       << operInfoFunc(subName, subOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2179                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(sub))
2180                       << operInfoFunc(subName, subOp, UGT, Value(UGT, 1e2f, 2e2f), Value(UGT, 0.0f, 1e2f), notUsed,
2181                                       5e-3f, 0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(sub))
2182                       << operInfoFunc(subName, subOp, UGT, Value(UGT, .5e9f, 3.7e9f), Value(UGT, 0.0f, 3.9e9f), notUsed,
2183                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(sub))
2184                       << operInfoFunc(subName, subOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
2185                                       0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(subVecScalar))
2186                       << operInfoFunc(subName, subOp, IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f,
2187                                       0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(subVecScalar))
2188                       << operInfoFunc(subName, subOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
2189                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(subVecScalar))
2190                       << operInfoFunc(subName, subOp, UV, Value(UV, 1e2f, 2e2f), Value(U, 0.0f, 1e2f), notUsed, 5e-3f,
2191                                       0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(subVecScalar))
2192                       << operInfoFunc(subName, subOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2193                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(subVecScalar));
2194 
2195         if (isNormalOp)
2196             binaryOpGroup << operInfoFunc(subName, subOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
2197                                           1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(subScalarVec))
2198                           << operInfoFunc(subName, subOp, IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed,
2199                                           0.1f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(subScalarVec))
2200                           << operInfoFunc(subName, subOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2201                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(subScalarVec))
2202                           << operInfoFunc(subName, subOp, UV, Value(U, 1e2f, 2e2f), Value(UV, 0.0f, 1e2f), notUsed,
2203                                           5e-3f, 0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(subScalarVec))
2204                           << operInfoFunc(subName, subOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2205                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(subScalarVec));
2206 
2207         // The multiply operator.
2208 
2209         binaryOpGroup << operInfoFunc(mulName, mulOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f,
2210                                       0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(mul))
2211                       << operInfoFunc(mulName, mulOp, IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed,
2212                                       0.1f, 0.5f, PRECMASK_MEDIUMP, INT_GENTYPE_FUNCS(mul))
2213                       << operInfoFunc(mulName, mulOp, IGT, Value(IGT, -3e5f, 3e5f), Value(IGT, -3e4f, 3e4f), notUsed,
2214                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(mul))
2215                       << operInfoFunc(mulName, mulOp, UGT, Value(UGT, 0.0f, 16.0f), Value(UGT, 0.0f, 16.0f), notUsed,
2216                                       4e-3f, 0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(mul))
2217                       << operInfoFunc(mulName, mulOp, UGT, Value(UGT, 0.0f, 6e5f), Value(UGT, 0.0f, 6e4f), notUsed,
2218                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(mul))
2219                       << operInfoFunc(mulName, mulOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
2220                                       0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mulVecScalar))
2221                       << operInfoFunc(mulName, mulOp, IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f,
2222                                       0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(mulVecScalar))
2223                       << operInfoFunc(mulName, mulOp, IV, Value(IV, -3e5f, 3e5f), Value(I, -3e4f, 3e4f), notUsed,
2224                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(mulVecScalar))
2225                       << operInfoFunc(mulName, mulOp, UV, Value(UV, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 4e-3f,
2226                                       0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(mulVecScalar))
2227                       << operInfoFunc(mulName, mulOp, UV, Value(UV, 0.0f, 6e5f), Value(U, 0.0f, 6e4f), notUsed, 2e-10f,
2228                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(mulVecScalar));
2229 
2230         if (isNormalOp)
2231             binaryOpGroup << operInfoFunc(mulName, mulOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
2232                                           1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mulScalarVec))
2233                           << operInfoFunc(mulName, mulOp, IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed,
2234                                           0.1f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(mulScalarVec))
2235                           << operInfoFunc(mulName, mulOp, IV, Value(I, -3e5f, 3e5f), Value(IV, -3e4f, 3e4f), notUsed,
2236                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(mulScalarVec))
2237                           << operInfoFunc(mulName, mulOp, UV, Value(U, 0.0f, 16.0f), Value(UV, 0.0f, 16.0f), notUsed,
2238                                           4e-3f, 0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(mulScalarVec))
2239                           << operInfoFunc(mulName, mulOp, UV, Value(U, 0.0f, 6e5f), Value(UV, 0.0f, 6e4f), notUsed,
2240                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(mulScalarVec));
2241 
2242         // The divide operator.
2243 
2244         binaryOpGroup << operInfoFunc(divName, divOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -2.0f, -0.5f), notUsed,
2245                                       1.0f, 0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(div))
2246                       << operInfoFunc(divName, divOp, IGT, Value(IGT, 24.0f, 24.0f), Value(IGT, -4.0f, -1.0f), notUsed,
2247                                       0.04f, 1.0f, PRECMASK_MEDIUMP, INT_GENTYPE_FUNCS(div))
2248                       << operInfoFunc(divName, divOp, IGT, Value(IGT, 40320.0f, 40320.0f), Value(IGT, -8.0f, -1.0f),
2249                                       notUsed, 1e-5f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(div))
2250                       << operInfoFunc(divName, divOp, UGT, Value(UGT, 0.0f, 24.0f), Value(UGT, 1.0f, 4.0f), notUsed,
2251                                       0.04f, 0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(div))
2252                       << operInfoFunc(divName, divOp, UGT, Value(UGT, 0.0f, 40320.0f), Value(UGT, 1.0f, 8.0f), notUsed,
2253                                       1e-5f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(div))
2254                       << operInfoFunc(divName, divOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -2.0f, -0.5f), notUsed, 1.0f,
2255                                       0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(divVecScalar))
2256                       << operInfoFunc(divName, divOp, IV, Value(IV, 24.0f, 24.0f), Value(I, -4.0f, -1.0f), notUsed,
2257                                       0.04f, 1.0f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(divVecScalar))
2258                       << operInfoFunc(divName, divOp, IV, Value(IV, 40320.0f, 40320.0f), Value(I, -8.0f, -1.0f),
2259                                       notUsed, 1e-5f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(divVecScalar))
2260                       << operInfoFunc(divName, divOp, UV, Value(UV, 0.0f, 24.0f), Value(U, 1.0f, 4.0f), notUsed, 0.04f,
2261                                       0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(divVecScalar))
2262                       << operInfoFunc(divName, divOp, UV, Value(UV, 0.0f, 40320.0f), Value(U, 1.0f, 8.0f), notUsed,
2263                                       1e-5f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(divVecScalar));
2264 
2265         if (isNormalOp)
2266             binaryOpGroup << operInfoFunc(divName, divOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -2.0f, -0.5f), notUsed,
2267                                           1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(divScalarVec))
2268                           << operInfoFunc(divName, divOp, IV, Value(I, 24.0f, 24.0f), Value(IV, -4.0f, -1.0f), notUsed,
2269                                           0.04f, 1.0f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(divScalarVec))
2270                           << operInfoFunc(divName, divOp, IV, Value(I, 40320.0f, 40320.0f), Value(IV, -8.0f, -1.0f),
2271                                           notUsed, 1e-5f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(divScalarVec))
2272                           << operInfoFunc(divName, divOp, UV, Value(U, 0.0f, 24.0f), Value(UV, 1.0f, 4.0f), notUsed,
2273                                           0.04f, 0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(divScalarVec))
2274                           << operInfoFunc(divName, divOp, UV, Value(U, 0.0f, 40320.0f), Value(UV, 1.0f, 8.0f), notUsed,
2275                                           1e-5f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(divScalarVec));
2276 
2277         // The modulus operator.
2278 
2279         binaryOpGroup << operInfoFunc(modName, modOp, IGT, Value(IGT, 0.0f, 6.0f), Value(IGT, 1.1f, 6.1f), notUsed,
2280                                       0.25f, 0.5f, PRECMASK_MEDIUMP, INT_GENTYPE_FUNCS(mod))
2281                       << operInfoFunc(modName, modOp, IGT, Value(IGT, 0.0f, 14.0f), Value(IGT, 1.1f, 11.1f), notUsed,
2282                                       0.1f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(mod))
2283                       << operInfoFunc(modName, modOp, UGT, Value(UGT, 0.0f, 6.0f), Value(UGT, 1.1f, 6.1f), notUsed,
2284                                       0.25f, 0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(mod))
2285                       << operInfoFunc(modName, modOp, UGT, Value(UGT, 0.0f, 24.0f), Value(UGT, 1.1f, 11.1f), notUsed,
2286                                       0.1f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(mod))
2287                       << operInfoFunc(modName, modOp, IV, Value(IV, 0.0f, 6.0f), Value(I, 1.1f, 6.1f), notUsed, 0.25f,
2288                                       0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(modVecScalar))
2289                       << operInfoFunc(modName, modOp, IV, Value(IV, 0.0f, 6.0f), Value(I, 1.1f, 11.1f), notUsed, 0.1f,
2290                                       0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(modVecScalar))
2291                       << operInfoFunc(modName, modOp, UV, Value(UV, 0.0f, 6.0f), Value(U, 1.1f, 6.1f), notUsed, 0.25f,
2292                                       0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(modVecScalar))
2293                       << operInfoFunc(modName, modOp, UV, Value(UV, 0.0f, 24.0f), Value(U, 1.1f, 11.1f), notUsed, 0.1f,
2294                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(modVecScalar));
2295 
2296         if (isNormalOp)
2297             binaryOpGroup << operInfoFunc(modName, modOp, IV, Value(I, 0.0f, 6.0f), Value(IV, 1.1f, 6.1f), notUsed,
2298                                           0.25f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(modScalarVec))
2299                           << operInfoFunc(modName, modOp, IV, Value(I, 0.0f, 6.0f), Value(IV, 1.1f, 11.1f), notUsed,
2300                                           0.1f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(modScalarVec))
2301                           << operInfoFunc(modName, modOp, UV, Value(U, 0.0f, 6.0f), Value(UV, 1.1f, 6.1f), notUsed,
2302                                           0.25f, 0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(modScalarVec))
2303                           << operInfoFunc(modName, modOp, UV, Value(U, 0.0f, 24.0f), Value(UV, 1.1f, 11.1f), notUsed,
2304                                           0.1f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(modScalarVec));
2305 
2306         // The bitwise and operator.
2307 
2308         binaryOpGroup << operInfoFunc(andName, andOp, IGT, Value(IGT, -16.0f, 16.0f), Value(IGT, -16.0f, 16.0f),
2309                                       notUsed, 0.03f, 0.5f, PRECMASK_MEDIUMP, INT_GENTYPE_FUNCS(bitwiseAnd))
2310                       << operInfoFunc(andName, andOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2311                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseAnd))
2312                       << operInfoFunc(andName, andOp, UGT, Value(UGT, 0.0f, 32.0f), Value(UGT, 0.0f, 32.0f), notUsed,
2313                                       0.03f, 0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(bitwiseAnd))
2314                       << operInfoFunc(andName, andOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2315                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseAnd))
2316                       << operInfoFunc(andName, andOp, IV, Value(IV, -16.0f, 16.0f), Value(I, -16.0f, 16.0f), notUsed,
2317                                       0.03f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(bitwiseAndVecScalar))
2318                       << operInfoFunc(andName, andOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
2319                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseAndVecScalar))
2320                       << operInfoFunc(andName, andOp, UV, Value(UV, 0.0f, 32.0f), Value(U, 0.0f, 32.0f), notUsed, 0.03f,
2321                                       0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(bitwiseAndVecScalar))
2322                       << operInfoFunc(andName, andOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2323                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseAndVecScalar));
2324 
2325         if (isNormalOp)
2326             binaryOpGroup << operInfoFunc(andName, andOp, IV, Value(I, -16.0f, 16.0f), Value(IV, -16.0f, 16.0f),
2327                                           notUsed, 0.03f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(bitwiseAndScalarVec))
2328                           << operInfoFunc(andName, andOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2329                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseAndScalarVec))
2330                           << operInfoFunc(andName, andOp, UV, Value(U, 0.0f, 32.0f), Value(UV, 0.0f, 32.0f), notUsed,
2331                                           0.03f, 0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(bitwiseAndScalarVec))
2332                           << operInfoFunc(andName, andOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2333                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseAndScalarVec));
2334 
2335         // The bitwise or operator.
2336 
2337         binaryOpGroup << operInfoFunc(orName, orOp, IGT, Value(IGT, -16.0f, 16.0f), Value(IGT, -16.0f, 16.0f), notUsed,
2338                                       0.03f, 0.5f, PRECMASK_MEDIUMP, INT_GENTYPE_FUNCS(bitwiseOr))
2339                       << operInfoFunc(orName, orOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2340                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseOr))
2341                       << operInfoFunc(orName, orOp, UGT, Value(UGT, 0.0f, 32.0f), Value(UGT, 0.0f, 32.0f), notUsed,
2342                                       0.03f, 0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(bitwiseOr))
2343                       << operInfoFunc(orName, orOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2344                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseOr))
2345                       << operInfoFunc(orName, orOp, IV, Value(IV, -16.0f, 16.0f), Value(I, -16.0f, 16.0f), notUsed,
2346                                       0.03f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(bitwiseOrVecScalar))
2347                       << operInfoFunc(orName, orOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed, 4e-10f,
2348                                       0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseOrVecScalar))
2349                       << operInfoFunc(orName, orOp, UV, Value(UV, 0.0f, 32.0f), Value(U, 0.0f, 32.0f), notUsed, 0.03f,
2350                                       0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(bitwiseOrVecScalar))
2351                       << operInfoFunc(orName, orOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2352                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseOrVecScalar));
2353 
2354         if (isNormalOp)
2355             binaryOpGroup << operInfoFunc(orName, orOp, IV, Value(I, -16.0f, 16.0f), Value(IV, -16.0f, 16.0f), notUsed,
2356                                           0.03f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(bitwiseOrScalarVec))
2357                           << operInfoFunc(orName, orOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2358                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseOrScalarVec))
2359                           << operInfoFunc(orName, orOp, UV, Value(U, 0.0f, 32.0f), Value(UV, 0.0f, 32.0f), notUsed,
2360                                           0.03f, 0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(bitwiseOrScalarVec))
2361                           << operInfoFunc(orName, orOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2362                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseOrScalarVec));
2363 
2364         // The bitwise xor operator.
2365 
2366         binaryOpGroup << operInfoFunc(xorName, xorOp, IGT, Value(IGT, -16.0f, 16.0f), Value(IGT, -16.0f, 16.0f),
2367                                       notUsed, 0.03f, 0.5f, PRECMASK_MEDIUMP, INT_GENTYPE_FUNCS(bitwiseXor))
2368                       << operInfoFunc(xorName, xorOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
2369                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseXor))
2370                       << operInfoFunc(xorName, xorOp, UGT, Value(UGT, 0.0f, 32.0f), Value(UGT, 0.0f, 32.0f), notUsed,
2371                                       0.03f, 0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(bitwiseXor))
2372                       << operInfoFunc(xorName, xorOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2373                                       2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseXor))
2374                       << operInfoFunc(xorName, xorOp, IV, Value(IV, -16.0f, 16.0f), Value(I, -16.0f, 16.0f), notUsed,
2375                                       0.03f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(bitwiseXorVecScalar))
2376                       << operInfoFunc(xorName, xorOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
2377                                       4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseXorVecScalar))
2378                       << operInfoFunc(xorName, xorOp, UV, Value(UV, 0.0f, 32.0f), Value(U, 0.0f, 32.0f), notUsed, 0.03f,
2379                                       0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(bitwiseXorVecScalar))
2380                       << operInfoFunc(xorName, xorOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
2381                                       0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseXorVecScalar));
2382 
2383         if (isNormalOp)
2384             binaryOpGroup << operInfoFunc(xorName, xorOp, IV, Value(I, -16.0f, 16.0f), Value(IV, -16.0f, 16.0f),
2385                                           notUsed, 0.03f, 0.5f, PRECMASK_MEDIUMP, INT_VEC_FUNCS(bitwiseXorScalarVec))
2386                           << operInfoFunc(xorName, xorOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
2387                                           4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseXorScalarVec))
2388                           << operInfoFunc(xorName, xorOp, UV, Value(U, 0.0f, 32.0f), Value(UV, 0.0f, 32.0f), notUsed,
2389                                           0.03f, 0.0f, PRECMASK_MEDIUMP, UINT_VEC_FUNCS(bitwiseXorScalarVec))
2390                           << operInfoFunc(xorName, xorOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2391                                           2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseXorScalarVec));
2392 
2393         // The left shift operator. Second operand (shift amount) can be either int or uint, even for uint and int first operand, respectively.
2394 
2395         for (int isSignedAmount = 0; isSignedAmount <= 1; isSignedAmount++)
2396         {
2397             ValueType gType = isSignedAmount == 0 ? UGT : IGT;
2398             ValueType sType = isSignedAmount == 0 ? U : I;
2399             binaryOpGroup << operInfoFunc(leftShiftName, leftShiftOp, IGT, Value(IGT, -7.0f, 7.0f),
2400                                           Value(gType, 0.0f, 4.0f), notUsed, 4e-3f, 0.5f, PRECMASK_MEDIUMP,
2401                                           INT_GENTYPE_FUNCS(leftShift))
2402                           << operInfoFunc(leftShiftName, leftShiftOp, IGT, Value(IGT, -7.0f, 7.0f),
2403                                           Value(gType, 0.0f, 27.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
2404                                           INT_GENTYPE_FUNCS(leftShift))
2405                           << operInfoFunc(leftShiftName, leftShiftOp, UGT, Value(UGT, 0.0f, 7.0f),
2406                                           Value(gType, 0.0f, 5.0f), notUsed, 4e-3f, 0.0f, PRECMASK_MEDIUMP,
2407                                           UINT_GENTYPE_FUNCS(leftShift))
2408                           << operInfoFunc(leftShiftName, leftShiftOp, UGT, Value(UGT, 0.0f, 7.0f),
2409                                           Value(gType, 0.0f, 28.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
2410                                           UINT_GENTYPE_FUNCS(leftShift))
2411                           << operInfoFunc(leftShiftName, leftShiftOp, IV, Value(IV, -7.0f, 7.0f),
2412                                           Value(sType, 0.0f, 4.0f), notUsed, 4e-3f, 0.5f, PRECMASK_MEDIUMP,
2413                                           INT_VEC_FUNCS(leftShiftVecScalar))
2414                           << operInfoFunc(leftShiftName, leftShiftOp, IV, Value(IV, -7.0f, 7.0f),
2415                                           Value(sType, 0.0f, 27.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
2416                                           INT_VEC_FUNCS(leftShiftVecScalar))
2417                           << operInfoFunc(leftShiftName, leftShiftOp, UV, Value(UV, 0.0f, 7.0f),
2418                                           Value(sType, 0.0f, 5.0f), notUsed, 4e-3f, 0.0f, PRECMASK_MEDIUMP,
2419                                           UINT_VEC_FUNCS(leftShiftVecScalar))
2420                           << operInfoFunc(leftShiftName, leftShiftOp, UV, Value(UV, 0.0f, 7.0f),
2421                                           Value(sType, 0.0f, 28.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
2422                                           UINT_VEC_FUNCS(leftShiftVecScalar));
2423         }
2424 
2425         // The right shift operator. Second operand (shift amount) can be either int or uint, even for uint and int first operand, respectively.
2426 
2427         for (int isSignedAmount = 0; isSignedAmount <= 1; isSignedAmount++)
2428         {
2429             ValueType gType = isSignedAmount == 0 ? UGT : IGT;
2430             ValueType sType = isSignedAmount == 0 ? U : I;
2431             binaryOpGroup << operInfoFunc(rightShiftName, rightShiftOp, IGT, Value(IGT, -127.0f, 127.0f),
2432                                           Value(gType, 0.0f, 8.0f), notUsed, 4e-3f, 0.5f, PRECMASK_MEDIUMP,
2433                                           INT_GENTYPE_FUNCS(rightShift))
2434                           << operInfoFunc(rightShiftName, rightShiftOp, IGT, Value(IGT, -2e9f, 2e9f),
2435                                           Value(gType, 0.0f, 31.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
2436                                           INT_GENTYPE_FUNCS(rightShift))
2437                           << operInfoFunc(rightShiftName, rightShiftOp, UGT, Value(UGT, 0.0f, 255.0f),
2438                                           Value(gType, 0.0f, 8.0f), notUsed, 4e-3f, 0.0f, PRECMASK_MEDIUMP,
2439                                           UINT_GENTYPE_FUNCS(rightShift))
2440                           << operInfoFunc(rightShiftName, rightShiftOp, UGT, Value(UGT, 0.0f, 4e9f),
2441                                           Value(gType, 0.0f, 31.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
2442                                           UINT_GENTYPE_FUNCS(rightShift))
2443                           << operInfoFunc(rightShiftName, rightShiftOp, IV, Value(IV, -127.0f, 127.0f),
2444                                           Value(sType, 0.0f, 8.0f), notUsed, 4e-3f, 0.5f, PRECMASK_MEDIUMP,
2445                                           INT_VEC_FUNCS(rightShiftVecScalar))
2446                           << operInfoFunc(rightShiftName, rightShiftOp, IV, Value(IV, -2e9f, 2e9f),
2447                                           Value(sType, 0.0f, 31.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
2448                                           INT_VEC_FUNCS(rightShiftVecScalar))
2449                           << operInfoFunc(rightShiftName, rightShiftOp, UV, Value(UV, 0.0f, 255.0f),
2450                                           Value(sType, 0.0f, 8.0f), notUsed, 4e-3f, 0.0f, PRECMASK_MEDIUMP,
2451                                           UINT_VEC_FUNCS(rightShiftVecScalar))
2452                           << operInfoFunc(rightShiftName, rightShiftOp, UV, Value(UV, 0.0f, 4e9f),
2453                                           Value(sType, 0.0f, 31.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
2454                                           UINT_VEC_FUNCS(rightShiftVecScalar));
2455         }
2456     }
2457 
2458     // Rest of binary operators.
2459 
2460     binaryOpGroup
2461         // Scalar relational operators.
2462         << BuiltinOperInfo("less", "<", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2463                            PRECMASK_ALL, eval_lessThan_float, DE_NULL, DE_NULL, DE_NULL)
2464         << BuiltinOperInfo("less", "<", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
2465                            PRECMASK_ALL, eval_lessThan_int, DE_NULL, DE_NULL, DE_NULL)
2466         << BuiltinOperInfo("less", "<", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f, 0.0f,
2467                            PRECMASK_ALL, eval_lessThan_uint, DE_NULL, DE_NULL, DE_NULL)
2468         << BuiltinOperInfo("less_or_equal", "<=", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2469                            PRECMASK_ALL, eval_lessThanEqual_float, DE_NULL, DE_NULL, DE_NULL)
2470         << BuiltinOperInfo("less_or_equal", "<=", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
2471                            PRECMASK_ALL, eval_lessThanEqual_int, DE_NULL, DE_NULL, DE_NULL)
2472         << BuiltinOperInfo("less_or_equal", "<=", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f, 0.0f,
2473                            PRECMASK_ALL, eval_lessThanEqual_uint, DE_NULL, DE_NULL, DE_NULL)
2474         << BuiltinOperInfo("greater", ">", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2475                            PRECMASK_ALL, eval_greaterThan_float, DE_NULL, DE_NULL, DE_NULL)
2476         << BuiltinOperInfo("greater", ">", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
2477                            PRECMASK_ALL, eval_greaterThan_int, DE_NULL, DE_NULL, DE_NULL)
2478         << BuiltinOperInfo("greater", ">", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f, 0.0f,
2479                            PRECMASK_ALL, eval_greaterThan_uint, DE_NULL, DE_NULL, DE_NULL)
2480         << BuiltinOperInfo("greater_or_equal", ">=", B, Value(F, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
2481                            0.0f, PRECMASK_ALL, eval_greaterThanEqual_float, DE_NULL, DE_NULL, DE_NULL)
2482         << BuiltinOperInfo("greater_or_equal", ">=", B, Value(I, -5.0f, 5.0f), Value(I, -5.0f, 5.0f), notUsed, 1.0f,
2483                            0.0f, PRECMASK_ALL, eval_greaterThanEqual_int, DE_NULL, DE_NULL, DE_NULL)
2484         << BuiltinOperInfo("greater_or_equal", ">=", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f,
2485                            0.0f, PRECMASK_ALL, eval_greaterThanEqual_uint, DE_NULL, DE_NULL, DE_NULL)
2486 
2487         // Equality comparison operators.
2488         << BuiltinOperInfo("equal", "==", B, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2489                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(allEqual))
2490         << BuiltinOperInfo("equal", "==", B, Value(IGT, -5.5f, 4.7f), Value(IGT, -2.1f, 0.1f), notUsed, 1.0f, 0.0f,
2491                            PRECMASK_ALL, INT_GENTYPE_FUNCS(allEqual))
2492         << BuiltinOperInfo("equal", "==", B, Value(UGT, 0.0f, 8.0f), Value(UGT, 3.5f, 4.5f), notUsed, 1.0f, 0.0f,
2493                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(allEqual))
2494         << BuiltinOperInfo("equal", "==", B, Value(BGT, -2.1f, 2.1f), Value(BGT, -1.1f, 3.0f), notUsed, 1.0f, 0.0f,
2495                            PRECMASK_NA, BOOL_GENTYPE_FUNCS(allEqual))
2496         << BuiltinOperInfo("not_equal", "!=", B, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2497                            PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(anyNotEqual))
2498         << BuiltinOperInfo("not_equal", "!=", B, Value(IGT, -5.5f, 4.7f), Value(IGT, -2.1f, 0.1f), notUsed, 1.0f, 0.0f,
2499                            PRECMASK_ALL, INT_GENTYPE_FUNCS(anyNotEqual))
2500         << BuiltinOperInfo("not_equal", "!=", B, Value(UGT, 0.0f, 8.0f), Value(UGT, 3.5f, 4.5f), notUsed, 1.0f, 0.0f,
2501                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(anyNotEqual))
2502         << BuiltinOperInfo("not_equal", "!=", B, Value(BGT, -2.1f, 2.1f), Value(BGT, -1.1f, 3.0f), notUsed, 1.0f, 0.0f,
2503                            PRECMASK_NA, BOOL_GENTYPE_FUNCS(anyNotEqual))
2504 
2505         // Logical operators.
2506         << BuiltinOperInfo("logical_and", "&&", B, Value(B, -1.0f, 1.0f), Value(B, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2507                            PRECMASK_NA, BOOL_FUNCS(logicalAnd))
2508         << BuiltinOperInfo("logical_or", "||", B, Value(B, -1.0f, 1.0f), Value(B, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2509                            PRECMASK_NA, BOOL_FUNCS(logicalOr))
2510         << BuiltinOperInfo("logical_xor", "^^", B, Value(B, -1.0f, 1.0f), Value(B, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2511                            PRECMASK_NA, BOOL_FUNCS(logicalXor));
2512 
2513     funcInfoGroups.push_back(binaryOpGroup);
2514 
2515     // Common Functions.
2516     funcInfoGroups.push_back(
2517         BuiltinFuncGroup("common_functions", "Common function tests.")
2518         << BuiltinFuncInfo("min", "min", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
2519                            PRECMASK_ALL, INT_GENTYPE_FUNCS(min))
2520         << BuiltinFuncInfo("min", "min", IGT, Value(IV, -4.0f, 4.0f), Value(I, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
2521                            PRECMASK_ALL, INT_VEC_FUNCS(minVecScalar))
2522         << BuiltinFuncInfo("min", "min", UGT, Value(UGT, 0.0f, 8.0f), Value(UGT, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
2523                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(min))
2524         << BuiltinFuncInfo("min", "min", UGT, Value(UV, 0.0f, 8.0f), Value(U, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
2525                            PRECMASK_ALL, UINT_VEC_FUNCS(minVecScalar))
2526         << BuiltinFuncInfo("max", "max", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
2527                            PRECMASK_ALL, INT_GENTYPE_FUNCS(max))
2528         << BuiltinFuncInfo("max", "max", IGT, Value(IV, -4.0f, 4.0f), Value(I, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
2529                            PRECMASK_ALL, INT_VEC_FUNCS(maxVecScalar))
2530         << BuiltinFuncInfo("max", "max", UGT, Value(UGT, 0.0f, 8.0f), Value(UGT, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
2531                            PRECMASK_ALL, UINT_GENTYPE_FUNCS(max))
2532         << BuiltinFuncInfo("max", "max", UGT, Value(UV, 0.0f, 8.0f), Value(U, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
2533                            PRECMASK_ALL, UINT_VEC_FUNCS(maxVecScalar))
2534         << BuiltinFuncInfo("clamp", "clamp", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -2.0f, 2.0f),
2535                            Value(IGT, 2.0f, 4.0f), 0.125f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(clamp))
2536         << BuiltinFuncInfo("clamp", "clamp", IGT, Value(IV, -4.0f, 4.0f), Value(I, -2.0f, 2.0f), Value(I, 2.0f, 4.0f),
2537                            0.125f, 0.5f, PRECMASK_ALL, INT_VEC_FUNCS(clampVecScalarScalar))
2538         << BuiltinFuncInfo("clamp", "clamp", UGT, Value(UGT, 0.0f, 8.0f), Value(UGT, 2.0f, 6.0f),
2539                            Value(UGT, 6.0f, 8.0f), 0.125f, 0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(clamp))
2540         << BuiltinFuncInfo("clamp", "clamp", UGT, Value(UV, 0.0f, 8.0f), Value(U, 2.0f, 6.0f), Value(U, 6.0f, 8.0f),
2541                            0.125f, 0.0f, PRECMASK_ALL, UINT_VEC_FUNCS(clampVecScalarScalar)));
2542 
2543     // Vector Relational Functions.
2544     funcInfoGroups.push_back(
2545         BuiltinFuncGroup("float_compare", "Floating point comparison tests.")
2546         << BuiltinFuncInfo("lessThan", "lessThan", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f,
2547                            0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(lessThan))
2548         << BuiltinFuncInfo("lessThanEqual", "lessThanEqual", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f),
2549                            notUsed, 1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(lessThanEqual))
2550         << BuiltinFuncInfo("greaterThan", "greaterThan", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
2551                            1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(greaterThan))
2552         << BuiltinFuncInfo("greaterThanEqual", "greaterThanEqual", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f),
2553                            notUsed, 1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(greaterThanEqual))
2554         << BuiltinFuncInfo("equal", "equal", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f, 0.0f,
2555                            PRECMASK_ALL, FLOAT_VEC_FUNCS(equal))
2556         << BuiltinFuncInfo("notEqual", "notEqual", BV, Value(FV, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed, 1.0f,
2557                            0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(notEqual)));
2558 
2559     funcInfoGroups.push_back(
2560         BuiltinFuncGroup("int_compare", "Integer comparison tests.")
2561         << BuiltinFuncInfo("lessThan", "lessThan", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed, 1.0f,
2562                            0.0f, PRECMASK_ALL, INT_VEC_FUNCS(lessThan))
2563         << BuiltinFuncInfo("lessThanEqual", "lessThanEqual", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f),
2564                            notUsed, 1.0f, 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(lessThanEqual))
2565         << BuiltinFuncInfo("greaterThan", "greaterThan", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed,
2566                            1.0f, 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(greaterThan))
2567         << BuiltinFuncInfo("greaterThanEqual", "greaterThanEqual", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f),
2568                            notUsed, 1.0f, 0.0f, PRECMASK_ALL, INT_VEC_FUNCS(greaterThanEqual))
2569         << BuiltinFuncInfo("equal", "equal", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f,
2570                            PRECMASK_ALL, INT_VEC_FUNCS(equal))
2571         << BuiltinFuncInfo("notEqual", "notEqual", BV, Value(IV, -5.2f, 4.9f), Value(IV, -5.0f, 5.0f), notUsed, 1.0f,
2572                            0.0f, PRECMASK_ALL, INT_VEC_FUNCS(notEqual)));
2573 
2574     funcInfoGroups.push_back(BuiltinFuncGroup("bool_compare", "Boolean comparison tests.")
2575                              << BuiltinFuncInfo("equal", "equal", BV, Value(BV, -5.2f, 4.9f), Value(BV, -5.0f, 5.0f),
2576                                                 notUsed, 1.0f, 0.0f, PRECMASK_NA, BOOL_VEC_FUNCS(equal))
2577                              << BuiltinFuncInfo("notEqual", "notEqual", BV, Value(BV, -5.2f, 4.9f),
2578                                                 Value(BV, -5.0f, 5.0f), notUsed, 1.0f, 0.0f, PRECMASK_NA,
2579                                                 BOOL_VEC_FUNCS(notEqual))
2580                              << BuiltinFuncInfo("any", "any", B, Value(BV, -1.0f, 0.3f), notUsed, notUsed, 1.0f, 0.0f,
2581                                                 PRECMASK_NA, BOOL_VEC_FUNCS(any))
2582                              << BuiltinFuncInfo("all", "all", B, Value(BV, -0.3f, 1.0f), notUsed, notUsed, 1.0f, 0.0f,
2583                                                 PRECMASK_NA, BOOL_VEC_FUNCS(all))
2584                              << BuiltinFuncInfo("not", "not", BV, Value(BV, -1.0f, 1.0f), notUsed, notUsed, 1.0f, 0.0f,
2585                                                 PRECMASK_NA, BOOL_VEC_FUNCS(boolNot)));
2586 
2587     static const ShaderType s_shaderTypes[] = {SHADERTYPE_VERTEX, SHADERTYPE_FRAGMENT};
2588 
2589     static const DataType s_floatTypes[] = {TYPE_FLOAT, TYPE_FLOAT_VEC2, TYPE_FLOAT_VEC3, TYPE_FLOAT_VEC4};
2590 
2591     static const DataType s_intTypes[] = {TYPE_INT, TYPE_INT_VEC2, TYPE_INT_VEC3, TYPE_INT_VEC4};
2592 
2593     static const DataType s_uintTypes[] = {TYPE_UINT, TYPE_UINT_VEC2, TYPE_UINT_VEC3, TYPE_UINT_VEC4};
2594 
2595     static const DataType s_boolTypes[] = {TYPE_BOOL, TYPE_BOOL_VEC2, TYPE_BOOL_VEC3, TYPE_BOOL_VEC4};
2596 
2597     for (int outerGroupNdx = 0; outerGroupNdx < (int)funcInfoGroups.size(); outerGroupNdx++)
2598     {
2599         // Create outer group.
2600         const BuiltinFuncGroup &outerGroupInfo = funcInfoGroups[outerGroupNdx];
2601         TestCaseGroup *outerGroup              = new TestCaseGroup(m_testCtx, outerGroupInfo.name);
2602         addChild(outerGroup);
2603 
2604         // Only create new group if name differs from previous one.
2605         TestCaseGroup *innerGroup = DE_NULL;
2606 
2607         for (int funcInfoNdx = 0; funcInfoNdx < (int)outerGroupInfo.funcInfos.size(); funcInfoNdx++)
2608         {
2609             const BuiltinFuncInfo &funcInfo = outerGroupInfo.funcInfos[funcInfoNdx];
2610             const char *shaderFuncName      = funcInfo.shaderFuncName;
2611             const bool isBoolCase           = (funcInfo.precisionMask == PRECMASK_NA);
2612             const bool isBoolOut  = (funcInfo.outValue & (VALUE_BOOL | VALUE_BOOL_VEC | VALUE_BOOL_GENTYPE)) != 0;
2613             const bool isIntOut   = (funcInfo.outValue & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
2614             const bool isUintOut  = (funcInfo.outValue & (VALUE_UINT | VALUE_UINT_VEC | VALUE_UINT_GENTYPE)) != 0;
2615             const bool isFloatOut = !isBoolOut && !isIntOut && !isUintOut;
2616 
2617             if (!innerGroup || (std::string(innerGroup->getName()) != funcInfo.caseName))
2618             {
2619                 std::string groupDesc = std::string("Built-in function ") + shaderFuncName + "() tests.";
2620                 innerGroup            = new TestCaseGroup(m_testCtx, funcInfo.caseName);
2621                 outerGroup->addChild(innerGroup);
2622             }
2623 
2624             for (int inScalarSize = 1; inScalarSize <= 4; inScalarSize++)
2625             {
2626                 const int outScalarSize =
2627                     ((funcInfo.outValue == VALUE_FLOAT) || (funcInfo.outValue == VALUE_BOOL)) ? 1 : inScalarSize;
2628                 const DataType outDataType = isFloatOut ? s_floatTypes[outScalarSize - 1] :
2629                                              isIntOut   ? s_intTypes[outScalarSize - 1] :
2630                                              isUintOut  ? s_uintTypes[outScalarSize - 1] :
2631                                              isBoolOut  ? s_boolTypes[outScalarSize - 1] :
2632                                                           TYPE_LAST;
2633 
2634                 ShaderEvalFunc evalFunc = DE_NULL;
2635                 switch (inScalarSize)
2636                 {
2637                 case 1:
2638                     evalFunc = funcInfo.evalFuncScalar;
2639                     break;
2640                 case 2:
2641                     evalFunc = funcInfo.evalFuncVec2;
2642                     break;
2643                 case 3:
2644                     evalFunc = funcInfo.evalFuncVec3;
2645                     break;
2646                 case 4:
2647                     evalFunc = funcInfo.evalFuncVec4;
2648                     break;
2649                 default:
2650                     DE_ASSERT(false);
2651                 }
2652 
2653                 // Skip if no valid eval func.
2654                 if (evalFunc == DE_NULL)
2655                     continue;
2656 
2657                 for (int precision = PRECISION_MEDIUMP; precision < PRECISION_LAST; precision++)
2658                 {
2659                     if ((funcInfo.precisionMask & (1 << precision)) ||
2660                         (funcInfo.precisionMask == PRECMASK_NA &&
2661                          precision == PRECISION_MEDIUMP)) // use mediump interpolators for booleans
2662                     {
2663                         const char *precisionStr          = getPrecisionName((Precision)precision);
2664                         const std::string precisionPrefix = isBoolCase ? "" : (std::string(precisionStr) + "_");
2665 
2666                         for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
2667                         {
2668                             const ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
2669                             const char *shaderTypeName  = getShaderTypeName(shaderType);
2670                             const bool isVertexCase     = (ShaderType)shaderType == SHADERTYPE_VERTEX;
2671                             const bool isUnaryOp        = (funcInfo.input1.valueType == VALUE_NONE);
2672 
2673                             // \note Data type names will be added to name in a following loop.
2674                             std::string name = precisionPrefix;
2675 
2676                             // Generate shader op.
2677                             std::string shaderOp = std::string("res = ");
2678 
2679                             // Setup shader data info.
2680                             ShaderDataSpec shaderSpec;
2681                             shaderSpec.numInputs      = 0;
2682                             shaderSpec.precision      = isBoolCase ? PRECISION_LAST : (Precision)precision;
2683                             shaderSpec.output         = outDataType;
2684                             shaderSpec.resultScale    = funcInfo.resultScale;
2685                             shaderSpec.resultBias     = funcInfo.resultBias;
2686                             shaderSpec.referenceScale = funcInfo.referenceScale;
2687                             shaderSpec.referenceBias  = funcInfo.referenceBias;
2688 
2689                             if (funcInfo.type == OPERATOR)
2690                             {
2691                                 if (isUnaryOp && funcInfo.isUnaryPrefix)
2692                                     shaderOp += shaderFuncName;
2693                             }
2694                             else if (funcInfo.type == FUNCTION)
2695                                 shaderOp += std::string(shaderFuncName) + "(";
2696                             else // SIDE_EFFECT_OPERATOR
2697                                 shaderOp += "in0;\n\t";
2698 
2699                             for (int inputNdx = 0; inputNdx < MAX_INPUTS; inputNdx++)
2700                             {
2701                                 const Value &prevV = (inputNdx == 1) ? funcInfo.input0 :
2702                                                      (inputNdx == 2) ? funcInfo.input1 :
2703                                                                        funcInfo.input2;
2704                                 const Value &v     = (inputNdx == 0) ? funcInfo.input0 :
2705                                                      (inputNdx == 1) ? funcInfo.input1 :
2706                                                                        funcInfo.input2;
2707 
2708                                 if (v.valueType == VALUE_NONE)
2709                                     continue; // Skip unused input.
2710 
2711                                 const int prevInScalarSize = isScalarType(prevV.valueType) ? 1 : inScalarSize;
2712                                 const DataType prevInDataType =
2713                                     isFloatType(prevV.valueType) ? s_floatTypes[prevInScalarSize - 1] :
2714                                     isIntType(prevV.valueType)   ? s_intTypes[prevInScalarSize - 1] :
2715                                     isUintType(prevV.valueType)  ? s_uintTypes[prevInScalarSize - 1] :
2716                                     isBoolType(prevV.valueType)  ? s_boolTypes[prevInScalarSize - 1] :
2717                                                                    TYPE_LAST;
2718 
2719                                 const int curInScalarSize = isScalarType(v.valueType) ? 1 : inScalarSize;
2720                                 const DataType curInDataType =
2721                                     isFloatType(v.valueType) ? s_floatTypes[curInScalarSize - 1] :
2722                                     isIntType(v.valueType)   ? s_intTypes[curInScalarSize - 1] :
2723                                     isUintType(v.valueType)  ? s_uintTypes[curInScalarSize - 1] :
2724                                     isBoolType(v.valueType)  ? s_boolTypes[curInScalarSize - 1] :
2725                                                                TYPE_LAST;
2726 
2727                                 // Write input type(s) to name.
2728                                 if (inputNdx == 0 ||
2729                                     prevInDataType !=
2730                                         curInDataType) // \note Only write input type to case name if different from previous input type (avoid overly long names).
2731                                     name += std::string("") + getDataTypeName(curInDataType) + "_";
2732 
2733                                 // Generate op input source.
2734                                 if (funcInfo.type == OPERATOR || funcInfo.type == FUNCTION)
2735                                 {
2736                                     if (inputNdx != 0)
2737                                     {
2738                                         if (funcInfo.type == OPERATOR && !isUnaryOp)
2739                                             shaderOp += " " + std::string(shaderFuncName) + " ";
2740                                         else
2741                                             shaderOp += ", ";
2742                                     }
2743 
2744                                     shaderOp += "in" + de::toString(inputNdx);
2745 
2746                                     if (funcInfo.type == OPERATOR && isUnaryOp && !funcInfo.isUnaryPrefix)
2747                                         shaderOp += std::string(shaderFuncName);
2748                                 }
2749                                 else
2750                                 {
2751                                     DE_ASSERT(funcInfo.type == SIDE_EFFECT_OPERATOR);
2752 
2753                                     if (inputNdx != 0 || (isUnaryOp && funcInfo.isUnaryPrefix))
2754                                         shaderOp += std::string("") + (isUnaryOp ? "" : " ") + shaderFuncName +
2755                                                     (isUnaryOp ? "" : " ");
2756 
2757                                     shaderOp +=
2758                                         inputNdx == 0 ?
2759                                             "res" :
2760                                             "in" +
2761                                                 de::toString(
2762                                                     inputNdx); // \note in0 has already been assigned to res, so start from in1.
2763 
2764                                     if (isUnaryOp && !funcInfo.isUnaryPrefix)
2765                                         shaderOp += shaderFuncName;
2766                                 }
2767 
2768                                 // Fill in shader info.
2769                                 shaderSpec.inputs[shaderSpec.numInputs++] =
2770                                     ShaderValue(curInDataType, v.rangeMin, v.rangeMax);
2771                             }
2772 
2773                             if (funcInfo.type == FUNCTION)
2774                                 shaderOp += ")";
2775 
2776                             shaderOp += ";";
2777 
2778                             name += shaderTypeName;
2779 
2780                             // Create the test case.
2781                             innerGroup->addChild(new ShaderOperatorCase(m_testCtx, name.c_str(), isVertexCase, evalFunc,
2782                                                                         shaderOp, shaderSpec));
2783                         }
2784                     }
2785                 }
2786             }
2787         }
2788     }
2789 
2790     // The ?: selection operator.
2791 
2792     static const struct
2793     {
2794         const DataType type; // The type of "Y" and "Z" operands in "X ? Y : Z" (X is always bool).
2795         const ShaderEvalFunc evalFunc;
2796     } s_selectionInfo[] = {{TYPE_FLOAT, eval_selection_float},     {TYPE_FLOAT_VEC2, eval_selection_vec2},
2797                            {TYPE_FLOAT_VEC3, eval_selection_vec3}, {TYPE_FLOAT_VEC4, eval_selection_vec4},
2798                            {TYPE_INT, eval_selection_int},         {TYPE_INT_VEC2, eval_selection_ivec2},
2799                            {TYPE_INT_VEC3, eval_selection_ivec3},  {TYPE_INT_VEC4, eval_selection_ivec4},
2800                            {TYPE_UINT, eval_selection_uint},       {TYPE_UINT_VEC2, eval_selection_uvec2},
2801                            {TYPE_UINT_VEC3, eval_selection_uvec3}, {TYPE_UINT_VEC4, eval_selection_uvec4},
2802                            {TYPE_BOOL, eval_selection_bool},       {TYPE_BOOL_VEC2, eval_selection_bvec2},
2803                            {TYPE_BOOL_VEC3, eval_selection_bvec3}, {TYPE_BOOL_VEC4, eval_selection_bvec4}};
2804 
2805     TestCaseGroup *selectionGroup = new TestCaseGroup(m_testCtx, "selection");
2806     addChild(selectionGroup);
2807 
2808     for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_selectionInfo); typeNdx++)
2809     {
2810         const DataType curType        = s_selectionInfo[typeNdx].type;
2811         const ShaderEvalFunc evalFunc = s_selectionInfo[typeNdx].evalFunc;
2812         const bool isBoolCase         = isDataTypeBoolOrBVec(curType);
2813         const bool isFloatCase        = isDataTypeFloatOrVec(curType);
2814         const bool isIntCase          = isDataTypeIntOrIVec(curType);
2815         const bool isUintCase         = isDataTypeUintOrUVec(curType);
2816         const char *dataTypeStr       = getDataTypeName(curType);
2817 
2818         DE_ASSERT(isBoolCase || isFloatCase || isIntCase || isUintCase);
2819         DE_UNREF(isIntCase);
2820 
2821         for (int precision = (int)PRECISION_MEDIUMP; precision < (int)PRECISION_LAST; precision++)
2822         {
2823             if (isBoolCase && precision != PRECISION_MEDIUMP) // Use mediump interpolators for booleans.
2824                 continue;
2825 
2826             const char *precisionStr    = getPrecisionName((Precision)precision);
2827             std::string precisionPrefix = isBoolCase ? "" : (std::string(precisionStr) + "_");
2828 
2829             for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
2830             {
2831                 const ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
2832                 const char *shaderTypeName  = getShaderTypeName(shaderType);
2833                 const bool isVertexCase     = (ShaderType)shaderType == SHADERTYPE_VERTEX;
2834 
2835                 std::string name = precisionPrefix + dataTypeStr + "_" + shaderTypeName;
2836 
2837                 ShaderDataSpec shaderSpec;
2838                 shaderSpec.numInputs      = 3;
2839                 shaderSpec.precision      = isBoolCase ? PRECISION_LAST : (Precision)precision;
2840                 shaderSpec.output         = curType;
2841                 shaderSpec.resultScale    = (isBoolCase ? 1.0f : (isFloatCase ? 0.5f : (isUintCase ? 0.5f : 0.1f)));
2842                 shaderSpec.resultBias     = (isBoolCase ? 0.0f : (isFloatCase ? 0.5f : (isUintCase ? 0.0f : 0.5f)));
2843                 shaderSpec.referenceScale = shaderSpec.resultScale;
2844                 shaderSpec.referenceBias  = shaderSpec.resultBias;
2845 
2846                 const float rangeMin = (isBoolCase ? -1.0f : (isFloatCase ? -1.0f : (isUintCase ? 0.0f : -5.0f)));
2847                 const float rangeMax = (isBoolCase ? 1.0f : (isFloatCase ? 1.0f : (isUintCase ? 2.0f : 5.0f)));
2848 
2849                 shaderSpec.inputs[0] = ShaderValue(TYPE_BOOL, -1.0f, 1.0f);
2850                 shaderSpec.inputs[1] = ShaderValue(curType, rangeMin, rangeMax);
2851                 shaderSpec.inputs[2] = ShaderValue(curType, rangeMin, rangeMax);
2852 
2853                 selectionGroup->addChild(new ShaderOperatorCase(m_testCtx, name.c_str(), isVertexCase, evalFunc,
2854                                                                 "res = in0 ? in1 : in2;", shaderSpec));
2855             }
2856         }
2857     }
2858 
2859     // The sequence operator (comma).
2860 
2861     TestCaseGroup *sequenceGroup = new TestCaseGroup(m_testCtx, "sequence");
2862     addChild(sequenceGroup);
2863 
2864     TestCaseGroup *sequenceNoSideEffGroup = new TestCaseGroup(m_testCtx, "no_side_effects");
2865     TestCaseGroup *sequenceSideEffGroup   = new TestCaseGroup(m_testCtx, "side_effects");
2866     sequenceGroup->addChild(sequenceNoSideEffGroup);
2867     sequenceGroup->addChild(sequenceSideEffGroup);
2868 
2869     static const struct
2870     {
2871         const bool containsSideEffects;
2872         const char *caseName;
2873         const char *expressionStr;
2874         const int numInputs;
2875         const DataType inputTypes[MAX_INPUTS];
2876         const DataType resultType;
2877         const ShaderEvalFunc evalFunc;
2878     } s_sequenceCases[] = {{false,
2879                             "vec4",
2880                             "in0, in2 + in1, in1 + in0",
2881                             3,
2882                             {TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4},
2883                             TYPE_FLOAT_VEC4,
2884                             evalSequenceNoSideEffCase0},
2885                            {false,
2886                             "float_uint",
2887                             "in0 + in2, in1 + in1",
2888                             3,
2889                             {TYPE_FLOAT, TYPE_UINT, TYPE_FLOAT},
2890                             TYPE_UINT,
2891                             evalSequenceNoSideEffCase1},
2892                            {false,
2893                             "bool_vec2",
2894                             "in0 && in1, in0, ivec2(vec2(in0) + in2)",
2895                             3,
2896                             {TYPE_BOOL, TYPE_BOOL, TYPE_FLOAT_VEC2},
2897                             TYPE_INT_VEC2,
2898                             evalSequenceNoSideEffCase2},
2899                            {false,
2900                             "vec4_ivec4_bvec4",
2901                             "in0 + vec4(in1), in2, in1",
2902                             3,
2903                             {TYPE_FLOAT_VEC4, TYPE_INT_VEC4, TYPE_BOOL_VEC4},
2904                             TYPE_INT_VEC4,
2905                             evalSequenceNoSideEffCase3},
2906 
2907                            {true,
2908                             "vec4",
2909                             "in0++, in1 = in0 + in2, in2 = in1",
2910                             3,
2911                             {TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4},
2912                             TYPE_FLOAT_VEC4,
2913                             evalSequenceSideEffCase0},
2914                            {true,
2915                             "float_uint",
2916                             "in1++, in0 = float(in1), in1 = uint(in0 + in2)",
2917                             3,
2918                             {TYPE_FLOAT, TYPE_UINT, TYPE_FLOAT},
2919                             TYPE_UINT,
2920                             evalSequenceSideEffCase1},
2921                            {true,
2922                             "bool_vec2",
2923                             "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)",
2924                             3,
2925                             {TYPE_BOOL, TYPE_BOOL, TYPE_FLOAT_VEC2},
2926                             TYPE_INT_VEC2,
2927                             evalSequenceSideEffCase2},
2928                            {true,
2929                             "vec4_ivec4_bvec4",
2930                             "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++",
2931                             3,
2932                             {TYPE_FLOAT_VEC4, TYPE_INT_VEC4, TYPE_BOOL_VEC4},
2933                             TYPE_INT_VEC4,
2934                             evalSequenceSideEffCase3}};
2935 
2936     for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_sequenceCases); caseNdx++)
2937     {
2938         for (int precision = (int)PRECISION_MEDIUMP; precision < (int)PRECISION_LAST; precision++)
2939         {
2940             for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
2941             {
2942                 const ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
2943                 const char *shaderTypeName  = getShaderTypeName(shaderType);
2944                 const bool isVertexCase     = (ShaderType)shaderType == SHADERTYPE_VERTEX;
2945 
2946                 std::string name = std::string("") + getPrecisionName((Precision)precision) + "_" +
2947                                    s_sequenceCases[caseNdx].caseName + "_" + shaderTypeName;
2948 
2949                 ShaderDataSpec shaderSpec;
2950                 shaderSpec.numInputs      = s_sequenceCases[caseNdx].numInputs;
2951                 shaderSpec.precision      = (Precision)precision;
2952                 shaderSpec.output         = s_sequenceCases[caseNdx].resultType;
2953                 shaderSpec.resultScale    = 0.5f;
2954                 shaderSpec.resultBias     = 0.0f;
2955                 shaderSpec.referenceScale = shaderSpec.resultScale;
2956                 shaderSpec.referenceBias  = shaderSpec.resultBias;
2957 
2958                 for (int inputNdx = 0; inputNdx < s_sequenceCases[caseNdx].numInputs; inputNdx++)
2959                 {
2960                     const DataType type = s_sequenceCases[caseNdx].inputTypes[inputNdx];
2961                     const float rangeMin =
2962                         (isDataTypeFloatOrVec(type) ?
2963                              -0.5f :
2964                              (isDataTypeIntOrIVec(type) ? -2.0f : (isDataTypeUintOrUVec(type) ? 0.0f : -1.0f)));
2965                     const float rangeMax =
2966                         (isDataTypeFloatOrVec(type) ?
2967                              0.5f :
2968                              (isDataTypeIntOrIVec(type) ? 2.0f : (isDataTypeUintOrUVec(type) ? 2.0f : 1.0f)));
2969 
2970                     shaderSpec.inputs[inputNdx] = ShaderValue(type, rangeMin, rangeMax);
2971                 }
2972 
2973                 const std::string expression =
2974                     std::string("") + "res = (" + s_sequenceCases[caseNdx].expressionStr + ");";
2975 
2976                 TestCaseGroup *group =
2977                     s_sequenceCases[caseNdx].containsSideEffects ? sequenceSideEffGroup : sequenceNoSideEffGroup;
2978                 group->addChild(new ShaderOperatorCase(m_testCtx, name.c_str(), isVertexCase,
2979                                                        s_sequenceCases[caseNdx].evalFunc, expression.c_str(),
2980                                                        shaderSpec));
2981             }
2982         }
2983     }
2984 }
2985 
2986 } // namespace
2987 
createOperatorTests(tcu::TestContext & testCtx)2988 tcu::TestCaseGroup *createOperatorTests(tcu::TestContext &testCtx)
2989 {
2990     return new ShaderOperatorTests(testCtx);
2991 }
2992 
2993 } // namespace sr
2994 } // namespace vkt
2995