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 
abs(float v)64 inline float abs		(float v)			{ return deFloatAbs(v); }
65 
logicalAnd(bool a,bool b)66 inline bool logicalAnd	(bool a, bool b)	{ return (a && b); }
logicalOr(bool a,bool b)67 inline bool logicalOr	(bool a, bool b)	{ return (a || b); }
logicalXor(bool a,bool 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 
DEFINE_VEC_FLOAT_FUNCTION(modVecFloat,mod)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; };
subOne(float v)134 inline float	subOne (float v)	{ return v - 1.0f; };
addOne(int v)135 inline int		addOne (int v)		{ return v + 1; };
subOne(int v)136 inline int		subOne (int v)		{ return v - 1; };
137 
addOne(const Vector<float,Size> & v)138 template<int Size> inline Vector<float, Size>	addOne (const Vector<float, Size>& v)	{ return v + 1.0f; };
subOne(const Vector<float,Size> & v)139 template<int Size> inline Vector<float, Size>	subOne (const Vector<float, Size>& v)	{ return v - 1.0f; };
addOne(const Vector<int,Size> & v)140 template<int Size> inline Vector<int, Size>		addOne (const Vector<int, Size>& v)		{ return v + 1; };
subOne(const Vector<int,Size> & v)141 template<int Size> inline Vector<int, Size>		subOne (const Vector<int, Size>& v)		{ return v - 1; };
142 
selection(bool cond,T a,T b)143 template<typename T> inline T selection	(bool cond, T a, T b)	{ return cond ? a : b; };
144 
addVecScalar(const Vector<T,Size> & v,T s)145 template<typename T, int Size> inline Vector<T, Size> addVecScalar	(const Vector<T, Size>& v, T s) { return v + s; };
subVecScalar(const Vector<T,Size> & v,T s)146 template<typename T, int Size> inline Vector<T, Size> subVecScalar	(const Vector<T, Size>& v, T s) { return v - s; };
mulVecScalar(const Vector<T,Size> & v,T s)147 template<typename T, int Size> inline Vector<T, Size> mulVecScalar	(const Vector<T, Size>& v, T s) { return v * s; };
divVecScalar(const Vector<T,Size> & v,T s)148 template<typename T, int Size> inline Vector<T, Size> divVecScalar	(const Vector<T, Size>& v, T s) { return v / s; };
149 
addScalarVec(T s,const Vector<T,Size> & v)150 template<typename T, int Size> inline Vector<T, Size> addScalarVec	(T s, const Vector<T, Size>& v) { return s + v; };
subScalarVec(T s,const Vector<T,Size> & v)151 template<typename T, int Size> inline Vector<T, Size> subScalarVec	(T s, const Vector<T, Size>& v) { return s - v; };
mulScalarVec(T s,const Vector<T,Size> & v)152 template<typename T, int Size> inline Vector<T, Size> mulScalarVec	(T s, const Vector<T, Size>& v) { return s * v; };
divScalarVec(T s,const Vector<T,Size> & 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"
sequenceNoSideEffCase0(const Vec4 & in0,const Vec4 & in1,const Vec4 & in2)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"
sequenceNoSideEffCase1(float in0,int in1,float in2)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)"
sequenceNoSideEffCase2(bool in0,bool in1,const Vec2 & 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"
sequenceNoSideEffCase3(const Vec4 & in0,const IVec4 & in1,const BVec4 & in2)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"
sequenceSideEffCase0(const Vec4 & in0,const Vec4 & in1,const Vec4 & in2)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)"
sequenceSideEffCase1(float in0,int in1,float in2)168 inline int		sequenceSideEffCase1 (float in0, int in1, float in2)							{ DE_UNREF(in0); return (int)(float(in1) + 1.0f + in2); }
169 // Reference for expression "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)"
sequenceSideEffCase2(bool in0,bool in1,const Vec2 & 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++"
sequenceSideEffCase3(const Vec4 & in0,const IVec4 & in1,const BVec4 & in2)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.
evalSequenceNoSideEffCase0(ShaderEvalContext & ctx)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)); }
evalSequenceNoSideEffCase1(ShaderEvalContext & ctx)176 void evalSequenceNoSideEffCase1	(ShaderEvalContext& ctx) { ctx.color.x()	= (float)sequenceNoSideEffCase1(ctx.in[0].z(), (int)ctx.in[1].x(), ctx.in[2].y()); }
evalSequenceNoSideEffCase2(ShaderEvalContext & ctx)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(); }
evalSequenceNoSideEffCase3(ShaderEvalContext & ctx)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(); }
evalSequenceSideEffCase0(ShaderEvalContext & ctx)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)); }
evalSequenceSideEffCase1(ShaderEvalContext & ctx)180 void evalSequenceSideEffCase1	(ShaderEvalContext& ctx) { ctx.color.x()	= (float)sequenceSideEffCase1(ctx.in[0].z(), (int)ctx.in[1].x(), ctx.in[2].y()); }
evalSequenceSideEffCase2(ShaderEvalContext & ctx)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(); }
evalSequenceSideEffCase3(ShaderEvalContext & ctx)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 
isScalarType(ValueType type)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 {
Valuedeqp::gles2::Functional::Value236 	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 {
BuiltinFuncInfodeqp::gles2::Functional::BuiltinFuncInfo257 	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 
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_)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.
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_)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 
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_)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.
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_)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 {
BuiltinFuncGroupdeqp::gles2::Functional::BuiltinFuncGroup319 						BuiltinFuncGroup	(const char* name_, const char* description_) : name(name_), description(description_) {}
operator <<deqp::gles2::Functional::BuiltinFuncGroup320 	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:
OperatorShaderEvaluator(ShaderEvalFunc evalFunc,float scale,float bias)341 	OperatorShaderEvaluator (ShaderEvalFunc evalFunc, float scale, float bias)
342 	{
343 		m_evalFunc	= evalFunc;
344 		m_scale		= scale;
345 		m_bias		= bias;
346 	}
347 
~OperatorShaderEvaluator(void)348 	virtual ~OperatorShaderEvaluator (void)
349 	{
350 	}
351 
evaluate(ShaderEvalContext & ctx)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 {
ShaderValuedeqp::gles2::Functional::ShaderValue368 	ShaderValue (DataType type_, float rangeMin_, float rangeMax_)
369 		: type		(type_)
370 		, rangeMin	(rangeMin_)
371 		, rangeMax	(rangeMax_)
372 	{
373 	}
374 
ShaderValuedeqp::gles2::Functional::ShaderValue375 	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 {
ShaderDataSpecdeqp::gles2::Functional::ShaderDataSpec389 	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 
ShaderOperatorCase(Context & context,const char * caseName,const char * description,bool isVertexCase,ShaderEvalFunc evalFunc,const char * shaderOp,const ShaderDataSpec & spec)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 
~ShaderOperatorCase(void)598 ShaderOperatorCase::~ShaderOperatorCase (void)
599 {
600 }
601 
602 // ShaderOperatorTests.
603 
ShaderOperatorTests(Context & context)604 ShaderOperatorTests::ShaderOperatorTests(Context& context)
605 	: TestCaseGroup(context, "operator", "Operator tests.")
606 {
607 }
608 
~ShaderOperatorTests(void)609 ShaderOperatorTests::~ShaderOperatorTests (void)
610 {
611 }
612 
613 // Vector math functions.
nop(T f)614 template<typename T> inline T nop (T f) { return f; }
615 
616 template <typename T, int Size>
nop(const Vector<T,Size> & v)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].swizzle(2)).x(); }			\
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].swizzle(2),          c.in[1].swizzle(0)).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].swizzle(2),          c.in[1].swizzle(0),          c.in[2].swizzle(1)).x(); }		\
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].swizzle(2)); }			\
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].swizzle(2),          c.in[1].swizzle(0)); }				\
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)
DECLARE_UNARY_GENTYPE_FUNCS(negate)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()); }
eval_selection_vec2(ShaderEvalContext & c)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)); }
eval_selection_vec3(ShaderEvalContext & c)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)); }
eval_selection_vec4(ShaderEvalContext & c)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)
DECLARE_UNARY_INT_GENTYPE_FUNCS(negate)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()); }
eval_selection_ivec2(ShaderEvalContext & c)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(); }
eval_selection_ivec3(ShaderEvalContext & c)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(); }
eval_selection_ivec4(ShaderEvalContext & c)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)
DECLARE_BINARY_BOOL_FUNCS(logicalAnd)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); }
eval_selection_bvec2(ShaderEvalContext & c)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(); }
eval_selection_bvec3(ShaderEvalContext & c)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(); }
eval_selection_bvec4(ShaderEvalContext & c)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)
DECLARE_VEC_FLOAT_FUNCS(subVecScalar)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)
DECLARE_TERNARY_GENTYPE_FUNCS(faceForward)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()); }
eval_refract_vec2(ShaderEvalContext & c)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()); }
eval_refract_vec3(ShaderEvalContext & c)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()); }
eval_refract_vec4(ShaderEvalContext & c)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 
init(void)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 	// Regression tests for sequence operator.
1528 	// http://khronos.org/registry/webgl/sdk/tests/conformance/glsl/bugs/sequence-operator-evaluation-order.html
1529 	{
1530 		class Case : public ShaderRenderCase
1531 		{
1532 			static void evalFunc(ShaderEvalContext& c) {
1533 				c.color = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); // green
1534 			}
1535 
1536 		public:
1537 			Case(Context& context, const char* name, const char* description, const char* fragShaderSource)
1538 				: ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, false, &evalFunc)
1539 			{
1540 				m_vertShaderSource =
1541 					"attribute vec4 a_position;\n"
1542 					"void main()\n"
1543 					"{\n"
1544 					"	gl_Position = a_position;\n"
1545 					"}\n";
1546 				m_fragShaderSource = fragShaderSource;
1547 			}
1548 		};
1549 
1550 		// ESSL 1.00 section 5.9, about sequence operator:
1551 		// "All expressions are evaluated, in order, from left to right"
1552 		// Also use a ternary operator where the third operand has side effects to make sure
1553 		// only the second operand is evaluated.
1554 		sequenceSideEffGroup->addChild(new Case(m_context, "affect_ternary",
1555 			"Expression where first operand of a sequence operator has side effects which affect the second operand that is a ternary operator", (
1556 				"precision mediump float;\n"
1557 				"bool correct = true;\n"
1558 				"uniform float u_zero;\n"
1559 				"float wrong() {\n"
1560 				"	correct = false;\n"
1561 				"	return 0.0;\n"
1562 				"}\n"
1563 				"void main() {\n"
1564 				"	float a = u_zero - 0.5; // Result should be -0.5.\n"
1565 				"	float green = (a++, a > 0.0 ? 1.0 : wrong());\n"
1566 				"	gl_FragColor = vec4(0.0, correct ? green : 0.0, 0.0, 1.0);\n"
1567 				"}\n"
1568 			)));
1569 
1570 		sequenceSideEffGroup->addChild(new Case(m_context, "affect_and",
1571 			"Expression where first operand of a sequence operator has side effects which affect the second operand that is an and operator", (
1572 				"precision mediump float;\n"
1573 				"uniform bool u_false;\n"
1574 				"bool sideEffectA = false;\n"
1575 				"bool funcA() {\n"
1576 				"	sideEffectA = true;\n"
1577 				"	return true;\n"
1578 				"}\n"
1579 				"bool sideEffectB = false;\n"
1580 				"bool funcB() {\n"
1581 				"	sideEffectB = true;\n"
1582 				"	return true;\n"
1583 				"}\n"
1584 				"void main() {\n"
1585 				"	bool b = (funcA(), u_false == sideEffectA && funcB());\n"
1586 				"	gl_FragColor = (!b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
1587 				"}\n"
1588 			)));
1589 
1590 		sequenceSideEffGroup->addChild(new Case(m_context, "affect_or",
1591 			"Expression where first operand of a sequence operator has side effects which affect the second operand that is an or operator", (
1592 				"precision mediump float;\n"
1593 				"uniform bool u_false;\n"
1594 				"bool sideEffectA = false;\n"
1595 				"bool funcA() {\n"
1596 				"	sideEffectA = true;\n"
1597 				"	return false;\n"
1598 				"}\n"
1599 				"bool sideEffectB = false;\n"
1600 				"bool funcB() {\n"
1601 				"	sideEffectB = true;\n"
1602 				"	return false;\n"
1603 				"}\n"
1604 				"void main() {\n"
1605 				"	bool b = (funcA(), (u_false == !sideEffectA) || funcB());\n"
1606 				"	gl_FragColor = (b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
1607 				"}\n"
1608 			)));
1609 	}
1610 }
1611 
1612 } // Functional
1613 } // gles2
1614 } // deqp
1615