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