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