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