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