1615 lines
90 KiB
C++
1615 lines
90 KiB
C++
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL ES 2.0 Module
|
|
* -------------------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Shader operators tests.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "es2fShaderOperatorTests.hpp"
|
|
#include "glsShaderRenderCase.hpp"
|
|
#include "gluShaderUtil.hpp"
|
|
#include "tcuVectorUtil.hpp"
|
|
|
|
#include "deStringUtil.hpp"
|
|
#include "deInt32.h"
|
|
#include "deMemory.h"
|
|
|
|
#include <map>
|
|
|
|
using namespace tcu;
|
|
using namespace glu;
|
|
using namespace deqp::gls;
|
|
|
|
using std::map;
|
|
using std::pair;
|
|
using std::vector;
|
|
using std::string;
|
|
using std::ostringstream;
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gles2
|
|
{
|
|
namespace Functional
|
|
{
|
|
|
|
#if defined(abs)
|
|
# undef abs
|
|
#endif
|
|
|
|
using de::min;
|
|
using de::max;
|
|
using de::clamp;
|
|
|
|
// \note VS2013 gets confused without these
|
|
using tcu::exp2;
|
|
using tcu::log2;
|
|
|
|
inline float abs (float v) { return deFloatAbs(v); }
|
|
|
|
inline bool logicalAnd (bool a, bool b) { return (a && b); }
|
|
inline bool logicalOr (bool a, bool b) { return (a || b); }
|
|
inline bool logicalXor (bool a, bool b) { return (a != b); }
|
|
|
|
#define DEFINE_VEC_FLOAT_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
|
|
template<int Size> \
|
|
inline Vector<float, Size> FUNC_NAME (const Vector<float, Size>& v, float s) \
|
|
{ \
|
|
Vector<float, Size> res; \
|
|
for (int i = 0; i < Size; i++) \
|
|
res[i] = SCALAR_OP_NAME(v[i], s); \
|
|
return res; \
|
|
}
|
|
|
|
#define DEFINE_FLOAT_VEC_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
|
|
template<int Size> \
|
|
inline Vector<float, Size> FUNC_NAME (float s, const Vector<float, Size>& v) \
|
|
{ \
|
|
Vector<float, Size> res; \
|
|
for (int i = 0; i < Size; i++) \
|
|
res[i] = SCALAR_OP_NAME(s, v[i]); \
|
|
return res; \
|
|
}
|
|
|
|
#define DEFINE_VEC_VEC_FLOAT_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
|
|
template<int Size> \
|
|
inline Vector<float, Size> FUNC_NAME (const Vector<float, Size>& v0, const Vector<float, Size>& v1, float s) \
|
|
{ \
|
|
Vector<float, Size> res; \
|
|
for (int i = 0; i < Size; i++) \
|
|
res[i] = SCALAR_OP_NAME(v0[i], v1[i], s); \
|
|
return res; \
|
|
}
|
|
|
|
#define DEFINE_VEC_FLOAT_FLOAT_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
|
|
template<int Size> \
|
|
inline Vector<float, Size> FUNC_NAME (const Vector<float, Size>& v, float s0, float s1) \
|
|
{ \
|
|
Vector<float, Size> res; \
|
|
for (int i = 0; i < Size; i++) \
|
|
res[i] = SCALAR_OP_NAME(v[i], s0, s1); \
|
|
return res; \
|
|
}
|
|
|
|
#define DEFINE_FLOAT_FLOAT_VEC_FUNCTION(FUNC_NAME, SCALAR_OP_NAME) \
|
|
template<int Size> \
|
|
inline Vector<float, Size> FUNC_NAME (float s0, float s1, const Vector<float, Size>& v) \
|
|
{ \
|
|
Vector<float, Size> res; \
|
|
for (int i = 0; i < Size; i++) \
|
|
res[i] = SCALAR_OP_NAME(s0, s1, v[i]); \
|
|
return res; \
|
|
}
|
|
|
|
DEFINE_VEC_FLOAT_FUNCTION (modVecFloat, mod)
|
|
DEFINE_VEC_FLOAT_FUNCTION (minVecFloat, min)
|
|
DEFINE_VEC_FLOAT_FUNCTION (maxVecFloat, max)
|
|
DEFINE_VEC_FLOAT_FLOAT_FUNCTION (clampVecFloatFloat, clamp)
|
|
DEFINE_VEC_VEC_FLOAT_FUNCTION (mixVecVecFloat, mix)
|
|
DEFINE_FLOAT_VEC_FUNCTION (stepFloatVec, step)
|
|
DEFINE_FLOAT_FLOAT_VEC_FUNCTION (smoothStepFloatFloatVec, smoothStep)
|
|
|
|
#undef DEFINE_VEC_FLOAT_FUNCTION
|
|
#undef DEFINE_VEC_VEC_FLOAT_FUNCTION
|
|
#undef DEFINE_VEC_FLOAT_FLOAT_FUNCTION
|
|
#undef DEFINE_FLOAT_FLOAT_VEC_FUNCTION
|
|
|
|
inline float addOne (float v) { return v + 1.0f; }
|
|
inline float subOne (float v) { return v - 1.0f; }
|
|
inline int addOne (int v) { return v + 1; }
|
|
inline int subOne (int v) { return v - 1; }
|
|
|
|
template<int Size> inline Vector<float, Size> addOne (const Vector<float, Size>& v) { return v + 1.0f; }
|
|
template<int Size> inline Vector<float, Size> subOne (const Vector<float, Size>& v) { return v - 1.0f; }
|
|
template<int Size> inline Vector<int, Size> addOne (const Vector<int, Size>& v) { return v + 1; }
|
|
template<int Size> inline Vector<int, Size> subOne (const Vector<int, Size>& v) { return v - 1; }
|
|
|
|
template<typename T> inline T selection (bool cond, T a, T b) { return cond ? a : b; }
|
|
|
|
template<typename T, int Size> inline Vector<T, Size> addVecScalar (const Vector<T, Size>& v, T s) { return v + s; }
|
|
template<typename T, int Size> inline Vector<T, Size> subVecScalar (const Vector<T, Size>& v, T s) { return v - s; }
|
|
template<typename T, int Size> inline Vector<T, Size> mulVecScalar (const Vector<T, Size>& v, T s) { return v * s; }
|
|
template<typename T, int Size> inline Vector<T, Size> divVecScalar (const Vector<T, Size>& v, T s) { return v / s; }
|
|
|
|
template<typename T, int Size> inline Vector<T, Size> addScalarVec (T s, const Vector<T, Size>& v) { return s + v; }
|
|
template<typename T, int Size> inline Vector<T, Size> subScalarVec (T s, const Vector<T, Size>& v) { return s - v; }
|
|
template<typename T, int Size> inline Vector<T, Size> mulScalarVec (T s, const Vector<T, Size>& v) { return s * v; }
|
|
template<typename T, int Size> inline Vector<T, Size> divScalarVec (T s, const Vector<T, Size>& v) { return s / v; }
|
|
|
|
// Reference functions for specific sequence operations for the sequence operator tests.
|
|
|
|
// Reference for expression "in0, in2 + in1, in1 + in0"
|
|
inline Vec4 sequenceNoSideEffCase0 (const Vec4& in0, const Vec4& in1, const Vec4& in2) { DE_UNREF(in2); return in1 + in0; }
|
|
// Reference for expression "in0, in2 + in1, in1 + in0"
|
|
inline int sequenceNoSideEffCase1 (float in0, int in1, float in2) { DE_UNREF(in0); DE_UNREF(in2); return in1 + in1; }
|
|
// Reference for expression "in0 && in1, in0, ivec2(vec2(in0) + in2)"
|
|
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())); }
|
|
// Reference for expression "in0 + vec4(in1), in2, in1"
|
|
inline IVec4 sequenceNoSideEffCase3 (const Vec4& in0, const IVec4& in1, const BVec4& in2) { DE_UNREF(in0); DE_UNREF(in2); return in1; }
|
|
// Reference for expression "in0++, in1 = in0 + in2, in2 = in1"
|
|
inline Vec4 sequenceSideEffCase0 (const Vec4& in0, const Vec4& in1, const Vec4& in2) { DE_UNREF(in1); return in0 + 1.0f + in2; }
|
|
// Reference for expression "in1++, in0 = float(in1), in1 = int(in0 + in2)"
|
|
inline int sequenceSideEffCase1 (float in0, int in1, float in2) { DE_UNREF(in0); return (int)(float(in1) + 1.0f + in2); }
|
|
// Reference for expression "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)"
|
|
inline IVec2 sequenceSideEffCase2 (bool in0, bool in1, const Vec2& in2) { DE_UNREF(in1); return (in2 + Vec2(1.0f) + Vec2((float)in0)).asInt(); }
|
|
// Reference for expression "in0 = in0 + vec4(in2), in1 = in1 + ivec4(in0), in1++"
|
|
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(); }
|
|
|
|
// ShaderEvalFunc-type wrappers for the above functions.
|
|
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)); }
|
|
void evalSequenceNoSideEffCase1 (ShaderEvalContext& ctx) { ctx.color.x() = (float)sequenceNoSideEffCase1(ctx.in[0].z(), (int)ctx.in[1].x(), ctx.in[2].y()); }
|
|
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(); }
|
|
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(); }
|
|
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)); }
|
|
void evalSequenceSideEffCase1 (ShaderEvalContext& ctx) { ctx.color.x() = (float)sequenceSideEffCase1(ctx.in[0].z(), (int)ctx.in[1].x(), ctx.in[2].y()); }
|
|
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(); }
|
|
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(); }
|
|
|
|
enum
|
|
{
|
|
MAX_INPUTS = 3
|
|
};
|
|
|
|
enum PrecisionMask
|
|
{
|
|
PRECMASK_NA = 0, //!< Precision not applicable (booleans)
|
|
PRECMASK_LOWP = (1<<PRECISION_LOWP),
|
|
PRECMASK_MEDIUMP = (1<<PRECISION_MEDIUMP),
|
|
PRECMASK_HIGHP = (1<<PRECISION_HIGHP),
|
|
|
|
PRECMASK_MEDIUMP_HIGHP = (1<<PRECISION_MEDIUMP) | (1<<PRECISION_HIGHP),
|
|
PRECMASK_ALL = (1<<PRECISION_LOWP) | (1<<PRECISION_MEDIUMP) | (1<<PRECISION_HIGHP)
|
|
};
|
|
|
|
enum ValueType
|
|
{
|
|
VALUE_NONE = 0,
|
|
VALUE_FLOAT = (1<<0), // float scalar
|
|
VALUE_FLOAT_VEC = (1<<1), // float vector
|
|
VALUE_FLOAT_GENTYPE = (1<<2), // float scalar/vector
|
|
VALUE_VEC3 = (1<<3), // vec3 only
|
|
VALUE_MATRIX = (1<<4), // matrix
|
|
VALUE_BOOL = (1<<5), // boolean scalar
|
|
VALUE_BOOL_VEC = (1<<6), // boolean vector
|
|
VALUE_BOOL_GENTYPE = (1<<7), // boolean scalar/vector
|
|
VALUE_INT = (1<<8), // int scalar
|
|
VALUE_INT_VEC = (1<<9), // int vector
|
|
VALUE_INT_GENTYPE = (1<<10), // int scalar/vector
|
|
|
|
// Shorthands.
|
|
F = VALUE_FLOAT,
|
|
FV = VALUE_FLOAT_VEC,
|
|
GT = VALUE_FLOAT_GENTYPE,
|
|
V3 = VALUE_VEC3,
|
|
M = VALUE_MATRIX,
|
|
B = VALUE_BOOL,
|
|
BV = VALUE_BOOL_VEC,
|
|
BGT = VALUE_BOOL_GENTYPE,
|
|
I = VALUE_INT,
|
|
IV = VALUE_INT_VEC,
|
|
IGT = VALUE_INT_GENTYPE
|
|
};
|
|
|
|
static inline bool isScalarType (ValueType type)
|
|
{
|
|
return type == VALUE_FLOAT || type == VALUE_BOOL || type == VALUE_INT;
|
|
}
|
|
|
|
struct Value
|
|
{
|
|
Value (ValueType valueType_, float rangeMin_, float rangeMax_)
|
|
: valueType (valueType_)
|
|
, rangeMin (rangeMin_)
|
|
, rangeMax (rangeMax_)
|
|
{
|
|
}
|
|
|
|
ValueType valueType;
|
|
float rangeMin;
|
|
float rangeMax;
|
|
};
|
|
|
|
enum OperationType
|
|
{
|
|
FUNCTION = 0,
|
|
OPERATOR,
|
|
SIDE_EFFECT_OPERATOR // Test the side-effect (as opposed to the result) of a side-effect operator.
|
|
};
|
|
|
|
struct BuiltinFuncInfo
|
|
{
|
|
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)
|
|
: caseName (caseName_)
|
|
, shaderFuncName (shaderFuncName_)
|
|
, outValue (outValue_)
|
|
, input0 (input0_)
|
|
, input1 (input1_)
|
|
, input2 (input2_)
|
|
, resultScale (resultScale_)
|
|
, resultBias (resultBias_)
|
|
, precisionMask (precisionMask_)
|
|
, evalFuncScalar (evalFuncScalar_)
|
|
, evalFuncVec2 (evalFuncVec2_)
|
|
, evalFuncVec3 (evalFuncVec3_)
|
|
, evalFuncVec4 (evalFuncVec4_)
|
|
, type (type_)
|
|
, isUnaryPrefix (isUnaryPrefix_)
|
|
{
|
|
}
|
|
|
|
const char* caseName; //!< Name of case.
|
|
const char* shaderFuncName; //!< Name in shading language.
|
|
ValueType outValue;
|
|
Value input0;
|
|
Value input1;
|
|
Value input2;
|
|
float resultScale;
|
|
float resultBias;
|
|
deUint32 precisionMask;
|
|
ShaderEvalFunc evalFuncScalar;
|
|
ShaderEvalFunc evalFuncVec2;
|
|
ShaderEvalFunc evalFuncVec3;
|
|
ShaderEvalFunc evalFuncVec4;
|
|
OperationType type;
|
|
bool isUnaryPrefix; //!< Whether a unary operator is a prefix operator; redundant unless unary.
|
|
};
|
|
|
|
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_)
|
|
{
|
|
return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, OPERATOR);
|
|
}
|
|
|
|
// For postfix (unary) operators.
|
|
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_)
|
|
{
|
|
return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, OPERATOR, false);
|
|
}
|
|
|
|
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_)
|
|
{
|
|
return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, SIDE_EFFECT_OPERATOR);
|
|
}
|
|
|
|
// For postfix (unary) operators, testing side-effect.
|
|
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_)
|
|
{
|
|
return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_, evalFuncVec4_, SIDE_EFFECT_OPERATOR, false);
|
|
}
|
|
|
|
// BuiltinFuncGroup
|
|
|
|
struct BuiltinFuncGroup
|
|
{
|
|
BuiltinFuncGroup (const char* name_, const char* description_) : name(name_), description(description_) {}
|
|
BuiltinFuncGroup& operator<< (const BuiltinFuncInfo& info) { funcInfos.push_back(info); return *this; }
|
|
|
|
const char* name;
|
|
const char* description;
|
|
std::vector<BuiltinFuncInfo> funcInfos;
|
|
};
|
|
|
|
static const char* s_inSwizzles[MAX_INPUTS][4] =
|
|
{
|
|
{ "z", "wy", "zxy", "yzwx" },
|
|
{ "x", "yx", "yzx", "wzyx" },
|
|
{ "y", "zy", "wyz", "xwzy" }
|
|
};
|
|
|
|
static const char* s_outSwizzles[] = { "x", "yz", "xyz", "xyzw" };
|
|
|
|
// OperatorShaderEvaluator
|
|
|
|
class OperatorShaderEvaluator : public ShaderEvaluator
|
|
{
|
|
public:
|
|
OperatorShaderEvaluator (ShaderEvalFunc evalFunc, float scale, float bias)
|
|
{
|
|
m_evalFunc = evalFunc;
|
|
m_scale = scale;
|
|
m_bias = bias;
|
|
}
|
|
|
|
virtual ~OperatorShaderEvaluator (void)
|
|
{
|
|
}
|
|
|
|
virtual void evaluate (ShaderEvalContext& ctx)
|
|
{
|
|
m_evalFunc(ctx);
|
|
ctx.color = ctx.color * m_scale + m_bias;
|
|
}
|
|
|
|
private:
|
|
ShaderEvalFunc m_evalFunc;
|
|
float m_scale;
|
|
float m_bias;
|
|
};
|
|
|
|
// Concrete value.
|
|
|
|
struct ShaderValue
|
|
{
|
|
ShaderValue (DataType type_, float rangeMin_, float rangeMax_)
|
|
: type (type_)
|
|
, rangeMin (rangeMin_)
|
|
, rangeMax (rangeMax_)
|
|
{
|
|
}
|
|
|
|
ShaderValue (void)
|
|
: type (TYPE_LAST)
|
|
, rangeMin (0.0f)
|
|
, rangeMax (0.0f)
|
|
{
|
|
}
|
|
|
|
DataType type;
|
|
float rangeMin;
|
|
float rangeMax;
|
|
};
|
|
|
|
struct ShaderDataSpec
|
|
{
|
|
ShaderDataSpec (void)
|
|
: resultScale (1.0f)
|
|
, resultBias (0.0f)
|
|
, precision (PRECISION_LAST)
|
|
, output (TYPE_LAST)
|
|
, numInputs (0)
|
|
{
|
|
}
|
|
|
|
float resultScale;
|
|
float resultBias;
|
|
Precision precision;
|
|
DataType output;
|
|
int numInputs;
|
|
ShaderValue inputs[MAX_INPUTS];
|
|
};
|
|
|
|
// ShaderOperatorCase
|
|
|
|
class ShaderOperatorCase : public ShaderRenderCase
|
|
{
|
|
public:
|
|
ShaderOperatorCase (Context& context, const char* caseName, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, const char* shaderOp, const ShaderDataSpec& spec);
|
|
virtual ~ShaderOperatorCase (void);
|
|
|
|
private:
|
|
ShaderOperatorCase (const ShaderOperatorCase&); // not allowed!
|
|
ShaderOperatorCase& operator= (const ShaderOperatorCase&); // not allowed!
|
|
|
|
OperatorShaderEvaluator m_evaluator;
|
|
};
|
|
|
|
ShaderOperatorCase::ShaderOperatorCase (Context& context, const char* caseName, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, const char* shaderOp, const ShaderDataSpec& spec)
|
|
: ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), caseName, description, isVertexCase, m_evaluator)
|
|
, m_evaluator(evalFunc, spec.resultScale, spec.resultBias)
|
|
{
|
|
const char* precision = spec.precision != PRECISION_LAST ? getPrecisionName(spec.precision) : DE_NULL;
|
|
const char* inputPrecision[MAX_INPUTS];
|
|
|
|
ostringstream vtx;
|
|
ostringstream frag;
|
|
ostringstream& op = isVertexCase ? vtx : frag;
|
|
|
|
// Compute precision for inputs.
|
|
for (int i = 0; i < spec.numInputs; i++)
|
|
{
|
|
bool isBoolVal = de::inRange<int>(spec.inputs[i].type, TYPE_BOOL, TYPE_BOOL_VEC4);
|
|
bool isIntVal = de::inRange<int>(spec.inputs[i].type, TYPE_INT, TYPE_INT_VEC4);
|
|
// \note Mediump interpolators are used for booleans and lowp ints.
|
|
Precision prec = isBoolVal || (isIntVal && spec.precision == PRECISION_LOWP) ? PRECISION_MEDIUMP : spec.precision;
|
|
inputPrecision[i] = getPrecisionName(prec);
|
|
}
|
|
|
|
// Attributes.
|
|
vtx << "attribute highp vec4 a_position;\n";
|
|
for (int i = 0; i < spec.numInputs; i++)
|
|
vtx << "attribute " << inputPrecision[i] << " vec4 a_in" << i << ";\n";
|
|
|
|
if (isVertexCase)
|
|
{
|
|
vtx << "varying mediump vec4 v_color;\n";
|
|
frag << "varying mediump vec4 v_color;\n";
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < spec.numInputs; i++)
|
|
{
|
|
vtx << "varying " << inputPrecision[i] << " vec4 v_in" << i << ";\n";
|
|
frag << "varying " << inputPrecision[i] << " vec4 v_in" << i << ";\n";
|
|
}
|
|
}
|
|
|
|
vtx << "\n";
|
|
vtx << "void main()\n";
|
|
vtx << "{\n";
|
|
vtx << " gl_Position = a_position;\n";
|
|
|
|
frag << "\n";
|
|
frag << "void main()\n";
|
|
frag << "{\n";
|
|
|
|
// Expression inputs.
|
|
string prefix = isVertexCase ? "a_" : "v_";
|
|
for (int i = 0; i < spec.numInputs; i++)
|
|
{
|
|
DataType inType = spec.inputs[i].type;
|
|
int inSize = getDataTypeScalarSize(inType);
|
|
bool isInt = de::inRange<int>(inType, TYPE_INT, TYPE_INT_VEC4);
|
|
bool isBool = de::inRange<int>(inType, TYPE_BOOL, TYPE_BOOL_VEC4);
|
|
const char* typeName = getDataTypeName(inType);
|
|
const char* swizzle = s_inSwizzles[i][inSize-1];
|
|
|
|
op << "\t";
|
|
if (precision && !isBool) op << precision << " ";
|
|
|
|
op << typeName << " in" << i << " = ";
|
|
|
|
if (isBool)
|
|
{
|
|
if (inSize == 1) op << "(";
|
|
else op << "greaterThan(";
|
|
}
|
|
else if (isInt)
|
|
op << typeName << "(";
|
|
|
|
op << prefix << "in" << i << "." << swizzle;
|
|
|
|
if (isBool)
|
|
{
|
|
if (inSize == 1) op << " > 0.0)";
|
|
else op << ", vec" << inSize << "(0.0))";
|
|
}
|
|
else if (isInt)
|
|
op << ")";
|
|
|
|
op << ";\n";
|
|
}
|
|
|
|
// Result variable.
|
|
{
|
|
const char* outTypeName = getDataTypeName(spec.output);
|
|
bool isBoolOut = de::inRange<int>(spec.output, TYPE_BOOL, TYPE_BOOL_VEC4);
|
|
|
|
op << "\t";
|
|
if (precision && !isBoolOut) op << precision << " ";
|
|
op << outTypeName << " res = " << outTypeName << "(0.0);\n\n";
|
|
}
|
|
|
|
// Expression.
|
|
op << "\t" << shaderOp << "\n\n";
|
|
|
|
// Convert to color.
|
|
bool isResFloatVec = de::inRange<int>(spec.output, TYPE_FLOAT, TYPE_FLOAT_VEC4);
|
|
int outScalarSize = getDataTypeScalarSize(spec.output);
|
|
|
|
op << "\tmediump vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n";
|
|
op << "\tcolor." << s_outSwizzles[outScalarSize-1] << " = ";
|
|
|
|
if (!isResFloatVec && outScalarSize == 1)
|
|
op << "float(res)";
|
|
else if (!isResFloatVec)
|
|
op << "vec" << outScalarSize << "(res)";
|
|
else
|
|
op << "res";
|
|
|
|
op << ";\n";
|
|
|
|
// Scale & bias.
|
|
float resultScale = spec.resultScale;
|
|
float resultBias = spec.resultBias;
|
|
if ((resultScale != 1.0f) || (resultBias != 0.0f))
|
|
{
|
|
op << "\tcolor = color";
|
|
if (resultScale != 1.0f) op << " * " << de::floatToString(resultScale, 2);
|
|
if (resultBias != 0.0f) op << " + " << de::floatToString(resultBias, 2);
|
|
op << ";\n";
|
|
}
|
|
|
|
// ..
|
|
if (isVertexCase)
|
|
{
|
|
vtx << " v_color = color;\n";
|
|
frag << " gl_FragColor = v_color;\n";
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < spec.numInputs; i++)
|
|
vtx << " v_in" << i << " = a_in" << i << ";\n";
|
|
frag << " gl_FragColor = color;\n";
|
|
}
|
|
|
|
vtx << "}\n";
|
|
frag << "}\n";
|
|
|
|
m_vertShaderSource = vtx.str();
|
|
m_fragShaderSource = frag.str();
|
|
|
|
// Setup the user attributes.
|
|
m_userAttribTransforms.resize(spec.numInputs);
|
|
for (int inputNdx = 0; inputNdx < spec.numInputs; inputNdx++)
|
|
{
|
|
const ShaderValue& v = spec.inputs[inputNdx];
|
|
DE_ASSERT(v.type != TYPE_LAST);
|
|
|
|
float scale = (v.rangeMax - v.rangeMin);
|
|
float minBias = v.rangeMin;
|
|
float maxBias = v.rangeMax;
|
|
Mat4 attribMatrix;
|
|
|
|
for (int rowNdx = 0; rowNdx < 4; rowNdx++)
|
|
{
|
|
Vec4 row;
|
|
|
|
switch ((rowNdx + inputNdx) % 4)
|
|
{
|
|
case 0: row = Vec4(scale, 0.0f, 0.0f, minBias); break;
|
|
case 1: row = Vec4(0.0f, scale, 0.0f, minBias); break;
|
|
case 2: row = Vec4(-scale, 0.0f, 0.0f, maxBias); break;
|
|
case 3: row = Vec4(0.0f, -scale, 0.0f, maxBias); break;
|
|
default: DE_ASSERT(false);
|
|
}
|
|
|
|
attribMatrix.setRow(rowNdx, row);
|
|
}
|
|
|
|
m_userAttribTransforms[inputNdx] = attribMatrix;
|
|
}
|
|
}
|
|
|
|
ShaderOperatorCase::~ShaderOperatorCase (void)
|
|
{
|
|
}
|
|
|
|
// ShaderOperatorTests.
|
|
|
|
ShaderOperatorTests::ShaderOperatorTests(Context& context)
|
|
: TestCaseGroup(context, "operator", "Operator tests.")
|
|
{
|
|
}
|
|
|
|
ShaderOperatorTests::~ShaderOperatorTests (void)
|
|
{
|
|
}
|
|
|
|
// Vector math functions.
|
|
template<typename T> inline T nop (T f) { return f; }
|
|
|
|
template <typename T, int Size>
|
|
Vector<T, Size> nop (const Vector<T, Size>& v) { return v; }
|
|
|
|
#define DECLARE_UNARY_GENTYPE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_float (ShaderEvalContext& c) { c.color.x() = FUNC_NAME(c.in[0].swizzle(2)).x(); } \
|
|
void eval_##FUNC_NAME##_vec2 (ShaderEvalContext& c) { c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1)); } \
|
|
void eval_##FUNC_NAME##_vec3 (ShaderEvalContext& c) { c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1)); } \
|
|
void eval_##FUNC_NAME##_vec4 (ShaderEvalContext& c) { c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0)); }
|
|
|
|
#define DECLARE_BINARY_GENTYPE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_float (ShaderEvalContext& c) { c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0)).x(); } \
|
|
void eval_##FUNC_NAME##_vec2 (ShaderEvalContext& c) { c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0)); } \
|
|
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)); } \
|
|
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)); }
|
|
|
|
#define DECLARE_TERNARY_GENTYPE_FUNCS(FUNC_NAME) \
|
|
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(); } \
|
|
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)); } \
|
|
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)); } \
|
|
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)); }
|
|
|
|
#define DECLARE_UNARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_float (ShaderEvalContext& c) { c.color.x() = FUNC_NAME(c.in[0].swizzle(2)); } \
|
|
void eval_##FUNC_NAME##_vec2 (ShaderEvalContext& c) { c.color.x() = FUNC_NAME(c.in[0].swizzle(3, 1)); } \
|
|
void eval_##FUNC_NAME##_vec3 (ShaderEvalContext& c) { c.color.x() = FUNC_NAME(c.in[0].swizzle(2, 0, 1)); } \
|
|
void eval_##FUNC_NAME##_vec4 (ShaderEvalContext& c) { c.color.x() = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0)); }
|
|
|
|
#define DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_float (ShaderEvalContext& c) { c.color.x() = FUNC_NAME(c.in[0].swizzle(2), c.in[1].swizzle(0)); } \
|
|
void eval_##FUNC_NAME##_vec2 (ShaderEvalContext& c) { c.color.x() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].swizzle(1, 0)); } \
|
|
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)); } \
|
|
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)); }
|
|
|
|
#define DECLARE_BINARY_BOOL_FUNCS(FUNC_NAME) \
|
|
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); }
|
|
|
|
#define DECLARE_UNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_bool (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(c.in[0].z() > 0.0f); } \
|
|
void eval_##FUNC_NAME##_bvec2 (ShaderEvalContext& c) { c.color.yz() = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat(); } \
|
|
void eval_##FUNC_NAME##_bvec3 (ShaderEvalContext& c) { c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat(); } \
|
|
void eval_##FUNC_NAME##_bvec4 (ShaderEvalContext& c) { c.color = FUNC_NAME(greaterThan(c.in[0].swizzle(1, 2, 3, 0), Vec4(0.0f))).asFloat(); }
|
|
|
|
#define DECLARE_TERNARY_BOOL_GENTYPE_FUNCS(FUNC_NAME) \
|
|
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); } \
|
|
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(); } \
|
|
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(); } \
|
|
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(); }
|
|
|
|
#define DECLARE_UNARY_INT_GENTYPE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_int (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME((int)c.in[0].z()); } \
|
|
void eval_##FUNC_NAME##_ivec2 (ShaderEvalContext& c) { c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asInt()).asFloat(); } \
|
|
void eval_##FUNC_NAME##_ivec3 (ShaderEvalContext& c) { c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asInt()).asFloat(); } \
|
|
void eval_##FUNC_NAME##_ivec4 (ShaderEvalContext& c) { c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asInt()).asFloat(); }
|
|
|
|
#define DECLARE_BINARY_INT_GENTYPE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_int (ShaderEvalContext& c) { c.color.x() = (float)tcu::FUNC_NAME((int)c.in[0].z(), (int)c.in[1].x()); } \
|
|
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(); } \
|
|
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(); } \
|
|
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(); }
|
|
|
|
#define DECLARE_TERNARY_INT_GENTYPE_FUNCS(FUNC_NAME) \
|
|
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()); } \
|
|
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(); } \
|
|
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(); } \
|
|
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(); }
|
|
|
|
#define DECLARE_VEC_FLOAT_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_vec2 (ShaderEvalContext& c) { c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1), c.in[1].x()); } \
|
|
void eval_##FUNC_NAME##_vec3 (ShaderEvalContext& c) { c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1), c.in[1].x()); } \
|
|
void eval_##FUNC_NAME##_vec4 (ShaderEvalContext& c) { c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0), c.in[1].x()); }
|
|
|
|
#define DECLARE_VEC_FLOAT_FLOAT_FUNCS(FUNC_NAME) \
|
|
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()); } \
|
|
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()); } \
|
|
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()); }
|
|
|
|
#define DECLARE_VEC_VEC_FLOAT_FUNCS(FUNC_NAME) \
|
|
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()); } \
|
|
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()); } \
|
|
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()); }
|
|
|
|
#define DECLARE_FLOAT_FLOAT_VEC_FUNCS(FUNC_NAME) \
|
|
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)); } \
|
|
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)); } \
|
|
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)); }
|
|
|
|
#define DECLARE_FLOAT_VEC_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_vec2 (ShaderEvalContext& c) { c.color.yz() = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(1, 0)); } \
|
|
void eval_##FUNC_NAME##_vec3 (ShaderEvalContext& c) { c.color.xyz() = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(1, 2, 0)); } \
|
|
void eval_##FUNC_NAME##_vec4 (ShaderEvalContext& c) { c.color = FUNC_NAME(c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0)); }
|
|
|
|
#define DECLARE_IVEC_INT_FUNCS(FUNC_NAME) \
|
|
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(); } \
|
|
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(); } \
|
|
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(); }
|
|
|
|
#define DECLARE_INT_IVEC_FUNCS(FUNC_NAME) \
|
|
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(); } \
|
|
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(); } \
|
|
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(); }
|
|
|
|
// Operators.
|
|
|
|
DECLARE_UNARY_GENTYPE_FUNCS(nop)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(negate)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(addOne)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(subOne)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(add)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(sub)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(mul)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(div)
|
|
|
|
void eval_selection_float (ShaderEvalContext& c) { c.color.x() = selection(c.in[0].z() > 0.0f, c.in[1].x(), c.in[2].y()); }
|
|
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)); }
|
|
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)); }
|
|
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)); }
|
|
|
|
DECLARE_UNARY_INT_GENTYPE_FUNCS(nop)
|
|
DECLARE_UNARY_INT_GENTYPE_FUNCS(negate)
|
|
DECLARE_UNARY_INT_GENTYPE_FUNCS(addOne)
|
|
DECLARE_UNARY_INT_GENTYPE_FUNCS(subOne)
|
|
DECLARE_BINARY_INT_GENTYPE_FUNCS(add)
|
|
DECLARE_BINARY_INT_GENTYPE_FUNCS(sub)
|
|
DECLARE_BINARY_INT_GENTYPE_FUNCS(mul)
|
|
DECLARE_BINARY_INT_GENTYPE_FUNCS(div)
|
|
|
|
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()); }
|
|
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(); }
|
|
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(); }
|
|
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(); }
|
|
|
|
DECLARE_UNARY_BOOL_GENTYPE_FUNCS(boolNot)
|
|
DECLARE_BINARY_BOOL_FUNCS(logicalAnd)
|
|
DECLARE_BINARY_BOOL_FUNCS(logicalOr)
|
|
DECLARE_BINARY_BOOL_FUNCS(logicalXor)
|
|
|
|
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); }
|
|
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(); }
|
|
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(); }
|
|
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(); }
|
|
|
|
DECLARE_VEC_FLOAT_FUNCS(addVecScalar)
|
|
DECLARE_VEC_FLOAT_FUNCS(subVecScalar)
|
|
DECLARE_VEC_FLOAT_FUNCS(mulVecScalar)
|
|
DECLARE_VEC_FLOAT_FUNCS(divVecScalar)
|
|
|
|
DECLARE_FLOAT_VEC_FUNCS(addScalarVec)
|
|
DECLARE_FLOAT_VEC_FUNCS(subScalarVec)
|
|
DECLARE_FLOAT_VEC_FUNCS(mulScalarVec)
|
|
DECLARE_FLOAT_VEC_FUNCS(divScalarVec)
|
|
|
|
DECLARE_IVEC_INT_FUNCS(addVecScalar)
|
|
DECLARE_IVEC_INT_FUNCS(subVecScalar)
|
|
DECLARE_IVEC_INT_FUNCS(mulVecScalar)
|
|
DECLARE_IVEC_INT_FUNCS(divVecScalar)
|
|
|
|
DECLARE_INT_IVEC_FUNCS(addScalarVec)
|
|
DECLARE_INT_IVEC_FUNCS(subScalarVec)
|
|
DECLARE_INT_IVEC_FUNCS(mulScalarVec)
|
|
DECLARE_INT_IVEC_FUNCS(divScalarVec)
|
|
|
|
// Built-in functions.
|
|
|
|
DECLARE_UNARY_GENTYPE_FUNCS(radians)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(degrees)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(sin)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(cos)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(tan)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(asin)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(acos)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(atan)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(atan2)
|
|
|
|
DECLARE_BINARY_GENTYPE_FUNCS(pow)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(exp)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(log)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(exp2)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(log2)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(sqrt)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(inverseSqrt)
|
|
|
|
DECLARE_UNARY_GENTYPE_FUNCS(abs)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(sign)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(floor)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(ceil)
|
|
DECLARE_UNARY_GENTYPE_FUNCS(fract)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(mod)
|
|
DECLARE_VEC_FLOAT_FUNCS(modVecFloat)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(min)
|
|
DECLARE_VEC_FLOAT_FUNCS(minVecFloat)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(max)
|
|
DECLARE_VEC_FLOAT_FUNCS(maxVecFloat)
|
|
DECLARE_TERNARY_GENTYPE_FUNCS(clamp)
|
|
DECLARE_VEC_FLOAT_FLOAT_FUNCS(clampVecFloatFloat)
|
|
DECLARE_TERNARY_GENTYPE_FUNCS(mix)
|
|
DECLARE_VEC_VEC_FLOAT_FUNCS(mixVecVecFloat)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(step)
|
|
DECLARE_FLOAT_VEC_FUNCS(stepFloatVec)
|
|
DECLARE_TERNARY_GENTYPE_FUNCS(smoothStep)
|
|
DECLARE_FLOAT_FLOAT_VEC_FUNCS(smoothStepFloatFloatVec)
|
|
|
|
DECLARE_UNARY_SCALAR_GENTYPE_FUNCS(length)
|
|
DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(distance)
|
|
DECLARE_BINARY_SCALAR_GENTYPE_FUNCS(dot)
|
|
void eval_cross_vec3 (ShaderEvalContext& c) { c.color.xyz() = cross(c.in[0].swizzle(2, 0, 1), c.in[1].swizzle(1, 2, 0)); }
|
|
|
|
DECLARE_UNARY_GENTYPE_FUNCS(normalize)
|
|
DECLARE_TERNARY_GENTYPE_FUNCS(faceForward)
|
|
DECLARE_BINARY_GENTYPE_FUNCS(reflect)
|
|
|
|
void eval_refract_float (ShaderEvalContext& c) { c.color.x() = refract(c.in[0].z(), c.in[1].x(), c.in[2].y()); }
|
|
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()); }
|
|
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()); }
|
|
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()); }
|
|
|
|
// Compare functions.
|
|
|
|
#define DECLARE_FLOAT_COMPARE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_float (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(c.in[0].z(), c.in[1].x()); } \
|
|
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)); } \
|
|
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)); } \
|
|
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)); }
|
|
|
|
#define DECLARE_FLOAT_CWISE_COMPARE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_float (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(c.in[0].z(), c.in[1].x()); } \
|
|
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(); } \
|
|
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(); } \
|
|
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(); }
|
|
|
|
#define DECLARE_INT_COMPARE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_int (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x())); } \
|
|
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))); } \
|
|
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))); } \
|
|
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))); }
|
|
|
|
#define DECLARE_INT_CWISE_COMPARE_FUNCS(FUNC_NAME) \
|
|
void eval_##FUNC_NAME##_int (ShaderEvalContext& c) { c.color.x() = (float)FUNC_NAME(chopToInt(c.in[0].z()), chopToInt(c.in[1].x())); } \
|
|
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(); } \
|
|
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(); } \
|
|
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(); }
|
|
|
|
#define DECLARE_BOOL_COMPARE_FUNCS(FUNC_NAME) \
|
|
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); } \
|
|
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))); } \
|
|
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))); } \
|
|
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))); }
|
|
|
|
#define DECLARE_BOOL_CWISE_COMPARE_FUNCS(FUNC_NAME) \
|
|
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); } \
|
|
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(); } \
|
|
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(); } \
|
|
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(); }
|
|
|
|
DECLARE_FLOAT_COMPARE_FUNCS(allEqual)
|
|
DECLARE_FLOAT_COMPARE_FUNCS(anyNotEqual)
|
|
DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThan)
|
|
DECLARE_FLOAT_CWISE_COMPARE_FUNCS(lessThanEqual)
|
|
DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThan)
|
|
DECLARE_FLOAT_CWISE_COMPARE_FUNCS(greaterThanEqual)
|
|
DECLARE_FLOAT_CWISE_COMPARE_FUNCS(equal)
|
|
DECLARE_FLOAT_CWISE_COMPARE_FUNCS(notEqual)
|
|
|
|
DECLARE_INT_COMPARE_FUNCS(allEqual)
|
|
DECLARE_INT_COMPARE_FUNCS(anyNotEqual)
|
|
DECLARE_INT_CWISE_COMPARE_FUNCS(lessThan)
|
|
DECLARE_INT_CWISE_COMPARE_FUNCS(lessThanEqual)
|
|
DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThan)
|
|
DECLARE_INT_CWISE_COMPARE_FUNCS(greaterThanEqual)
|
|
DECLARE_INT_CWISE_COMPARE_FUNCS(equal)
|
|
DECLARE_INT_CWISE_COMPARE_FUNCS(notEqual)
|
|
|
|
DECLARE_BOOL_COMPARE_FUNCS(allEqual)
|
|
DECLARE_BOOL_COMPARE_FUNCS(anyNotEqual)
|
|
DECLARE_BOOL_CWISE_COMPARE_FUNCS(equal)
|
|
DECLARE_BOOL_CWISE_COMPARE_FUNCS(notEqual)
|
|
|
|
// Boolean functions.
|
|
|
|
#define DECLARE_UNARY_SCALAR_BVEC_FUNCS(GLSL_NAME, FUNC_NAME) \
|
|
void eval_##GLSL_NAME##_bvec2 (ShaderEvalContext& c) { c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f)))); } \
|
|
void eval_##GLSL_NAME##_bvec3 (ShaderEvalContext& c) { c.color.x() = float(FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f)))); } \
|
|
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)))); }
|
|
|
|
#define DECLARE_UNARY_BVEC_BVEC_FUNCS(GLSL_NAME, FUNC_NAME) \
|
|
void eval_##GLSL_NAME##_bvec2 (ShaderEvalContext& c) { c.color.yz() = FUNC_NAME(greaterThan(c.in[0].swizzle(3, 1), Vec2(0.0f))).asFloat(); } \
|
|
void eval_##GLSL_NAME##_bvec3 (ShaderEvalContext& c) { c.color.xyz() = FUNC_NAME(greaterThan(c.in[0].swizzle(2, 0, 1), Vec3(0.0f))).asFloat(); } \
|
|
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(); }
|
|
|
|
DECLARE_UNARY_SCALAR_BVEC_FUNCS(any, boolAny)
|
|
DECLARE_UNARY_SCALAR_BVEC_FUNCS(all, boolAll)
|
|
|
|
void ShaderOperatorTests::init (void)
|
|
{
|
|
// Requisites:
|
|
// - input types (const, uniform, dynamic, mixture)
|
|
// - data types (bool, int, float, vecs, mats)
|
|
// -
|
|
// - complex expressions (\todo [petri] move to expressions?)
|
|
// * early-exit from side effects
|
|
// * precedence
|
|
|
|
// unary plus, minus
|
|
// add, sub
|
|
// mul (larger range)
|
|
// div (div-by-zero)
|
|
// incr, decr (int only)
|
|
// relational
|
|
// equality
|
|
// logical
|
|
// selection
|
|
// assignment
|
|
// arithmetic assignment
|
|
|
|
// parenthesis
|
|
// sequence
|
|
// subscript, function call, field selector/swizzler
|
|
|
|
// precedence
|
|
// data types (float, int, bool, vecs, matrices)
|
|
|
|
// TestCaseGroup* group = new TestCaseGroup(m_testCtx, "additive", "Additive operator tests.");
|
|
// addChild(group);
|
|
|
|
// * * *
|
|
|
|
// Built-in functions
|
|
// - precision, data types
|
|
|
|
#define BOOL_FUNCS(FUNC_NAME) eval_##FUNC_NAME##_bool, DE_NULL, DE_NULL, DE_NULL
|
|
|
|
#define FLOAT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
|
|
#define INT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
|
|
#define BOOL_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
|
|
|
|
#define FLOAT_GENTYPE_FUNCS(FUNC_NAME) eval_##FUNC_NAME##_float, eval_##FUNC_NAME##_vec2, eval_##FUNC_NAME##_vec3, eval_##FUNC_NAME##_vec4
|
|
#define INT_GENTYPE_FUNCS(FUNC_NAME) eval_##FUNC_NAME##_int, eval_##FUNC_NAME##_ivec2, eval_##FUNC_NAME##_ivec3, eval_##FUNC_NAME##_ivec4
|
|
#define BOOL_GENTYPE_FUNCS(FUNC_NAME) eval_##FUNC_NAME##_bool, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
|
|
|
|
Value notUsed = Value(VALUE_NONE, 0.0f, 0.0f);
|
|
|
|
std::vector<BuiltinFuncGroup> funcInfoGroups;
|
|
|
|
// Unary operators.
|
|
funcInfoGroups.push_back(
|
|
BuiltinFuncGroup("unary_operator", "Unary operator tests")
|
|
<< BuiltinOperInfo("plus", "+", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(nop))
|
|
<< BuiltinOperInfo("plus", "+", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(nop))
|
|
<< BuiltinOperInfo("minus", "-", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(negate))
|
|
<< BuiltinOperInfo("minus", "-", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(negate))
|
|
<< 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)
|
|
|
|
// Pre/post incr/decr side effect cases.
|
|
<< BuiltinSideEffOperInfo ("pre_increment_effect", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
|
|
<< BuiltinSideEffOperInfo ("pre_increment_effect", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
|
|
<< BuiltinSideEffOperInfo ("pre_decrement_effect", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 1.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
|
|
<< BuiltinSideEffOperInfo ("pre_decrement_effect", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
|
|
<< BuiltinPostSideEffOperInfo ("post_increment_effect", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
|
|
<< BuiltinPostSideEffOperInfo ("post_increment_effect", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
|
|
<< BuiltinPostSideEffOperInfo ("post_decrement_effect", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 1.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
|
|
<< BuiltinPostSideEffOperInfo ("post_decrement_effect", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
|
|
|
|
// Pre/post incr/decr result cases.
|
|
<< BuiltinOperInfo ("pre_increment_result", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(addOne))
|
|
<< BuiltinOperInfo ("pre_increment_result", "++", IGT, Value(IGT, -6.0f, 4.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(addOne))
|
|
<< BuiltinOperInfo ("pre_decrement_result", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 1.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(subOne))
|
|
<< BuiltinOperInfo ("pre_decrement_result", "--", IGT, Value(IGT, -4.0f, 6.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(subOne))
|
|
<< BuiltinPostOperInfo ("post_increment_result", "++", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(nop))
|
|
<< BuiltinPostOperInfo ("post_increment_result", "++", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(nop))
|
|
<< BuiltinPostOperInfo ("post_decrement_result", "--", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(nop))
|
|
<< BuiltinPostOperInfo ("post_decrement_result", "--", IGT, Value(IGT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(nop))
|
|
);
|
|
|
|
// Binary operators.
|
|
funcInfoGroups.push_back(
|
|
BuiltinFuncGroup("binary_operator", "Binary operator tests")
|
|
// Arithmetic operators.
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
|
|
// Arithmetic assignment side effect cases.
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
|
|
// Arithmetic assignment result cases.
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
|
|
// Scalar relational operators.
|
|
<< 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)
|
|
<< 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)
|
|
<< 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)
|
|
<< 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)
|
|
<< 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)
|
|
<< 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)
|
|
<< 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)
|
|
<< 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)
|
|
|
|
// Equality comparison operators.
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
|
|
// Logical operators.
|
|
<< 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))
|
|
<< 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))
|
|
<< 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))
|
|
);
|
|
|
|
// 8.1 Angle and Trigonometry Functions.
|
|
funcInfoGroups.push_back(
|
|
BuiltinFuncGroup("angle_and_trigonometry", "Angle and trigonometry function tests.")
|
|
<< BuiltinFuncInfo("radians", "radians", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 25.0f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(radians) )
|
|
<< BuiltinFuncInfo("degrees", "degrees", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 0.04f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(degrees) )
|
|
<< BuiltinFuncInfo("sin", "sin", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(sin) )
|
|
<< BuiltinFuncInfo("sin", "sin", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(sin) )
|
|
<< BuiltinFuncInfo("cos", "cos", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(cos) )
|
|
<< BuiltinFuncInfo("cos", "cos", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(cos) )
|
|
<< BuiltinFuncInfo("tan", "tan", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(tan) )
|
|
<< BuiltinFuncInfo("tan", "tan", GT, Value(GT, -1.5f, 5.5f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(tan) )
|
|
<< BuiltinFuncInfo("asin", "asin", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(asin) )
|
|
<< BuiltinFuncInfo("acos", "acos", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(acos) )
|
|
<< BuiltinFuncInfo("atan", "atan", GT, Value(GT, -4.0f, 4.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(atan) )
|
|
<< 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) )
|
|
);
|
|
|
|
// 8.2 Exponential Functions.
|
|
funcInfoGroups.push_back(
|
|
BuiltinFuncGroup("exponential", "Exponential function tests")
|
|
<< 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) )
|
|
<< BuiltinFuncInfo("exp", "exp", GT, Value(GT, -6.0f, 3.0f), notUsed, notUsed, 0.5f, 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(exp) )
|
|
<< BuiltinFuncInfo("log", "log", GT, Value(GT, 0.1f, 10.0f), notUsed, notUsed, 0.5f, 0.3f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(log) )
|
|
<< BuiltinFuncInfo("exp2", "exp2", GT, Value(GT, -7.0f, 2.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(exp2) )
|
|
<< BuiltinFuncInfo("log2", "log2", GT, Value(GT, 0.1f, 10.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(log2) )
|
|
<< BuiltinFuncInfo("sqrt", "sqrt", GT, Value(GT, 0.0f, 10.0f), notUsed, notUsed, 0.3f, 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(sqrt) )
|
|
<< BuiltinFuncInfo("inversesqrt", "inversesqrt", GT, Value(GT, 0.5f, 10.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(inverseSqrt) )
|
|
);
|
|
|
|
// 8.3 Common Functions.
|
|
funcInfoGroups.push_back(
|
|
BuiltinFuncGroup("common_functions", "Common function tests.")
|
|
<< BuiltinFuncInfo("abs", "abs", GT, Value(GT, -2.0f, 2.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(abs) )
|
|
<< BuiltinFuncInfo("sign", "sign", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.3f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(sign) )
|
|
<< BuiltinFuncInfo("floor", "floor", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.7f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(floor) )
|
|
<< BuiltinFuncInfo("ceil", "ceil", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.5f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(ceil) )
|
|
<< BuiltinFuncInfo("fract", "fract", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.8f, 0.1f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(fract) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
);
|
|
|
|
// 8.4 Geometric Functions.
|
|
funcInfoGroups.push_back(
|
|
BuiltinFuncGroup("geometric", "Geometric function tests.")
|
|
<< BuiltinFuncInfo("length", "length", F, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.1f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(length) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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 )
|
|
<< BuiltinFuncInfo("normalize", "normalize", GT, Value(GT, 0.1f, 4.0f), notUsed, notUsed, 0.5f, 0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(normalize) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
);
|
|
|
|
// 8.5 Matrix Functions.
|
|
// separate matrix tests?
|
|
// funcInfoGroups.push_back(
|
|
// BuiltinFuncGroup("matrix", "Matrix function tests.")
|
|
// << BuiltinFuncInfo("matrixCompMult", "matrixCompMult", M, ... )
|
|
// );
|
|
|
|
// 8.6 Vector Relational Functions.
|
|
funcInfoGroups.push_back(
|
|
BuiltinFuncGroup("float_compare", "Floating point comparison tests.")
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
);
|
|
|
|
funcInfoGroups.push_back(
|
|
BuiltinFuncGroup("int_compare", "Integer comparison tests.")
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
<< 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) )
|
|
);
|
|
|
|
funcInfoGroups.push_back(
|
|
BuiltinFuncGroup("bool_compare", "Boolean comparison tests.")
|
|
<< 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) )
|
|
<< 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) )
|
|
<< BuiltinFuncInfo("any", "any", B, Value(BV, -1.0f, 0.3f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_NA, BOOL_VEC_FUNCS(any) )
|
|
<< BuiltinFuncInfo("all", "all", B, Value(BV, -0.3f, 1.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_NA, BOOL_VEC_FUNCS(all) )
|
|
<< BuiltinFuncInfo("not", "not", BV, Value(BV, -1.0f, 1.0f), notUsed, notUsed, 1.0f, 0.0f, PRECMASK_NA, BOOL_VEC_FUNCS(boolNot) )
|
|
);
|
|
|
|
// 8.7 Texture Lookup Functions
|
|
// texture2D (sampler, vec2)
|
|
// texture2D (sampler, vec2, bias)
|
|
// texture2DProj (sampler, vec3)
|
|
// texture2DProj (sampler, vec3, bias)
|
|
// texture2DProj (sampler, vec4)
|
|
// texture2DProj (sampler, vec4, bias)
|
|
// texture2DLod (sampler, vec2, lod)
|
|
// texture2DProjLod (sampler, vec3, lod)
|
|
// texture2DProjLod (sampler, vec4, lod)
|
|
// textureCube (sampler, vec3)
|
|
// textureCube (sampler, vec3, bias)
|
|
// textureCubeLod (sampler, vec3, lod)
|
|
|
|
static const ShaderType s_shaderTypes[] =
|
|
{
|
|
SHADERTYPE_VERTEX,
|
|
SHADERTYPE_FRAGMENT
|
|
};
|
|
|
|
static const DataType s_floatTypes[] =
|
|
{
|
|
TYPE_FLOAT,
|
|
TYPE_FLOAT_VEC2,
|
|
TYPE_FLOAT_VEC3,
|
|
TYPE_FLOAT_VEC4
|
|
};
|
|
|
|
static const DataType s_intTypes[] =
|
|
{
|
|
TYPE_INT,
|
|
TYPE_INT_VEC2,
|
|
TYPE_INT_VEC3,
|
|
TYPE_INT_VEC4
|
|
};
|
|
|
|
static const DataType s_boolTypes[] =
|
|
{
|
|
TYPE_BOOL,
|
|
TYPE_BOOL_VEC2,
|
|
TYPE_BOOL_VEC3,
|
|
TYPE_BOOL_VEC4
|
|
};
|
|
|
|
for (int outerGroupNdx = 0; outerGroupNdx < (int)funcInfoGroups.size(); outerGroupNdx++)
|
|
{
|
|
// Create outer group.
|
|
const BuiltinFuncGroup& outerGroupInfo = funcInfoGroups[outerGroupNdx];
|
|
TestCaseGroup* outerGroup = new TestCaseGroup(m_context, outerGroupInfo.name, outerGroupInfo.description);
|
|
addChild(outerGroup);
|
|
|
|
// Only create new group if name differs from previous one.
|
|
TestCaseGroup* innerGroup = DE_NULL;
|
|
|
|
for (int funcInfoNdx = 0; funcInfoNdx < (int)outerGroupInfo.funcInfos.size(); funcInfoNdx++)
|
|
{
|
|
const BuiltinFuncInfo& funcInfo = outerGroupInfo.funcInfos[funcInfoNdx];
|
|
const char* shaderFuncName = funcInfo.shaderFuncName;
|
|
bool isBoolCase = (funcInfo.precisionMask == PRECMASK_NA);
|
|
bool isIntCase = (funcInfo.input0.valueType & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
|
|
bool isFloatCase = !isBoolCase && !isIntCase; // \todo [petri] Better check.
|
|
bool isBoolOut = (funcInfo.outValue & (VALUE_BOOL | VALUE_BOOL_VEC | VALUE_BOOL_GENTYPE)) != 0;
|
|
bool isIntOut = (funcInfo.outValue & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
|
|
bool isFloatOut = !isBoolOut && !isIntOut;
|
|
|
|
if (!innerGroup || (string(innerGroup->getName()) != funcInfo.caseName))
|
|
{
|
|
string groupDesc = string("Built-in function ") + shaderFuncName + "() tests.";
|
|
innerGroup = new TestCaseGroup(m_context, funcInfo.caseName, groupDesc.c_str());
|
|
outerGroup->addChild(innerGroup);
|
|
}
|
|
|
|
for (int inScalarSize = 1; inScalarSize <= 4; inScalarSize++)
|
|
{
|
|
int outScalarSize = ((funcInfo.outValue == VALUE_FLOAT) || (funcInfo.outValue == VALUE_BOOL)) ? 1 : inScalarSize; // \todo [petri] Int.
|
|
DataType outDataType = isFloatOut ? s_floatTypes[outScalarSize - 1]
|
|
: isIntOut ? s_intTypes[outScalarSize - 1]
|
|
: isBoolOut ? s_boolTypes[outScalarSize - 1]
|
|
: TYPE_LAST;
|
|
|
|
ShaderEvalFunc evalFunc = DE_NULL;
|
|
if (inScalarSize == 1) evalFunc = funcInfo.evalFuncScalar;
|
|
else if (inScalarSize == 2) evalFunc = funcInfo.evalFuncVec2;
|
|
else if (inScalarSize == 3) evalFunc = funcInfo.evalFuncVec3;
|
|
else if (inScalarSize == 4) evalFunc = funcInfo.evalFuncVec4;
|
|
else DE_ASSERT(false);
|
|
|
|
// Skip if no valid eval func.
|
|
// \todo [petri] Better check for V3 only etc. cases?
|
|
if (evalFunc == DE_NULL)
|
|
continue;
|
|
|
|
for (int precision = 0; precision < PRECISION_LAST; precision++)
|
|
{
|
|
if ((funcInfo.precisionMask & (1<<precision)) ||
|
|
(funcInfo.precisionMask == PRECMASK_NA && precision == PRECISION_MEDIUMP)) // use mediump interpolators for booleans
|
|
{
|
|
const char* precisionStr = getPrecisionName((Precision)precision);
|
|
string precisionPrefix = isBoolCase ? "" : (string(precisionStr) + "_");
|
|
|
|
for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
|
|
{
|
|
ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
|
|
ShaderDataSpec shaderSpec;
|
|
const char* shaderTypeName = getShaderTypeName(shaderType);
|
|
bool isVertexCase = (ShaderType)shaderType == SHADERTYPE_VERTEX;
|
|
bool isUnaryOp = (funcInfo.input1.valueType == VALUE_NONE);
|
|
|
|
// \note Data type names will be added to description and name in a following loop.
|
|
string desc = string("Built-in function ") + shaderFuncName + "(";
|
|
string name = precisionPrefix;
|
|
|
|
// Generate shader op.
|
|
string shaderOp = string("res = ");
|
|
|
|
// Setup shader data info.
|
|
shaderSpec.numInputs = 0;
|
|
shaderSpec.precision = isBoolCase ? PRECISION_LAST : (Precision)precision;
|
|
shaderSpec.output = outDataType;
|
|
shaderSpec.resultScale = funcInfo.resultScale;
|
|
shaderSpec.resultBias = funcInfo.resultBias;
|
|
|
|
if (funcInfo.type == OPERATOR)
|
|
{
|
|
if (isUnaryOp && funcInfo.isUnaryPrefix)
|
|
shaderOp += shaderFuncName;
|
|
}
|
|
else if (funcInfo.type == FUNCTION)
|
|
shaderOp += string(shaderFuncName) + "(";
|
|
else // SIDE_EFFECT_OPERATOR
|
|
shaderOp += "in0;\n\t";
|
|
|
|
for (int inputNdx = 0; inputNdx < MAX_INPUTS; inputNdx++)
|
|
{
|
|
const Value& v = (inputNdx == 0) ? funcInfo.input0 : (inputNdx == 1) ? funcInfo.input1 : funcInfo.input2;
|
|
const Value& prevV = (inputNdx == 1) ? funcInfo.input0 : (inputNdx == 2) ? funcInfo.input1 : funcInfo.input2;
|
|
|
|
if (v.valueType == VALUE_NONE)
|
|
continue; // Skip unused input.
|
|
|
|
int curInScalarSize = isScalarType(v.valueType) ? 1 : inScalarSize;
|
|
DataType curInDataType = isFloatCase ? s_floatTypes[curInScalarSize - 1]
|
|
: isIntCase ? s_intTypes[curInScalarSize - 1]
|
|
: isBoolCase ? s_boolTypes[curInScalarSize - 1]
|
|
: TYPE_LAST;
|
|
|
|
// Write input type(s) to case description and name.
|
|
|
|
if (inputNdx > 0)
|
|
desc += ", ";
|
|
|
|
desc += getDataTypeName(curInDataType);
|
|
|
|
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).
|
|
name += string("") + getDataTypeName(curInDataType) + "_";
|
|
|
|
// Generate op input source.
|
|
|
|
if (funcInfo.type == OPERATOR || funcInfo.type == FUNCTION)
|
|
{
|
|
if (inputNdx != 0)
|
|
{
|
|
if (funcInfo.type == OPERATOR && !isUnaryOp)
|
|
shaderOp += " " + string(shaderFuncName) + " ";
|
|
else
|
|
shaderOp += ", ";
|
|
}
|
|
|
|
shaderOp += "in" + de::toString(inputNdx);
|
|
|
|
if (funcInfo.type == OPERATOR && isUnaryOp && !funcInfo.isUnaryPrefix)
|
|
shaderOp += string(shaderFuncName);
|
|
}
|
|
else
|
|
{
|
|
DE_ASSERT(funcInfo.type == SIDE_EFFECT_OPERATOR);
|
|
|
|
if (inputNdx != 0 || (isUnaryOp && funcInfo.isUnaryPrefix))
|
|
shaderOp += string("") + (isUnaryOp ? "" : " ") + shaderFuncName + (isUnaryOp ? "" : " ");
|
|
|
|
shaderOp += inputNdx == 0 ? "res" : "in" + de::toString(inputNdx); // \note in0 has already been assigned to res, so start from in1.
|
|
|
|
if (isUnaryOp && !funcInfo.isUnaryPrefix)
|
|
shaderOp += shaderFuncName;
|
|
}
|
|
|
|
// Fill in shader info.
|
|
shaderSpec.inputs[shaderSpec.numInputs++] = ShaderValue(curInDataType, v.rangeMin, v.rangeMax);
|
|
}
|
|
|
|
if (funcInfo.type == FUNCTION)
|
|
shaderOp += ")";
|
|
|
|
shaderOp += ";";
|
|
|
|
desc += ").";
|
|
name += shaderTypeName;
|
|
|
|
// Create the test case.
|
|
innerGroup->addChild(new ShaderOperatorCase(m_context, name.c_str(), desc.c_str(), isVertexCase, evalFunc, shaderOp.c_str(), shaderSpec));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// The ?: selection operator.
|
|
|
|
static const struct
|
|
{
|
|
DataType type; // The type of "Y" and "Z" operands in "X ? Y : Z" (X is always bool).
|
|
ShaderEvalFunc evalFunc;
|
|
} s_selectionInfo[] =
|
|
{
|
|
{ TYPE_FLOAT, eval_selection_float },
|
|
{ TYPE_FLOAT_VEC2, eval_selection_vec2 },
|
|
{ TYPE_FLOAT_VEC3, eval_selection_vec3 },
|
|
{ TYPE_FLOAT_VEC4, eval_selection_vec4 },
|
|
{ TYPE_INT, eval_selection_int },
|
|
{ TYPE_INT_VEC2, eval_selection_ivec2 },
|
|
{ TYPE_INT_VEC3, eval_selection_ivec3 },
|
|
{ TYPE_INT_VEC4, eval_selection_ivec4 },
|
|
{ TYPE_BOOL, eval_selection_bool },
|
|
{ TYPE_BOOL_VEC2, eval_selection_bvec2 },
|
|
{ TYPE_BOOL_VEC3, eval_selection_bvec3 },
|
|
{ TYPE_BOOL_VEC4, eval_selection_bvec4 }
|
|
};
|
|
|
|
TestCaseGroup* selectionGroup = new TestCaseGroup(m_context, "selection", "Selection operator tests");
|
|
addChild(selectionGroup);
|
|
|
|
for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_selectionInfo); typeNdx++)
|
|
{
|
|
DataType curType = s_selectionInfo[typeNdx].type;
|
|
ShaderEvalFunc evalFunc = s_selectionInfo[typeNdx].evalFunc;
|
|
bool isBoolCase = isDataTypeBoolOrBVec(curType);
|
|
bool isFloatCase = isDataTypeFloatOrVec(curType);
|
|
bool isIntCase = isDataTypeIntOrIVec(curType);
|
|
const char* dataTypeStr = getDataTypeName(curType);
|
|
|
|
DE_ASSERT(isBoolCase || isFloatCase || isIntCase);
|
|
DE_UNREF(isIntCase);
|
|
|
|
for (int precision = 0; precision < (int)PRECISION_LAST; precision++)
|
|
{
|
|
if (isBoolCase && precision != PRECISION_MEDIUMP) // Use mediump interpolators for booleans.
|
|
continue;
|
|
|
|
const char* precisionStr = getPrecisionName((Precision)precision);
|
|
string precisionPrefix = isBoolCase ? "" : (string(precisionStr) + "_");
|
|
|
|
for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
|
|
{
|
|
ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
|
|
ShaderDataSpec shaderSpec;
|
|
const char* shaderTypeName = getShaderTypeName(shaderType);
|
|
bool isVertexCase = (ShaderType)shaderType == SHADERTYPE_VERTEX;
|
|
|
|
string name = precisionPrefix + dataTypeStr + "_" + shaderTypeName;
|
|
|
|
shaderSpec.numInputs = 3;
|
|
shaderSpec.precision = isBoolCase ? PRECISION_LAST : (Precision)precision;
|
|
shaderSpec.output = curType;
|
|
shaderSpec.resultScale = isBoolCase ? 1.0f : isFloatCase ? 0.5f : 0.1f;
|
|
shaderSpec.resultBias = isBoolCase ? 0.0f : isFloatCase ? 0.5f : 0.5f;
|
|
|
|
float rangeMin = isBoolCase ? -1.0f : isFloatCase ? -1.0f : -5.0f;
|
|
float rangeMax = isBoolCase ? 1.0f : isFloatCase ? 1.0f : 5.0f;
|
|
|
|
shaderSpec.inputs[0] = ShaderValue(TYPE_BOOL, -1.0f, 1.0f);
|
|
shaderSpec.inputs[1] = ShaderValue(curType, rangeMin, rangeMax);
|
|
shaderSpec.inputs[2] = ShaderValue(curType, rangeMin, rangeMax);
|
|
|
|
selectionGroup->addChild(new ShaderOperatorCase(m_context, name.c_str(), "", isVertexCase, evalFunc, "res = in0 ? in1 : in2;", shaderSpec));
|
|
}
|
|
}
|
|
}
|
|
|
|
// The sequence operator (comma).
|
|
|
|
TestCaseGroup* sequenceGroup = new TestCaseGroup(m_context, "sequence", "Sequence operator tests");
|
|
addChild(sequenceGroup);
|
|
|
|
TestCaseGroup* sequenceNoSideEffGroup = new TestCaseGroup(m_context, "no_side_effects", "Sequence tests without side-effects");
|
|
TestCaseGroup* sequenceSideEffGroup = new TestCaseGroup(m_context, "side_effects", "Sequence tests with side-effects");
|
|
sequenceGroup->addChild(sequenceNoSideEffGroup);
|
|
sequenceGroup->addChild(sequenceSideEffGroup);
|
|
|
|
static const struct
|
|
{
|
|
bool containsSideEffects;
|
|
const char* caseName;
|
|
const char* expressionStr;
|
|
int numInputs;
|
|
DataType inputTypes[MAX_INPUTS];
|
|
DataType resultType;
|
|
ShaderEvalFunc evalFunc;
|
|
} s_sequenceCases[] =
|
|
{
|
|
{ false, "vec4", "in0, in2 + in1, in1 + in0", 3, { TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4 }, TYPE_FLOAT_VEC4, evalSequenceNoSideEffCase0 },
|
|
{ false, "float_int", "in0 + in2, in1 + in1", 3, { TYPE_FLOAT, TYPE_INT, TYPE_FLOAT }, TYPE_INT, evalSequenceNoSideEffCase1 },
|
|
{ false, "bool_vec2", "in0 && in1, in0, ivec2(vec2(in0) + in2)", 3, { TYPE_BOOL, TYPE_BOOL, TYPE_FLOAT_VEC2 }, TYPE_INT_VEC2, evalSequenceNoSideEffCase2 },
|
|
{ false, "vec4_ivec4_bvec4", "in0 + vec4(in1), in2, in1", 3, { TYPE_FLOAT_VEC4, TYPE_INT_VEC4, TYPE_BOOL_VEC4 }, TYPE_INT_VEC4, evalSequenceNoSideEffCase3 },
|
|
|
|
{ true, "vec4", "in0++, in1 = in0 + in2, in2 = in1", 3, { TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4, TYPE_FLOAT_VEC4 }, TYPE_FLOAT_VEC4, evalSequenceSideEffCase0 },
|
|
{ true, "float_int", "in1++, in0 = float(in1), in1 = int(in0 + in2)", 3, { TYPE_FLOAT, TYPE_INT, TYPE_FLOAT }, TYPE_INT, evalSequenceSideEffCase1 },
|
|
{ true, "bool_vec2", "in1 = in0, in2++, in2 = in2 + vec2(in1), ivec2(in2)", 3, { TYPE_BOOL, TYPE_BOOL, TYPE_FLOAT_VEC2 }, TYPE_INT_VEC2, evalSequenceSideEffCase2 },
|
|
{ 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 }
|
|
};
|
|
|
|
for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_sequenceCases); caseNdx++)
|
|
{
|
|
for (int precision = 0; precision < (int)PRECISION_LAST; precision++)
|
|
{
|
|
for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++)
|
|
{
|
|
ShaderType shaderType = s_shaderTypes[shaderTypeNdx];
|
|
ShaderDataSpec shaderSpec;
|
|
const char* shaderTypeName = getShaderTypeName(shaderType);
|
|
bool isVertexCase = (ShaderType)shaderType == SHADERTYPE_VERTEX;
|
|
|
|
string name = string("") + getPrecisionName((Precision)precision) + "_" + s_sequenceCases[caseNdx].caseName + "_" + shaderTypeName;
|
|
|
|
shaderSpec.numInputs = s_sequenceCases[caseNdx].numInputs;
|
|
shaderSpec.precision = (Precision)precision;
|
|
shaderSpec.output = s_sequenceCases[caseNdx].resultType;
|
|
shaderSpec.resultScale = 0.5f;
|
|
shaderSpec.resultBias = 0.0f;
|
|
|
|
for (int inputNdx = 0; inputNdx < s_sequenceCases[caseNdx].numInputs; inputNdx++)
|
|
{
|
|
DataType type = s_sequenceCases[caseNdx].inputTypes[inputNdx];
|
|
float rangeMin = isDataTypeFloatOrVec(type) ? -0.5f : isDataTypeIntOrIVec(type) ? -2.0f : -1.0f;
|
|
float rangeMax = isDataTypeFloatOrVec(type) ? 0.5f : isDataTypeIntOrIVec(type) ? 2.0f : 1.0f;
|
|
|
|
shaderSpec.inputs[inputNdx] = ShaderValue(type, rangeMin, rangeMax);
|
|
}
|
|
|
|
string expression = string("") + "res = (" + s_sequenceCases[caseNdx].expressionStr + ");";
|
|
|
|
TestCaseGroup* group = s_sequenceCases[caseNdx].containsSideEffects ? sequenceSideEffGroup : sequenceNoSideEffGroup;
|
|
group->addChild(new ShaderOperatorCase(m_context, name.c_str(), "", isVertexCase, s_sequenceCases[caseNdx].evalFunc, expression.c_str(), shaderSpec));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Regression tests for sequence operator.
|
|
// http://khronos.org/registry/webgl/sdk/tests/conformance/glsl/bugs/sequence-operator-evaluation-order.html
|
|
{
|
|
class Case : public ShaderRenderCase
|
|
{
|
|
static void evalFunc(ShaderEvalContext& c) {
|
|
c.color = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); // green
|
|
}
|
|
|
|
public:
|
|
Case(Context& context, const char* name, const char* description, const char* fragShaderSource)
|
|
: ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, false, &evalFunc)
|
|
{
|
|
m_vertShaderSource =
|
|
"attribute vec4 a_position;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = a_position;\n"
|
|
"}\n";
|
|
m_fragShaderSource = fragShaderSource;
|
|
}
|
|
};
|
|
|
|
// ESSL 1.00 section 5.9, about sequence operator:
|
|
// "All expressions are evaluated, in order, from left to right"
|
|
// Also use a ternary operator where the third operand has side effects to make sure
|
|
// only the second operand is evaluated.
|
|
sequenceSideEffGroup->addChild(new Case(m_context, "affect_ternary",
|
|
"Expression where first operand of a sequence operator has side effects which affect the second operand that is a ternary operator", (
|
|
"precision mediump float;\n"
|
|
"bool correct = true;\n"
|
|
"uniform float u_zero;\n"
|
|
"float wrong() {\n"
|
|
" correct = false;\n"
|
|
" return 0.0;\n"
|
|
"}\n"
|
|
"void main() {\n"
|
|
" float a = u_zero - 0.5; // Result should be -0.5.\n"
|
|
" float green = (a++, a > 0.0 ? 1.0 : wrong());\n"
|
|
" gl_FragColor = vec4(0.0, correct ? green : 0.0, 0.0, 1.0);\n"
|
|
"}\n"
|
|
)));
|
|
|
|
sequenceSideEffGroup->addChild(new Case(m_context, "affect_and",
|
|
"Expression where first operand of a sequence operator has side effects which affect the second operand that is an and operator", (
|
|
"precision mediump float;\n"
|
|
"uniform bool u_false;\n"
|
|
"bool sideEffectA = false;\n"
|
|
"bool funcA() {\n"
|
|
" sideEffectA = true;\n"
|
|
" return true;\n"
|
|
"}\n"
|
|
"bool sideEffectB = false;\n"
|
|
"bool funcB() {\n"
|
|
" sideEffectB = true;\n"
|
|
" return true;\n"
|
|
"}\n"
|
|
"void main() {\n"
|
|
" bool b = (funcA(), u_false == sideEffectA && funcB());\n"
|
|
" gl_FragColor = (!b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
|
|
"}\n"
|
|
)));
|
|
|
|
sequenceSideEffGroup->addChild(new Case(m_context, "affect_or",
|
|
"Expression where first operand of a sequence operator has side effects which affect the second operand that is an or operator", (
|
|
"precision mediump float;\n"
|
|
"uniform bool u_false;\n"
|
|
"bool sideEffectA = false;\n"
|
|
"bool funcA() {\n"
|
|
" sideEffectA = true;\n"
|
|
" return false;\n"
|
|
"}\n"
|
|
"bool sideEffectB = false;\n"
|
|
"bool funcB() {\n"
|
|
" sideEffectB = true;\n"
|
|
" return false;\n"
|
|
"}\n"
|
|
"void main() {\n"
|
|
" bool b = (funcA(), (u_false == !sideEffectA) || funcB());\n"
|
|
" gl_FragColor = (b && sideEffectA && !sideEffectB) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
|
|
"}\n"
|
|
)));
|
|
}
|
|
}
|
|
|
|
} // Functional
|
|
} // gles2
|
|
} // deqp
|