blob: 1a3fb170cbea881d628189f3baa85b361b915403 [file] [log] [blame]
/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 3.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 "es3fShaderOperatorTests.hpp"
#include "glsShaderRenderCase.hpp"
#include "gluShaderUtil.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuVectorUtil.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
#include "deStringUtil.hpp"
#include "deInt32.h"
#include "deMemory.h"
#include <map>
#include <limits>
using namespace tcu;
using namespace glu;
using namespace deqp::gls;
using std::map;
using std::ostringstream;
using std::pair;
using std::string;
using std::vector;
namespace deqp
{
namespace gles3
{
namespace Functional
{
#if defined(abs)
#undef abs
#endif
using de::clamp;
using de::max;
using de::min;
// \note VS2013 gets confused without these
using tcu::acosh;
using tcu::asinh;
using tcu::atanh;
using tcu::exp2;
using tcu::log2;
using tcu::trunc;
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);
}
// \note stdlib.h defines div() that is not compatible with the macros.
template <typename T>
inline T div(T a, T b)
{
return a / b;
}
template <typename T>
inline T leftShift(T value, int amount)
{
return value << amount;
}
inline uint32_t rightShift(uint32_t value, int amount)
{
return value >> amount;
}
inline int rightShift(int value, int amount)
{
return (value >> amount) | (value >= 0 ? 0 : ~(~0U >> amount));
} // \note Arithmetic shift.
template <typename T, int Size>
Vector<T, Size> leftShift(const Vector<T, Size> &value, const Vector<int, Size> &amount)
{
Vector<T, Size> result;
for (int i = 0; i < Size; i++)
result[i] = leftShift(value[i], amount[i]);
return result;
}
template <typename T, int Size>
Vector<T, Size> rightShift(const Vector<T, Size> &value, const Vector<int, Size> &amount)
{
Vector<T, Size> result;
for (int i = 0; i < Size; i++)
result[i] = rightShift(value[i], amount[i]);
return result;
}
template <typename T, int Size>
Vector<T, Size> leftShiftVecScalar(const Vector<T, Size> &value, int amount)
{
return leftShift(value, Vector<int, Size>(amount));
}
template <typename T, int Size>
Vector<T, Size> rightShiftVecScalar(const Vector<T, Size> &value, int amount)
{
return rightShift(value, Vector<int, Size>(amount));
}
template <typename T, int Size>
inline Vector<T, Size> minVecScalar(const Vector<T, Size> &v, T s)
{
Vector<T, Size> res;
for (int i = 0; i < Size; i++)
res[i] = min(v[i], s);
return res;
}
template <typename T, int Size>
inline Vector<T, Size> maxVecScalar(const Vector<T, Size> &v, T s)
{
Vector<T, Size> res;
for (int i = 0; i < Size; i++)
res[i] = max(v[i], s);
return res;
}
template <typename T, int Size>
inline Vector<T, Size> clampVecScalarScalar(const Vector<T, Size> &v, T s0, T s1)
{
Vector<T, Size> res;
for (int i = 0; i < Size; i++)
res[i] = clamp(v[i], s0, s1);
return res;
}
template <typename T, int Size>
inline Vector<T, Size> mixVecVecScalar(const Vector<T, Size> &v0, const Vector<T, Size> &v1, T s)
{
Vector<T, Size> res;
for (int i = 0; i < Size; i++)
res[i] = mix(v0[i], v1[i], s);
return res;
}
template <typename T, int Size>
inline Vector<T, Size> stepScalarVec(T s, const Vector<T, Size> &v)
{
Vector<T, Size> res;
for (int i = 0; i < Size; i++)
res[i] = step(s, v[i]);
return res;
}
template <typename T, int Size>
inline Vector<T, Size> smoothStepScalarScalarVec(T s0, T s1, const Vector<T, Size> &v)
{
Vector<T, Size> res;
for (int i = 0; i < Size; i++)
res[i] = smoothStep(s0, s1, v[i]);
return res;
}
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;
}
inline uint32_t addOne(uint32_t v)
{
return v + 1;
}
inline uint32_t subOne(uint32_t 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 <int Size>
inline Vector<uint32_t, Size> addOne(const Vector<uint32_t, Size> &v)
{
return v + 1U;
}
template <int Size>
inline Vector<uint32_t, Size> subOne(const Vector<uint32_t, Size> &v)
{
return (v.asInt() - 1).asUint();
}
template <typename T>
inline T selection(bool cond, T a, T b)
{
return cond ? a : b;
}
// Vec-scalar and scalar-vec binary operators.
// \note This one is done separately due to how the overloaded minus operator is implemented for vector-scalar operands.
template <int Size>
inline Vector<uint32_t, Size> subVecScalar(const Vector<uint32_t, Size> &v, uint32_t s)
{
return (v.asInt() - (int)s).asUint();
}
template <typename T, int Size>
inline Vector<T, Size> addVecScalar(const Vector<T, Size> &v, T s)
{
return v + s;
}
// Specialize add, sub, and mul integer operations to use 64bit to avoid undefined signed integer overflows.
inline int add(int a, int b)
{
return static_cast<int>(static_cast<int64_t>(a) + static_cast<int64_t>(b));
}
inline int sub(int a, int b)
{
return static_cast<int>(static_cast<int64_t>(a) - static_cast<int64_t>(b));
}
inline int mul(int a, int b)
{
return static_cast<int>(static_cast<int64_t>(a) * static_cast<int64_t>(b));
}
inline uint32_t add(uint32_t a, uint32_t b)
{
return a + b;
}
inline uint32_t sub(uint32_t a, uint32_t b)
{
return a - b;
}
inline uint32_t mul(uint32_t a, uint32_t b)
{
return a * b;
}
#define DECLARE_IVEC_BINARY_FUNC(OP_NAME) \
template <int Size> \
inline Vector<int, Size> OP_NAME(const Vector<int, Size> &a, const Vector<int, Size> &b) \
{ \
Vector<int, Size> res; \
for (int i = 0; i < Size; i++) \
res.m_data[i] = OP_NAME(a.m_data[i], b.m_data[i]); \
return res; \
}
#define DECLARE_IVEC_INT_BINARY_FUNC(OP_NAME) \
template <int Size> \
inline Vector<int, Size> OP_NAME##VecScalar(const Vector<int, Size> &v, int s) \
{ \
Vector<int, Size> ret; \
for (int i = 0; i < Size; i++) \
ret[i] = OP_NAME(v.m_data[i], s); \
return ret; \
};
#define DECLARE_INT_IVEC_BINARY_FUNC(OP_NAME) \
template <int Size> \
inline Vector<int, Size> OP_NAME##ScalarVec(int s, const Vector<int, Size> &v) \
{ \
Vector<int, Size> ret; \
for (int i = 0; i < Size; i++) \
ret[i] = OP_NAME(s, v.m_data[i]); \
return ret; \
};
DECLARE_IVEC_BINARY_FUNC(add)
DECLARE_IVEC_BINARY_FUNC(sub)
DECLARE_IVEC_BINARY_FUNC(mul)
DECLARE_IVEC_INT_BINARY_FUNC(add)
DECLARE_IVEC_INT_BINARY_FUNC(sub)
DECLARE_IVEC_INT_BINARY_FUNC(mul)
DECLARE_INT_IVEC_BINARY_FUNC(add)
DECLARE_INT_IVEC_BINARY_FUNC(sub)
DECLARE_INT_IVEC_BINARY_FUNC(mul)
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> modVecScalar(const Vector<T, Size> &v, T s)
{
return mod(v, Vector<T, Size>(s));
}
template <typename T, int Size>
inline Vector<T, Size> bitwiseAndVecScalar(const Vector<T, Size> &v, T s)
{
return bitwiseAnd(v, Vector<T, Size>(s));
}
template <typename T, int Size>
inline Vector<T, Size> bitwiseOrVecScalar(const Vector<T, Size> &v, T s)
{
return bitwiseOr(v, Vector<T, Size>(s));
}
template <typename T, int Size>
inline Vector<T, Size> bitwiseXorVecScalar(const Vector<T, Size> &v, T s)
{
return bitwiseXor(v, Vector<T, Size>(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;
}
template <typename T, int Size>
inline Vector<T, Size> modScalarVec(T s, const Vector<T, Size> &v)
{
return mod(Vector<T, Size>(s), v);
}
template <typename T, int Size>
inline Vector<T, Size> bitwiseAndScalarVec(T s, const Vector<T, Size> &v)
{
return bitwiseAnd(Vector<T, Size>(s), v);
}
template <typename T, int Size>
inline Vector<T, Size> bitwiseOrScalarVec(T s, const Vector<T, Size> &v)
{
return bitwiseOr(Vector<T, Size>(s), v);
}
template <typename T, int Size>
inline Vector<T, Size> bitwiseXorScalarVec(T s, const Vector<T, Size> &v)
{
return bitwiseXor(Vector<T, Size>(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 uint32_t sequenceNoSideEffCase1(float in0, uint32_t 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 = uint(in0 + in2)"
inline uint32_t sequenceSideEffCase1(float in0, uint32_t in1, float in2)
{
DE_UNREF(in0);
return (uint32_t)(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(), (uint32_t)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(), (uint32_t)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();
}
static string stringJoin(const vector<string> &elems, const string &delim)
{
string result;
for (int i = 0; i < (int)elems.size(); i++)
result += (i > 0 ? delim : "") + elems[i];
return result;
}
static void stringReplace(string &str, const string &from, const string &to)
{
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
{
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
static string twoValuedVec4(const string &first, const string &second, const BVec4 &firstMask)
{
vector<string> elems(4);
for (int i = 0; i < 4; i++)
elems[i] = firstMask[i] ? first : second;
return "vec4(" + stringJoin(elems, ", ") + ")";
}
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_LOWP_MEDIUMP = PRECMASK_LOWP | PRECMASK_MEDIUMP,
PRECMASK_MEDIUMP_HIGHP = PRECMASK_MEDIUMP | PRECMASK_HIGHP,
PRECMASK_ALL = PRECMASK_LOWP | PRECMASK_MEDIUMP | PRECMASK_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
VALUE_UINT = (1 << 11), // uint scalar
VALUE_UINT_VEC = (1 << 12), // uint vector
VALUE_UINT_GENTYPE = (1 << 13), // uint 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,
U = VALUE_UINT,
UV = VALUE_UINT_VEC,
UGT = VALUE_UINT_GENTYPE
};
static inline bool isScalarType(ValueType type)
{
return type == VALUE_FLOAT || type == VALUE_BOOL || type == VALUE_INT || type == VALUE_UINT;
}
static inline bool isFloatType(ValueType type)
{
return (type & (VALUE_FLOAT | VALUE_FLOAT_VEC | VALUE_FLOAT_GENTYPE)) != 0;
}
static inline bool isIntType(ValueType type)
{
return (type & (VALUE_INT | VALUE_INT_VEC | VALUE_INT_GENTYPE)) != 0;
}
static inline bool isUintType(ValueType type)
{
return (type & (VALUE_UINT | VALUE_UINT_VEC | VALUE_UINT_GENTYPE)) != 0;
}
static inline bool isBoolType(ValueType type)
{
return (type & (VALUE_BOOL | VALUE_BOOL_VEC | VALUE_BOOL_GENTYPE)) != 0;
}
static inline int getGLSLUintBits(const glw::Functions &gl, ShaderType shaderType, Precision uintPrecision)
{
uint32_t intPrecisionGL;
uint32_t shaderTypeGL;
switch (uintPrecision)
{
case PRECISION_LOWP:
intPrecisionGL = GL_LOW_INT;
break;
case PRECISION_MEDIUMP:
intPrecisionGL = GL_MEDIUM_INT;
break;
case PRECISION_HIGHP:
intPrecisionGL = GL_HIGH_INT;
break;
default:
DE_ASSERT(false);
intPrecisionGL = 0;
}
switch (shaderType)
{
case SHADERTYPE_VERTEX:
shaderTypeGL = GL_VERTEX_SHADER;
break;
case SHADERTYPE_FRAGMENT:
shaderTypeGL = GL_FRAGMENT_SHADER;
break;
default:
DE_ASSERT(false);
shaderTypeGL = 0;
}
glw::GLint range[2] = {-1, -1};
glw::GLint precision = -1;
gl.getShaderPrecisionFormat(shaderTypeGL, intPrecisionGL, &range[0], &precision);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderPrecisionFormat failed");
TCU_CHECK(de::inBounds(range[0], 8, 32));
const int numBitsInType = range[0] + 1;
return numBitsInType;
}
static inline float getGLSLUintMaxAsFloat(const glw::Functions &gl, ShaderType shaderType, Precision uintPrecision)
{
const int numBitsInType = getGLSLUintBits(gl, shaderType, uintPrecision);
const float maxAsFloat = static_cast<float>((1ull << numBitsInType) - 1);
const float maxRepresentableAsFloat = floorf(nextafterf(maxAsFloat, 0));
// Not accurate for integers wider than 24 bits.
return numBitsInType > 24 ? maxRepresentableAsFloat : maxAsFloat;
}
// Float scalar that can be either constant or a symbol that can be evaluated later.
class FloatScalar
{
public:
enum Symbol
{
SYMBOL_LOWP_UINT_MAX = 0,
SYMBOL_MEDIUMP_UINT_MAX,
SYMBOL_LOWP_UINT_MAX_RECIPROCAL,
SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL,
SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX,
SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX,
SYMBOL_LAST
};
FloatScalar(float c) : m_isConstant(true), m_value(c)
{
}
FloatScalar(Symbol s) : m_isConstant(false), m_value(s)
{
}
float getValue(const glw::Functions &gl, ShaderType shaderType) const
{
if (m_isConstant)
return m_value.constant;
else
{
switch (m_value.symbol)
{
case SYMBOL_LOWP_UINT_MAX:
return getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_LOWP);
case SYMBOL_MEDIUMP_UINT_MAX:
return getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_MEDIUMP);
case SYMBOL_LOWP_UINT_MAX_RECIPROCAL:
return 1.0f / getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_LOWP);
case SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL:
return 1.0f / getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_MEDIUMP);
case SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX:
return 1.0f - (float)std::numeric_limits<uint32_t>::max() /
getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_LOWP);
case SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX:
return 1.0f - (float)std::numeric_limits<uint32_t>::max() /
getGLSLUintMaxAsFloat(gl, shaderType, PRECISION_MEDIUMP);
default:
DE_ASSERT(false);
return 0.0f;
}
}
}
uint32_t getValueMask(const glw::Functions &gl, ShaderType shaderType) const
{
if (m_isConstant)
return 0;
int bits = 0;
switch (m_value.symbol)
{
case SYMBOL_LOWP_UINT_MAX_RECIPROCAL:
case SYMBOL_LOWP_UINT_MAX:
bits = getGLSLUintBits(gl, shaderType, PRECISION_LOWP);
break;
case SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL:
case SYMBOL_MEDIUMP_UINT_MAX:
bits = getGLSLUintBits(gl, shaderType, PRECISION_MEDIUMP);
break;
case SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX:
case SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX:
return 0;
default:
DE_ASSERT(false);
return 0;
}
return bits == 32 ? 0 : (1u << bits) - 1;
}
private:
bool m_isConstant;
union ConstantOrSymbol
{
float constant;
Symbol symbol;
ConstantOrSymbol(float c) : constant(c)
{
}
ConstantOrSymbol(Symbol s) : symbol(s)
{
}
} m_value;
};
struct Value
{
Value(ValueType valueType_, const FloatScalar &rangeMin_, const FloatScalar &rangeMax_)
: valueType(valueType_)
, rangeMin(rangeMin_)
, rangeMax(rangeMax_)
{
}
ValueType valueType;
FloatScalar rangeMin;
FloatScalar 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_, const FloatScalar &resultScale_, const FloatScalar &resultBias_,
uint32_t 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_)
, referenceScale(resultScale_)
, referenceBias(resultBias_)
, precisionMask(precisionMask_)
, evalFuncScalar(evalFuncScalar_)
, evalFuncVec2(evalFuncVec2_)
, evalFuncVec3(evalFuncVec3_)
, evalFuncVec4(evalFuncVec4_)
, type(type_)
, isUnaryPrefix(isUnaryPrefix_)
{
}
BuiltinFuncInfo(const char *caseName_, const char *shaderFuncName_, ValueType outValue_, Value input0_,
Value input1_, Value input2_, const FloatScalar &resultScale_, const FloatScalar &resultBias_,
const FloatScalar &referenceScale_, const FloatScalar &referenceBias_, uint32_t 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_)
, referenceScale(referenceScale_)
, referenceBias(referenceBias_)
, 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;
FloatScalar resultScale;
FloatScalar resultBias;
FloatScalar referenceScale;
FloatScalar referenceBias;
uint32_t 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_,
const FloatScalar &resultScale_, const FloatScalar &resultBias_,
uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_,
ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
ShaderEvalFunc evalFuncVec4_)
{
return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
resultScale_, resultBias_, precisionMask_, evalFuncScalar_, evalFuncVec2_, evalFuncVec3_,
evalFuncVec4_, OPERATOR);
}
static inline BuiltinFuncInfo BuiltinOperInfoSeparateRefScaleBias(
const char *caseName_, const char *shaderFuncName_, ValueType outValue_, Value input0_, Value input1_,
Value input2_, const FloatScalar &resultScale_, const FloatScalar &resultBias_, uint32_t precisionMask_,
ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
ShaderEvalFunc evalFuncVec4_, const FloatScalar &referenceScale_, const FloatScalar &referenceBias_)
{
return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
referenceScale_, referenceBias_, 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_,
const FloatScalar &resultScale_, const FloatScalar &resultBias_,
uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_,
ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
ShaderEvalFunc evalFuncVec4_)
{
return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
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_,
const FloatScalar &resultScale_, const FloatScalar &resultBias_,
uint32_t precisionMask_, ShaderEvalFunc evalFuncScalar_,
ShaderEvalFunc evalFuncVec2_, ShaderEvalFunc evalFuncVec3_,
ShaderEvalFunc evalFuncVec4_)
{
return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
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_, const FloatScalar &resultScale_,
const FloatScalar &resultBias_, uint32_t precisionMask_,
ShaderEvalFunc evalFuncScalar_, ShaderEvalFunc evalFuncVec2_,
ShaderEvalFunc evalFuncVec3_, ShaderEvalFunc evalFuncVec4_)
{
return BuiltinFuncInfo(caseName_, shaderFuncName_, outValue_, input0_, input1_, input2_, resultScale_, resultBias_,
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"};
static const BVec4 s_outSwizzleChannelMasks[] = {BVec4(true, false, false, false), BVec4(false, true, true, false),
BVec4(true, true, true, false), BVec4(true, true, true, true)};
// OperatorShaderEvaluator
class OperatorShaderEvaluator : public ShaderEvaluator
{
public:
OperatorShaderEvaluator(const glw::Functions &gl, ShaderType shaderType, ShaderEvalFunc evalFunc,
const FloatScalar &scale, const FloatScalar &bias, int resultScalarSize)
: m_gl(gl)
, m_shaderType(shaderType)
, m_evalFunc(evalFunc)
, m_scale(scale)
, m_bias(bias)
, m_resultScalarSize(resultScalarSize)
, m_areScaleAndBiasEvaluated(false)
, m_evaluatedScale(-1.0f)
, m_evaluatedBias(-1.0f)
{
DE_ASSERT(de::inRange(resultScalarSize, 1, 4));
}
virtual ~OperatorShaderEvaluator(void)
{
}
virtual void evaluate(ShaderEvalContext &ctx)
{
m_evalFunc(ctx);
if (!m_areScaleAndBiasEvaluated)
{
m_evaluatedScale = m_scale.getValue(m_gl, m_shaderType);
m_evaluatedBias = m_bias.getValue(m_gl, m_shaderType);
m_areScaleAndBiasEvaluated = true;
}
for (int i = 0; i < 4; i++)
if (s_outSwizzleChannelMasks[m_resultScalarSize - 1][i])
ctx.color[i] = ctx.color[i] * m_evaluatedScale + m_evaluatedBias;
}
private:
const glw::Functions &m_gl;
ShaderType m_shaderType;
ShaderEvalFunc m_evalFunc;
FloatScalar m_scale;
FloatScalar m_bias;
int m_resultScalarSize;
bool m_areScaleAndBiasEvaluated;
float m_evaluatedScale;
float m_evaluatedBias;
};
// Concrete value.
struct ShaderValue
{
ShaderValue(DataType type_, const FloatScalar &rangeMin_, const FloatScalar &rangeMax_)
: type(type_)
, rangeMin(rangeMin_)
, rangeMax(rangeMax_)
{
}
ShaderValue(void) : type(TYPE_LAST), rangeMin(0.0f), rangeMax(0.0f)
{
}
DataType type;
FloatScalar rangeMin;
FloatScalar rangeMax;
};
struct ShaderDataSpec
{
ShaderDataSpec(void)
: resultScale(1.0f)
, resultBias(0.0f)
, referenceScale(1.0f)
, referenceBias(0.0f)
, precision(PRECISION_LAST)
, output(TYPE_LAST)
, numInputs(0)
{
}
FloatScalar resultScale;
FloatScalar resultBias;
FloatScalar referenceScale;
FloatScalar referenceBias;
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 string &shaderOp, const ShaderDataSpec &spec);
virtual ~ShaderOperatorCase(void);
protected:
void setupShaderData(void);
private:
ShaderOperatorCase(const ShaderOperatorCase &); // not allowed!
ShaderOperatorCase &operator=(const ShaderOperatorCase &); // not allowed!
ShaderDataSpec m_spec;
string m_shaderOp;
OperatorShaderEvaluator m_evaluator;
};
ShaderOperatorCase::ShaderOperatorCase(Context &context, const char *caseName, const char *description,
bool isVertexCase, ShaderEvalFunc evalFunc, const string &shaderOp,
const ShaderDataSpec &spec)
: ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), caseName,
description, isVertexCase, m_evaluator)
, m_spec(spec)
, m_shaderOp(shaderOp)
, m_evaluator(m_renderCtx.getFunctions(), isVertexCase ? SHADERTYPE_VERTEX : SHADERTYPE_FRAGMENT, evalFunc,
spec.referenceScale, spec.referenceBias, getDataTypeScalarSize(spec.output))
{
}
void ShaderOperatorCase::setupShaderData(void)
{
ShaderType shaderType = m_isVertexCase ? SHADERTYPE_VERTEX : SHADERTYPE_FRAGMENT;
const char *precision = m_spec.precision != PRECISION_LAST ? getPrecisionName(m_spec.precision) : DE_NULL;
const char *inputPrecision[MAX_INPUTS];
ostringstream vtx;
ostringstream frag;
ostringstream &op = m_isVertexCase ? vtx : frag;
vtx << "#version 300 es\n";
frag << "#version 300 es\n";
// Compute precision for inputs.
for (int i = 0; i < m_spec.numInputs; i++)
{
bool isBoolVal = de::inRange<int>(m_spec.inputs[i].type, TYPE_BOOL, TYPE_BOOL_VEC4);
bool isIntVal = de::inRange<int>(m_spec.inputs[i].type, TYPE_INT, TYPE_INT_VEC4);
bool isUintVal = de::inRange<int>(m_spec.inputs[i].type, TYPE_UINT, TYPE_UINT_VEC4);
// \note Mediump interpolators are used for booleans, and highp for integers.
Precision prec = isBoolVal ? PRECISION_MEDIUMP : isIntVal || isUintVal ? PRECISION_HIGHP : m_spec.precision;
inputPrecision[i] = getPrecisionName(prec);
}
// Attributes.
vtx << "in highp vec4 a_position;\n";
for (int i = 0; i < m_spec.numInputs; i++)
vtx << "in " << inputPrecision[i] << " vec4 a_in" << i << ";\n";
// Color output.
frag << "layout(location = 0) out mediump vec4 o_color;\n";
if (m_isVertexCase)
{
vtx << "out mediump vec4 v_color;\n";
frag << "in mediump vec4 v_color;\n";
}
else
{
for (int i = 0; i < m_spec.numInputs; i++)
{
vtx << "out " << inputPrecision[i] << " vec4 v_in" << i << ";\n";
frag << "in " << 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";
bool isResFloatVec = de::inRange<int>(m_spec.output, TYPE_FLOAT, TYPE_FLOAT_VEC4);
bool isResBoolVec = de::inRange<int>(m_spec.output, TYPE_BOOL, TYPE_BOOL_VEC4);
bool hasReference = !isResFloatVec && !isResBoolVec &&
(m_spec.precision == PRECISION_LOWP || m_spec.precision == PRECISION_MEDIUMP);
string refShaderOp = m_shaderOp;
// Expression inputs.
string prefix = m_isVertexCase ? "a_" : "v_";
for (int i = 0; i < m_spec.numInputs; i++)
{
DataType inType = m_spec.inputs[i].type;
int inSize = getDataTypeScalarSize(inType);
bool isBool = de::inRange<int>(inType, TYPE_BOOL, TYPE_BOOL_VEC4);
bool isInt = de::inRange<int>(inType, TYPE_INT, TYPE_INT_VEC4);
bool isUint = de::inRange<int>(inType, TYPE_UINT, TYPE_UINT_VEC4);
const char *typeName = getDataTypeName(inType);
const char *swizzle = s_inSwizzles[i][inSize - 1];
bool hasReferenceIn = hasReference && !isBool;
// For int/uint types, generate:
//
// highp type highp_inN = ...;
// precision type inN = highp_inN;
//
// inN_high will be used later for reference checking.
//
// For other types, generate:
//
// precision type inN = ...;
//
op << "\t";
if (precision && !isBool)
{
if (hasReferenceIn)
op << "highp ";
else
op << precision << " ";
}
op << typeName << " ";
if (hasReferenceIn)
op << "highp_";
op << "in" << i << " = ";
if (isBool)
{
if (inSize == 1)
op << "(";
else
op << "greaterThan(";
}
else if (isInt || isUint)
op << typeName << "(";
op << prefix << "in" << i << "." << swizzle;
if (isBool)
{
if (inSize == 1)
op << " > 0.0)";
else
op << ", vec" << inSize << "(0.0))";
}
else if (isInt || isUint)
op << ")";
op << ";\n";
if (hasReferenceIn)
{
op << "\t" << precision << " " << typeName << " in" << i << " = highp_in" << i << ";\n";
string inputName = "in" + string(1, static_cast<char>('0' + i));
stringReplace(refShaderOp, inputName, "highp_" + inputName);
}
}
// Result variable.
{
const char *outTypeName = getDataTypeName(m_spec.output);
bool isBoolOut = de::inRange<int>(m_spec.output, TYPE_BOOL, TYPE_BOOL_VEC4);
op << "\t";
if (precision && !isBoolOut)
op << precision << " ";
op << outTypeName << " res = " << outTypeName << "(0.0);\n";
if (hasReference)
{
op << "\thighp " << outTypeName << " ref = " << outTypeName << "(0.0);\n";
}
op << "\n";
}
// Expression.
op << "\t" << m_shaderOp << "\n";
if (hasReference)
{
stringReplace(refShaderOp, "res", "ref");
op << "\t" << refShaderOp << "\n";
}
op << "\n";
// Implementations may use more bits than advertised. Assume an implementation advertising 16
// bits for mediump, but actually using 24 bits for a particular operation. We have:
//
// highp ref = expr;
// mediump res = expr;
//
// We expect res&0xFFFF to be correct, because that ensures that _at least_ 16 bits were
// provided. However, we also need to make sure that if there is anything in the upper 16 bits
// of res, that those bits match with ref. In short, we expect to see the following bits
// (assume the advertised number of bits is N, and the actual calculation is done in M bits):
//
// ref = a31 ... aM aM-1 ... aN aN-1 ... a0
// res = 0 ... 0 bM-1 ... bN bN-1 ... b0
//
// The test verifies that bN-1 ... b0 is correct based on the shader output. We additionally
// want to make sure that:
//
// - bM-1 ... bN is identical to aM-1 ... aN
// - bits above bM-1 are zero.
//
// This is done as follows:
//
// diff = res ^ ref --> should produce a31 ... aM 0 ... 0
// diff == 0: accept res
// diff != 0:
// lsb = log2((~diff + 1u) & diff) --> log2(0 .. 0 1 0 ...0)
// == findLSB(diff)
//
// outOfRangeMask = 0xFFFFFFFF << lsb --> 1 ... 1 0 ... 0
//
// (res & outOfRangeMask) == 0: accept res
//
// Note that (diff & ~outOfRangeMask) == 0 necessarily holds, because outOfRangeMask has 1s
// starting from the first bit that differs between res and ref, which means that res and ref
// are identical in those bits.
int outScalarSize = getDataTypeScalarSize(m_spec.output);
string floatType = "";
if (!isResFloatVec)
{
if (outScalarSize == 1)
floatType = "float";
else
floatType = "vec" + string(1, static_cast<char>('0' + outScalarSize));
}
if (hasReference)
{
bool isInt = de::inRange<int>(m_spec.output, TYPE_INT, TYPE_INT_VEC4);
const char *outTypeName = getDataTypeName(m_spec.output);
const char *outBasicTypeName = getDataTypeName(isInt ? TYPE_INT : TYPE_UINT);
uint32_t resultMask = m_spec.resultScale.getValueMask(m_renderCtx.getFunctions(), shaderType);
op << "\thighp " << outTypeName << " diff = res ^ ref;\n";
op << "\tdiff = (~diff + " << outTypeName << "(1)) & diff;\n";
op << "\thighp " << outTypeName << " lsb = " << outTypeName << "(32);\n";
op << "\thighp " << outTypeName << " outOfRangeMask = " << outTypeName << "(0);\n";
if (outScalarSize == 1)
{
op << "\tif (diff != " << outTypeName << "(0))\n\t{\n";
op << "\t\tlsb = " << outTypeName << "(log2(" << floatType << "(diff)));\n";
op << "\t\toutOfRangeMask = " << outTypeName << "(0xFFFFFFFF) << lsb;\n";
op << "\t}\n";
}
else
{
op << "\tbvec" << outScalarSize << " isDiffZero = equal(diff, " << outTypeName << "(0));\n";
op << "\thighp " << outTypeName << " lsbUnsantized = " << outTypeName << "(log2(vec" << outScalarSize
<< "((~diff + " << outTypeName << "(1)) & diff)));\n";
for (int channel = 0; channel < outScalarSize; ++channel)
{
op << "\tif (!isDiffZero[" << channel << "])\n\t{\n";
op << "\t\tlsb[" << channel << "] = lsbUnsantized[" << channel << "];\n";
op << "\t\toutOfRangeMask[" << channel << "] = " << outBasicTypeName << "(0xFFFFFFFF) << lsb["
<< channel << "];\n";
op << "\t}\n";
}
}
op << "\thighp " << outTypeName << " outOfRangeRes = res & outOfRangeMask;\n";
op << "\tif (outOfRangeRes != " << outTypeName << "(0)) res = " << outTypeName << "(0);\n";
if (resultMask != 0)
op << "\tres &= " << outTypeName << "(" << resultMask << ");\n";
op << "\n";
}
// Convert to color.
op << "\thighp vec4 color = vec4(0.0, 0.0, 0.0, 1.0);\n";
op << "\tcolor." << s_outSwizzles[outScalarSize - 1] << " = " << floatType << "(res);\n";
// Scale & bias.
float resultScale = m_spec.resultScale.getValue(m_renderCtx.getFunctions(), shaderType);
float resultBias = m_spec.resultBias.getValue(m_renderCtx.getFunctions(), shaderType);
if ((resultScale != 1.0f) || (resultBias != 0.0f))
{
op << "\tcolor = color";
if (resultScale != 1.0f)
op << " * " << twoValuedVec4(de::toString(resultScale), "1.0", s_outSwizzleChannelMasks[outScalarSize - 1]);
if (resultBias != 0.0f)
op << " + "
<< twoValuedVec4(de::floatToString(resultBias, 2), "0.0", s_outSwizzleChannelMasks[outScalarSize - 1]);
op << ";\n";
}
// ..
if (m_isVertexCase)
{
vtx << " v_color = color;\n";
frag << " o_color = v_color;\n";
}
else
{
for (int i = 0; i < m_spec.numInputs; i++)
vtx << " v_in" << i << " = a_in" << i << ";\n";
frag << " o_color = color;\n";
}
vtx << "}\n";
frag << "}\n";
m_vertShaderSource = vtx.str();
m_fragShaderSource = frag.str();
// Setup the user attributes.
m_userAttribTransforms.resize(m_spec.numInputs);
for (int inputNdx = 0; inputNdx < m_spec.numInputs; inputNdx++)
{
const ShaderValue &v = m_spec.inputs[inputNdx];
DE_ASSERT(v.type != TYPE_LAST);
float rangeMin = v.rangeMin.getValue(m_renderCtx.getFunctions(), shaderType);
float rangeMax = v.rangeMax.getValue(m_renderCtx.getFunctions(), shaderType);
float scale = rangeMax - rangeMin;
float minBias = rangeMin;
float maxBias = 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)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_UNARY_UINT_GENTYPE_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uint(ShaderEvalContext &c) \
{ \
c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z()); \
} \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint()).asFloat(); \
}
#define DECLARE_BINARY_UINT_GENTYPE_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uint(ShaderEvalContext &c) \
{ \
c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x()); \
} \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()).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_TERNARY_UINT_GENTYPE_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uint(ShaderEvalContext &c) \
{ \
c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()); \
} \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = \
FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint(), c.in[2].swizzle(2, 1).asUint()) \
.asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint(), \
c.in[2].swizzle(3, 1, 2).asUint()) \
.asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint(), \
c.in[2].swizzle(0, 3, 2, 1).asUint()) \
.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_IVEC_INT_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(), (int)c.in[2].y()).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(), (int)c.in[2].y()).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(), (int)c.in[2].y()).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(); \
}
#define DECLARE_UVEC_UINT_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), (uint32_t)c.in[1].x()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), (uint32_t)c.in[1].x()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), (uint32_t)c.in[1].x()).asFloat(); \
}
#define DECLARE_UVEC_UINT_UINT_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = \
FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = \
FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = \
FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y()).asFloat(); \
}
#define DECLARE_UINT_UVEC_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = FUNC_NAME((uint32_t)c.in[0].z(), c.in[1].swizzle(1, 0).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = FUNC_NAME((uint32_t)c.in[0].z(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = FUNC_NAME((uint32_t)c.in[0].z(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat(); \
}
#define DECLARE_BINARY_INT_VEC_FUNCS(FUNC_NAME) \
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_BINARY_UINT_VEC_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()).asFloat(); \
}
#define DECLARE_UINT_INT_GENTYPE_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uint(ShaderEvalContext &c) \
{ \
c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (int)c.in[1].x()); \
} \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asInt()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asInt()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asInt()).asFloat(); \
}
#define DECLARE_UVEC_INT_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), (int)c.in[1].x()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), (int)c.in[1].x()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), (int)c.in[1].x()).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_UNARY_INT_GENTYPE_FUNCS(bitwiseNot)
DECLARE_BINARY_INT_GENTYPE_FUNCS(add)
DECLARE_BINARY_INT_GENTYPE_FUNCS(sub)
DECLARE_BINARY_INT_GENTYPE_FUNCS(mul)
DECLARE_BINARY_INT_GENTYPE_FUNCS(div)
DECLARE_BINARY_INT_GENTYPE_FUNCS(mod)
DECLARE_BINARY_INT_GENTYPE_FUNCS(bitwiseAnd)
DECLARE_BINARY_INT_GENTYPE_FUNCS(bitwiseOr)
DECLARE_BINARY_INT_GENTYPE_FUNCS(bitwiseXor)
void eval_leftShift_int(ShaderEvalContext &c)
{
c.color.x() = (float)leftShift((int)c.in[0].z(), (int)c.in[1].x());
}
DECLARE_BINARY_INT_VEC_FUNCS(leftShift)
void eval_rightShift_int(ShaderEvalContext &c)
{
c.color.x() = (float)rightShift((int)c.in[0].z(), (int)c.in[1].x());
}
DECLARE_BINARY_INT_VEC_FUNCS(rightShift)
DECLARE_IVEC_INT_FUNCS(leftShiftVecScalar)
DECLARE_IVEC_INT_FUNCS(rightShiftVecScalar)
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_UINT_GENTYPE_FUNCS(nop)
DECLARE_UNARY_UINT_GENTYPE_FUNCS(negate)
DECLARE_UNARY_UINT_GENTYPE_FUNCS(bitwiseNot)
DECLARE_UNARY_UINT_GENTYPE_FUNCS(addOne)
DECLARE_UNARY_UINT_GENTYPE_FUNCS(subOne)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(add)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(sub)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(mul)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(div)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(mod)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(bitwiseAnd)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(bitwiseOr)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(bitwiseXor)
DECLARE_UINT_INT_GENTYPE_FUNCS(leftShift)
DECLARE_UINT_INT_GENTYPE_FUNCS(rightShift)
DECLARE_UVEC_INT_FUNCS(leftShiftVecScalar)
DECLARE_UVEC_INT_FUNCS(rightShiftVecScalar)
void eval_selection_uint(ShaderEvalContext &c)
{
c.color.x() = (float)selection(c.in[0].z() > 0.0f, (uint32_t)c.in[1].x(), (uint32_t)c.in[2].y());
}
void eval_selection_uvec2(ShaderEvalContext &c)
{
c.color.yz() =
selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 0).asUint(), c.in[2].swizzle(2, 1).asUint()).asFloat();
}
void eval_selection_uvec3(ShaderEvalContext &c)
{
c.color.xyz() =
selection(c.in[0].z() > 0.0f, c.in[1].swizzle(1, 2, 0).asUint(), c.in[2].swizzle(3, 1, 2).asUint()).asFloat();
}
void eval_selection_uvec4(ShaderEvalContext &c)
{
c.color = selection(c.in[0].z() > 0.0f, c.in[1].swizzle(3, 2, 1, 0).asUint(), c.in[2].swizzle(0, 3, 2, 1).asUint())
.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_IVEC_INT_FUNCS(modVecScalar)
DECLARE_IVEC_INT_FUNCS(bitwiseAndVecScalar)
DECLARE_IVEC_INT_FUNCS(bitwiseOrVecScalar)
DECLARE_IVEC_INT_FUNCS(bitwiseXorVecScalar)
DECLARE_INT_IVEC_FUNCS(addScalarVec)
DECLARE_INT_IVEC_FUNCS(subScalarVec)
DECLARE_INT_IVEC_FUNCS(mulScalarVec)
DECLARE_INT_IVEC_FUNCS(divScalarVec)
DECLARE_INT_IVEC_FUNCS(modScalarVec)
DECLARE_INT_IVEC_FUNCS(bitwiseAndScalarVec)
DECLARE_INT_IVEC_FUNCS(bitwiseOrScalarVec)
DECLARE_INT_IVEC_FUNCS(bitwiseXorScalarVec)
DECLARE_UVEC_UINT_FUNCS(addVecScalar)
DECLARE_UVEC_UINT_FUNCS(subVecScalar)
DECLARE_UVEC_UINT_FUNCS(mulVecScalar)
DECLARE_UVEC_UINT_FUNCS(divVecScalar)
DECLARE_UVEC_UINT_FUNCS(modVecScalar)
DECLARE_UVEC_UINT_FUNCS(bitwiseAndVecScalar)
DECLARE_UVEC_UINT_FUNCS(bitwiseOrVecScalar)
DECLARE_UVEC_UINT_FUNCS(bitwiseXorVecScalar)
DECLARE_UINT_UVEC_FUNCS(addScalarVec)
DECLARE_UINT_UVEC_FUNCS(subScalarVec)
DECLARE_UINT_UVEC_FUNCS(mulScalarVec)
DECLARE_UINT_UVEC_FUNCS(divScalarVec)
DECLARE_UINT_UVEC_FUNCS(modScalarVec)
DECLARE_UINT_UVEC_FUNCS(bitwiseAndScalarVec)
DECLARE_UINT_UVEC_FUNCS(bitwiseOrScalarVec)
DECLARE_UINT_UVEC_FUNCS(bitwiseXorScalarVec)
// 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_UNARY_GENTYPE_FUNCS(sinh)
DECLARE_UNARY_GENTYPE_FUNCS(cosh)
DECLARE_UNARY_GENTYPE_FUNCS(tanh)
DECLARE_UNARY_GENTYPE_FUNCS(asinh)
DECLARE_UNARY_GENTYPE_FUNCS(acosh)
DECLARE_UNARY_GENTYPE_FUNCS(atanh)
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(trunc)
DECLARE_UNARY_GENTYPE_FUNCS(roundToEven)
DECLARE_UNARY_GENTYPE_FUNCS(ceil)
DECLARE_UNARY_GENTYPE_FUNCS(fract)
DECLARE_BINARY_GENTYPE_FUNCS(mod)
DECLARE_VEC_FLOAT_FUNCS(modVecScalar)
DECLARE_BINARY_GENTYPE_FUNCS(min)
DECLARE_VEC_FLOAT_FUNCS(minVecScalar)
DECLARE_BINARY_INT_GENTYPE_FUNCS(min)
DECLARE_IVEC_INT_FUNCS(minVecScalar)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(min)
DECLARE_UVEC_UINT_FUNCS(minVecScalar)
DECLARE_BINARY_GENTYPE_FUNCS(max)
DECLARE_VEC_FLOAT_FUNCS(maxVecScalar)
DECLARE_BINARY_INT_GENTYPE_FUNCS(max)
DECLARE_IVEC_INT_FUNCS(maxVecScalar)
DECLARE_BINARY_UINT_GENTYPE_FUNCS(max)
DECLARE_UVEC_UINT_FUNCS(maxVecScalar)
DECLARE_TERNARY_GENTYPE_FUNCS(clamp)
DECLARE_VEC_FLOAT_FLOAT_FUNCS(clampVecScalarScalar)
DECLARE_TERNARY_INT_GENTYPE_FUNCS(clamp)
DECLARE_IVEC_INT_INT_FUNCS(clampVecScalarScalar)
DECLARE_TERNARY_UINT_GENTYPE_FUNCS(clamp)
DECLARE_UVEC_UINT_UINT_FUNCS(clampVecScalarScalar)
DECLARE_TERNARY_GENTYPE_FUNCS(mix)
DECLARE_VEC_VEC_FLOAT_FUNCS(mixVecVecScalar)
DECLARE_BINARY_GENTYPE_FUNCS(step)
DECLARE_FLOAT_VEC_FUNCS(stepScalarVec)
DECLARE_TERNARY_GENTYPE_FUNCS(smoothStep)
DECLARE_FLOAT_FLOAT_VEC_FUNCS(smoothStepScalarScalarVec)
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_UINT_COMPARE_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uint(ShaderEvalContext &c) \
{ \
c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x()); \
} \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color.x() = (float)FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()); \
}
#define DECLARE_UINT_CWISE_COMPARE_FUNCS(FUNC_NAME) \
void eval_##FUNC_NAME##_uint(ShaderEvalContext &c) \
{ \
c.color.x() = (float)FUNC_NAME((uint32_t)c.in[0].z(), (uint32_t)c.in[1].x()); \
} \
void eval_##FUNC_NAME##_uvec2(ShaderEvalContext &c) \
{ \
c.color.yz() = FUNC_NAME(c.in[0].swizzle(3, 1).asUint(), c.in[1].swizzle(1, 0).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec3(ShaderEvalContext &c) \
{ \
c.color.xyz() = FUNC_NAME(c.in[0].swizzle(2, 0, 1).asUint(), c.in[1].swizzle(1, 2, 0).asUint()).asFloat(); \
} \
void eval_##FUNC_NAME##_uvec4(ShaderEvalContext &c) \
{ \
c.color = FUNC_NAME(c.in[0].swizzle(1, 2, 3, 0).asUint(), c.in[1].swizzle(3, 2, 1, 0).asUint()).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_UINT_COMPARE_FUNCS(allEqual)
DECLARE_UINT_COMPARE_FUNCS(anyNotEqual)
DECLARE_UINT_CWISE_COMPARE_FUNCS(lessThan)
DECLARE_UINT_CWISE_COMPARE_FUNCS(lessThanEqual)
DECLARE_UINT_CWISE_COMPARE_FUNCS(greaterThan)
DECLARE_UINT_CWISE_COMPARE_FUNCS(greaterThanEqual)
DECLARE_UINT_CWISE_COMPARE_FUNCS(equal)
DECLARE_UINT_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)
{
#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 UINT_VEC_FUNCS(FUNC_NAME) DE_NULL, eval_##FUNC_NAME##_uvec2, eval_##FUNC_NAME##_uvec3, eval_##FUNC_NAME##_uvec4
#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 UINT_GENTYPE_FUNCS(FUNC_NAME) \
eval_##FUNC_NAME##_uint, eval_##FUNC_NAME##_uvec2, eval_##FUNC_NAME##_uvec3, eval_##FUNC_NAME##_uvec4
#define BOOL_GENTYPE_FUNCS(FUNC_NAME) \
eval_##FUNC_NAME##_bool, eval_##FUNC_NAME##_bvec2, eval_##FUNC_NAME##_bvec3, eval_##FUNC_NAME##_bvec4
// Shorthands.
Value notUsed = Value(VALUE_NONE, 0.0f, 0.0f);
FloatScalar::Symbol lUMax = FloatScalar::SYMBOL_LOWP_UINT_MAX;
FloatScalar::Symbol mUMax = FloatScalar::SYMBOL_MEDIUMP_UINT_MAX;
FloatScalar::Symbol lUMaxR = FloatScalar::SYMBOL_LOWP_UINT_MAX_RECIPROCAL;
FloatScalar::Symbol mUMaxR = FloatScalar::SYMBOL_MEDIUMP_UINT_MAX_RECIPROCAL;
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("plus", "+", UGT, Value(UGT, 0.0f, 2e2f), notUsed, notUsed, 5e-3f, 0.0f, PRECMASK_ALL,
UINT_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))
<< BuiltinOperInfoSeparateRefScaleBias("minus", "-", UGT, Value(UGT, 0.0f, lUMax), notUsed, notUsed, lUMaxR,
0.0f, PRECMASK_LOWP, UINT_GENTYPE_FUNCS(negate), lUMaxR,
FloatScalar::SYMBOL_ONE_MINUS_UINT32MAX_DIV_LOWP_UINT_MAX)
<< BuiltinOperInfoSeparateRefScaleBias("minus", "-", UGT, Value(UGT, 0.0f, mUMax), notUsed, notUsed, mUMaxR,
0.0f, PRECMASK_MEDIUMP, UINT_GENTYPE_FUNCS(negate), mUMaxR,
FloatScalar::SYMBOL_ONE_MINUS_UINT32MAX_DIV_MEDIUMP_UINT_MAX)
<< BuiltinOperInfo("minus", "-", UGT, Value(UGT, 0.0f, 4e9f), notUsed, notUsed, 2e-10f, 0.0f, PRECMASK_HIGHP,
UINT_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)
<< BuiltinOperInfo("bitwise_not", "~", IGT, Value(IGT, -1e5f, 1e5f), notUsed, notUsed, 5e-5f, 0.5f,
PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseNot))
<< BuiltinOperInfo("bitwise_not", "~", UGT, Value(UGT, 0.0f, 2e9f), notUsed, notUsed, 2e-10f, 0.0f,
PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseNot))
// 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_increment_effect", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed, 0.1f,
0.0f, PRECMASK_ALL, UINT_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))
<< BuiltinSideEffOperInfo("pre_decrement_effect", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed, 0.1f,
0.0f, PRECMASK_ALL, UINT_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_increment_effect", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed,
0.1f, 0.0f, PRECMASK_ALL, UINT_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))
<< BuiltinPostSideEffOperInfo("post_decrement_effect", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed,
0.1f, 0.0f, PRECMASK_ALL, UINT_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_increment_result", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed, 0.1f, 0.0f,
PRECMASK_ALL, UINT_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))
<< BuiltinOperInfo("pre_decrement_result", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed, 0.1f, 0.0f,
PRECMASK_ALL, UINT_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_increment_result", "++", UGT, Value(UGT, 0.0f, 9.0f), notUsed, notUsed, 0.1f, 0.0f,
PRECMASK_ALL, UINT_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))
<< BuiltinPostOperInfo("post_decrement_result", "--", UGT, Value(UGT, 1.0f, 10.0f), notUsed, notUsed, 0.1f,
0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(nop)));
BuiltinFuncGroup binaryOpGroup("binary_operator", "Binary operator tests");
// Normal binary operations and their corresponding assignment operations have lots in common; generate both in the following loop.
for (int binaryOperatorType = 0; binaryOperatorType <= 2;
binaryOperatorType++) // 0: normal op test, 1: assignment op side-effect test, 2: assignment op result test
{
bool isNormalOp = binaryOperatorType == 0;
bool isAssignEff = binaryOperatorType == 1;
bool isAssignRes = binaryOperatorType == 2;
DE_ASSERT(isNormalOp || isAssignEff || isAssignRes);
DE_UNREF(isAssignRes);
const char *addName = isNormalOp ? "add" : isAssignEff ? "add_assign_effect" : "add_assign_result";
const char *subName = isNormalOp ? "sub" : isAssignEff ? "sub_assign_effect" : "sub_assign_result";
const char *mulName = isNormalOp ? "mul" : isAssignEff ? "mul_assign_effect" : "mul_assign_result";
const char *divName = isNormalOp ? "div" : isAssignEff ? "div_assign_effect" : "div_assign_result";
const char *modName = isNormalOp ? "mod" : isAssignEff ? "mod_assign_effect" : "mod_assign_result";
const char *andName = isNormalOp ? "bitwise_and" :
isAssignEff ? "bitwise_and_assign_effect" :
"bitwise_and_assign_result";
const char *orName = isNormalOp ? "bitwise_or" :
isAssignEff ? "bitwise_or_assign_effect" :
"bitwise_or_assign_result";
const char *xorName = isNormalOp ? "bitwise_xor" :
isAssignEff ? "bitwise_xor_assign_effect" :
"bitwise_xor_assign_result";
const char *leftShiftName = isNormalOp ? "left_shift" :
isAssignEff ? "left_shift_assign_effect" :
"left_shift_assign_result";
const char *rightShiftName = isNormalOp ? "right_shift" :
isAssignEff ? "right_shift_assign_effect" :
"right_shift_assign_result";
const char *addOp = isNormalOp ? "+" : "+=";
const char *subOp = isNormalOp ? "-" : "-=";
const char *mulOp = isNormalOp ? "*" : "*=";
const char *divOp = isNormalOp ? "/" : "/=";
const char *modOp = isNormalOp ? "%" : "%=";
const char *andOp = isNormalOp ? "&" : "&=";
const char *orOp = isNormalOp ? "|" : "|=";
const char *xorOp = isNormalOp ? "^" : "^=";
const char *leftShiftOp = isNormalOp ? "<<" : "<<=";
const char *rightShiftOp = isNormalOp ? ">>" : ">>=";
// Pointer to appropriate OperInfo function.
BuiltinFuncInfo (*operInfoFunc)(const char *, const char *, ValueType, Value, Value, Value, const FloatScalar &,
const FloatScalar &, uint32_t, ShaderEvalFunc, ShaderEvalFunc, ShaderEvalFunc,
ShaderEvalFunc) = isAssignEff ? BuiltinSideEffOperInfo : BuiltinOperInfo;
DE_ASSERT(operInfoFunc != DE_NULL);
// The following cases will be added for each operator, precision and fundamental type (float, int, uint) combination, where applicable:
// gentype <op> gentype
// vector <op> scalar
// For normal (non-assigning) operators only:
// scalar <op> vector
// The add operator.
binaryOpGroup << operInfoFunc(addName, addOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f,
0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(add))
<< operInfoFunc(addName, addOp, IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed,
0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(add))
<< operInfoFunc(addName, addOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(add))
<< operInfoFunc(addName, addOp, UGT, Value(UGT, 0.0f, 1e2f), Value(UGT, 0.0f, 1e2f), notUsed,
5e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(add))
<< operInfoFunc(addName, addOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(add))
<< operInfoFunc(addName, addOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(addVecScalar))
<< operInfoFunc(addName, addOp, IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f,
0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(addVecScalar))
<< operInfoFunc(addName, addOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(addVecScalar))
<< operInfoFunc(addName, addOp, UV, Value(UV, 0.0f, 1e2f), Value(U, 0.0f, 1e2f), notUsed, 5e-3f,
0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(addVecScalar))
<< operInfoFunc(addName, addOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(addVecScalar));
if (isNormalOp)
binaryOpGroup << operInfoFunc(addName, addOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(addScalarVec))
<< operInfoFunc(addName, addOp, IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed,
0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(addScalarVec))
<< operInfoFunc(addName, addOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(addScalarVec))
<< operInfoFunc(addName, addOp, UV, Value(U, 0.0f, 1e2f), Value(UV, 0.0f, 1e2f), notUsed,
5e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(addScalarVec))
<< operInfoFunc(addName, addOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(addScalarVec));
// The subtract operator.
binaryOpGroup << operInfoFunc(subName, subOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f,
0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(sub))
<< operInfoFunc(subName, subOp, IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed,
0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(sub))
<< operInfoFunc(subName, subOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(sub))
<< operInfoFunc(subName, subOp, UGT, Value(UGT, 1e2f, 2e2f), Value(UGT, 0.0f, 1e2f), notUsed,
5e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(sub))
<< operInfoFunc(subName, subOp, UGT, Value(UGT, .5e9f, 3.7e9f), Value(UGT, 0.0f, 3.9e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(sub))
<< operInfoFunc(subName, subOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(subVecScalar))
<< operInfoFunc(subName, subOp, IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f,
0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(subVecScalar))
<< operInfoFunc(subName, subOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(subVecScalar))
<< operInfoFunc(subName, subOp, UV, Value(UV, 1e2f, 2e2f), Value(U, 0.0f, 1e2f), notUsed, 5e-3f,
0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(subVecScalar))
<< operInfoFunc(subName, subOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(subVecScalar));
if (isNormalOp)
binaryOpGroup << operInfoFunc(subName, subOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(subScalarVec))
<< operInfoFunc(subName, subOp, IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed,
0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(subScalarVec))
<< operInfoFunc(subName, subOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(subScalarVec))
<< operInfoFunc(subName, subOp, UV, Value(U, 1e2f, 2e2f), Value(UV, 0.0f, 1e2f), notUsed,
5e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(subScalarVec))
<< operInfoFunc(subName, subOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(subScalarVec));
// The multiply operator.
binaryOpGroup << operInfoFunc(mulName, mulOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -1.0f, 1.0f), notUsed, 1.0f,
0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(mul))
<< operInfoFunc(mulName, mulOp, IGT, Value(IGT, -4.0f, 6.0f), Value(IGT, -6.0f, 5.0f), notUsed,
0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(mul))
<< operInfoFunc(mulName, mulOp, IGT, Value(IGT, -3e5f, 3e5f), Value(IGT, -3e4f, 3e4f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(mul))
<< operInfoFunc(mulName, mulOp, UGT, Value(UGT, 0.0f, 16.0f), Value(UGT, 0.0f, 16.0f), notUsed,
4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(mul))
<< operInfoFunc(mulName, mulOp, UGT, Value(UGT, 0.0f, 6e5f), Value(UGT, 0.0f, 6e4f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(mul))
<< operInfoFunc(mulName, mulOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -1.0f, 1.0f), notUsed, 1.0f,
0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mulVecScalar))
<< operInfoFunc(mulName, mulOp, IV, Value(IV, -4.0f, 6.0f), Value(I, -6.0f, 5.0f), notUsed, 0.1f,
0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(mulVecScalar))
<< operInfoFunc(mulName, mulOp, IV, Value(IV, -3e5f, 3e5f), Value(I, -3e4f, 3e4f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(mulVecScalar))
<< operInfoFunc(mulName, mulOp, UV, Value(UV, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 4e-3f,
0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(mulVecScalar))
<< operInfoFunc(mulName, mulOp, UV, Value(UV, 0.0f, 6e5f), Value(U, 0.0f, 6e4f), notUsed, 2e-10f,
0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(mulVecScalar));
if (isNormalOp)
binaryOpGroup << operInfoFunc(mulName, mulOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -1.0f, 1.0f), notUsed,
1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(mulScalarVec))
<< operInfoFunc(mulName, mulOp, IV, Value(I, -4.0f, 6.0f), Value(IV, -6.0f, 5.0f), notUsed,
0.1f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(mulScalarVec))
<< operInfoFunc(mulName, mulOp, IV, Value(I, -3e5f, 3e5f), Value(IV, -3e4f, 3e4f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(mulScalarVec))
<< operInfoFunc(mulName, mulOp, UV, Value(U, 0.0f, 16.0f), Value(UV, 0.0f, 16.0f), notUsed,
4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(mulScalarVec))
<< operInfoFunc(mulName, mulOp, UV, Value(U, 0.0f, 6e5f), Value(UV, 0.0f, 6e4f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(mulScalarVec));
// The divide operator.
binaryOpGroup << operInfoFunc(divName, divOp, GT, Value(GT, -1.0f, 1.0f), Value(GT, -2.0f, -0.5f), notUsed,
1.0f, 0.0f, PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(div))
<< operInfoFunc(divName, divOp, IGT, Value(IGT, 24.0f, 24.0f), Value(IGT, -4.0f, -1.0f), notUsed,
0.04f, 1.0f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(div))
<< operInfoFunc(divName, divOp, IGT, Value(IGT, 40320.0f, 40320.0f), Value(IGT, -8.0f, -1.0f),
notUsed, 1e-5f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(div))
<< operInfoFunc(divName, divOp, UGT, Value(UGT, 0.0f, 24.0f), Value(UGT, 1.0f, 4.0f), notUsed,
0.04f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(div))
<< operInfoFunc(divName, divOp, UGT, Value(UGT, 0.0f, 40320.0f), Value(UGT, 1.0f, 8.0f), notUsed,
1e-5f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(div))
<< operInfoFunc(divName, divOp, FV, Value(FV, -1.0f, 1.0f), Value(F, -2.0f, -0.5f), notUsed, 1.0f,
0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(divVecScalar))
<< operInfoFunc(divName, divOp, IV, Value(IV, 24.0f, 24.0f), Value(I, -4.0f, -1.0f), notUsed,
0.04f, 1.0f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(divVecScalar))
<< operInfoFunc(divName, divOp, IV, Value(IV, 40320.0f, 40320.0f), Value(I, -8.0f, -1.0f),
notUsed, 1e-5f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(divVecScalar))
<< operInfoFunc(divName, divOp, UV, Value(UV, 0.0f, 24.0f), Value(U, 1.0f, 4.0f), notUsed, 0.04f,
0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(divVecScalar))
<< operInfoFunc(divName, divOp, UV, Value(UV, 0.0f, 40320.0f), Value(U, 1.0f, 8.0f), notUsed,
1e-5f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(divVecScalar));
if (isNormalOp)
binaryOpGroup << operInfoFunc(divName, divOp, FV, Value(F, -1.0f, 1.0f), Value(FV, -2.0f, -0.5f), notUsed,
1.0f, 0.0f, PRECMASK_ALL, FLOAT_VEC_FUNCS(divScalarVec))
<< operInfoFunc(divName, divOp, IV, Value(I, 24.0f, 24.0f), Value(IV, -4.0f, -1.0f), notUsed,
0.04f, 1.0f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(divScalarVec))
<< operInfoFunc(divName, divOp, IV, Value(I, 40320.0f, 40320.0f), Value(IV, -8.0f, -1.0f),
notUsed, 1e-5f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(divScalarVec))
<< operInfoFunc(divName, divOp, UV, Value(U, 0.0f, 24.0f), Value(UV, 1.0f, 4.0f), notUsed,
0.04f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(divScalarVec))
<< operInfoFunc(divName, divOp, UV, Value(U, 0.0f, 40320.0f), Value(UV, 1.0f, 8.0f), notUsed,
1e-5f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(divScalarVec));
// The modulus operator.
binaryOpGroup << operInfoFunc(modName, modOp, IGT, Value(IGT, 0.0f, 6.0f), Value(IGT, 1.1f, 6.1f), notUsed,
0.25f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(mod))
<< operInfoFunc(modName, modOp, IGT, Value(IGT, 0.0f, 14.0f), Value(IGT, 1.1f, 11.1f), notUsed,
0.1f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(mod))
<< operInfoFunc(modName, modOp, UGT, Value(UGT, 0.0f, 6.0f), Value(UGT, 1.1f, 6.1f), notUsed,
0.25f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(mod))
<< operInfoFunc(modName, modOp, UGT, Value(UGT, 0.0f, 24.0f), Value(UGT, 1.1f, 11.1f), notUsed,
0.1f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(mod))
<< operInfoFunc(modName, modOp, IV, Value(IV, 0.0f, 6.0f), Value(I, 1.1f, 6.1f), notUsed, 0.25f,
0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(modVecScalar))
<< operInfoFunc(modName, modOp, IV, Value(IV, 0.0f, 6.0f), Value(I, 1.1f, 11.1f), notUsed, 0.1f,
0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(modVecScalar))
<< operInfoFunc(modName, modOp, UV, Value(UV, 0.0f, 6.0f), Value(U, 1.1f, 6.1f), notUsed, 0.25f,
0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(modVecScalar))
<< operInfoFunc(modName, modOp, UV, Value(UV, 0.0f, 24.0f), Value(U, 1.1f, 11.1f), notUsed, 0.1f,
0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(modVecScalar));
if (isNormalOp)
binaryOpGroup << operInfoFunc(modName, modOp, IV, Value(I, 0.0f, 6.0f), Value(IV, 1.1f, 6.1f), notUsed,
0.25f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(modScalarVec))
<< operInfoFunc(modName, modOp, IV, Value(I, 0.0f, 6.0f), Value(IV, 1.1f, 11.1f), notUsed,
0.1f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(modScalarVec))
<< operInfoFunc(modName, modOp, UV, Value(U, 0.0f, 6.0f), Value(UV, 1.1f, 6.1f), notUsed,
0.25f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(modScalarVec))
<< operInfoFunc(modName, modOp, UV, Value(U, 0.0f, 24.0f), Value(UV, 1.1f, 11.1f), notUsed,
0.1f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(modScalarVec));
// The bitwise and operator.
binaryOpGroup << operInfoFunc(andName, andOp, IGT, Value(IGT, -16.0f, 16.0f), Value(IGT, -16.0f, 16.0f),
notUsed, 0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(bitwiseAnd))
<< operInfoFunc(andName, andOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseAnd))
<< operInfoFunc(andName, andOp, UGT, Value(UGT, 0.0f, 32.0f), Value(UGT, 0.0f, 32.0f), notUsed,
0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(bitwiseAnd))
<< operInfoFunc(andName, andOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseAnd))
<< operInfoFunc(andName, andOp, IV, Value(IV, -16.0f, 16.0f), Value(I, -16.0f, 16.0f), notUsed,
0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(bitwiseAndVecScalar))
<< operInfoFunc(andName, andOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseAndVecScalar))
<< operInfoFunc(andName, andOp, UV, Value(UV, 0.0f, 32.0f), Value(U, 0.0f, 32.0f), notUsed, 0.03f,
0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseAndVecScalar))
<< operInfoFunc(andName, andOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseAndVecScalar));
if (isNormalOp)
binaryOpGroup << operInfoFunc(andName, andOp, IV, Value(I, -16.0f, 16.0f), Value(IV, -16.0f, 16.0f),
notUsed, 0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP,
INT_VEC_FUNCS(bitwiseAndScalarVec))
<< operInfoFunc(andName, andOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseAndScalarVec))
<< operInfoFunc(andName, andOp, UV, Value(U, 0.0f, 32.0f), Value(UV, 0.0f, 32.0f), notUsed,
0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseAndScalarVec))
<< operInfoFunc(andName, andOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseAndScalarVec));
// The bitwise or operator.
binaryOpGroup << operInfoFunc(orName, orOp, IGT, Value(IGT, -16.0f, 16.0f), Value(IGT, -16.0f, 16.0f), notUsed,
0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(bitwiseOr))
<< operInfoFunc(orName, orOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseOr))
<< operInfoFunc(orName, orOp, UGT, Value(UGT, 0.0f, 32.0f), Value(UGT, 0.0f, 32.0f), notUsed,
0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(bitwiseOr))
<< operInfoFunc(orName, orOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseOr))
<< operInfoFunc(orName, orOp, IV, Value(IV, -16.0f, 16.0f), Value(I, -16.0f, 16.0f), notUsed,
0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(bitwiseOrVecScalar))
<< operInfoFunc(orName, orOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed, 4e-10f,
0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseOrVecScalar))
<< operInfoFunc(orName, orOp, UV, Value(UV, 0.0f, 32.0f), Value(U, 0.0f, 32.0f), notUsed, 0.03f,
0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseOrVecScalar))
<< operInfoFunc(orName, orOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseOrVecScalar));
if (isNormalOp)
binaryOpGroup << operInfoFunc(orName, orOp, IV, Value(I, -16.0f, 16.0f), Value(IV, -16.0f, 16.0f), notUsed,
0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(bitwiseOrScalarVec))
<< operInfoFunc(orName, orOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseOrScalarVec))
<< operInfoFunc(orName, orOp, UV, Value(U, 0.0f, 32.0f), Value(UV, 0.0f, 32.0f), notUsed,
0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseOrScalarVec))
<< operInfoFunc(orName, orOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseOrScalarVec));
// The bitwise xor operator.
binaryOpGroup << operInfoFunc(xorName, xorOp, IGT, Value(IGT, -16.0f, 16.0f), Value(IGT, -16.0f, 16.0f),
notUsed, 0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_GENTYPE_FUNCS(bitwiseXor))
<< operInfoFunc(xorName, xorOp, IGT, Value(IGT, -2e9f, 2e9f), Value(IGT, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_GENTYPE_FUNCS(bitwiseXor))
<< operInfoFunc(xorName, xorOp, UGT, Value(UGT, 0.0f, 32.0f), Value(UGT, 0.0f, 32.0f), notUsed,
0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_GENTYPE_FUNCS(bitwiseXor))
<< operInfoFunc(xorName, xorOp, UGT, Value(UGT, 0.0f, 4e9f), Value(UGT, 0.0f, 4e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_GENTYPE_FUNCS(bitwiseXor))
<< operInfoFunc(xorName, xorOp, IV, Value(IV, -16.0f, 16.0f), Value(I, -16.0f, 16.0f), notUsed,
0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP, INT_VEC_FUNCS(bitwiseXorVecScalar))
<< operInfoFunc(xorName, xorOp, IV, Value(IV, -2e9f, 2e9f), Value(I, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseXorVecScalar))
<< operInfoFunc(xorName, xorOp, UV, Value(UV, 0.0f, 32.0f), Value(U, 0.0f, 32.0f), notUsed, 0.03f,
0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseXorVecScalar))
<< operInfoFunc(xorName, xorOp, UV, Value(UV, 0.0f, 4e9f), Value(U, 0.0f, 4e9f), notUsed, 2e-10f,
0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseXorVecScalar));
if (isNormalOp)
binaryOpGroup << operInfoFunc(xorName, xorOp, IV, Value(I, -16.0f, 16.0f), Value(IV, -16.0f, 16.0f),
notUsed, 0.03f, 0.5f, PRECMASK_LOWP_MEDIUMP,
INT_VEC_FUNCS(bitwiseXorScalarVec))
<< operInfoFunc(xorName, xorOp, IV, Value(I, -2e9f, 2e9f), Value(IV, -2e9f, 2e9f), notUsed,
4e-10f, 0.5f, PRECMASK_HIGHP, INT_VEC_FUNCS(bitwiseXorScalarVec))
<< operInfoFunc(xorName, xorOp, UV, Value(U, 0.0f, 32.0f), Value(UV, 0.0f, 32.0f), notUsed,
0.03f, 0.0f, PRECMASK_LOWP_MEDIUMP, UINT_VEC_FUNCS(bitwiseXorScalarVec))
<< operInfoFunc(xorName, xorOp, UV, Value(U, 0.0f, 4e9f), Value(UV, 0.0f, 4e9f), notUsed,
2e-10f, 0.0f, PRECMASK_HIGHP, UINT_VEC_FUNCS(bitwiseXorScalarVec));
// The left shift operator. Second operand (shift amount) can be either int or uint, even for uint and int first operand, respectively.
for (int isSignedAmount = 0; isSignedAmount <= 1; isSignedAmount++)
{
ValueType gType = isSignedAmount == 0 ? UGT : IGT;
ValueType sType = isSignedAmount == 0 ? U : I;
binaryOpGroup << operInfoFunc(leftShiftName, leftShiftOp, IGT, Value(IGT, -7.0f, 7.0f),
Value(gType, 0.0f, 4.0f), notUsed, 4e-3f, 0.5f, PRECMASK_LOWP_MEDIUMP,
INT_GENTYPE_FUNCS(leftShift))
<< operInfoFunc(leftShiftName, leftShiftOp, IGT, Value(IGT, -7.0f, 7.0f),
Value(gType, 0.0f, 27.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
INT_GENTYPE_FUNCS(leftShift))
<< operInfoFunc(leftShiftName, leftShiftOp, UGT, Value(UGT, 0.0f, 7.0f),
Value(gType, 0.0f, 5.0f), notUsed, 4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP,
UINT_GENTYPE_FUNCS(leftShift))
<< operInfoFunc(leftShiftName, leftShiftOp, UGT, Value(UGT, 0.0f, 7.0f),
Value(gType, 0.0f, 28.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
UINT_GENTYPE_FUNCS(leftShift))
<< operInfoFunc(leftShiftName, leftShiftOp, IV, Value(IV, -7.0f, 7.0f),
Value(sType, 0.0f, 4.0f), notUsed, 4e-3f, 0.5f, PRECMASK_LOWP_MEDIUMP,
INT_VEC_FUNCS(leftShiftVecScalar))
<< operInfoFunc(leftShiftName, leftShiftOp, IV, Value(IV, -7.0f, 7.0f),
Value(sType, 0.0f, 27.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
INT_VEC_FUNCS(leftShiftVecScalar))
<< operInfoFunc(leftShiftName, leftShiftOp, UV, Value(UV, 0.0f, 7.0f),
Value(sType, 0.0f, 5.0f), notUsed, 4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP,
UINT_VEC_FUNCS(leftShiftVecScalar))
<< operInfoFunc(leftShiftName, leftShiftOp, UV, Value(UV, 0.0f, 7.0f),
Value(sType, 0.0f, 28.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
UINT_VEC_FUNCS(leftShiftVecScalar));
}
// The right shift operator. Second operand (shift amount) can be either int or uint, even for uint and int first operand, respectively.
for (int isSignedAmount = 0; isSignedAmount <= 1; isSignedAmount++)
{
ValueType gType = isSignedAmount == 0 ? UGT : IGT;
ValueType sType = isSignedAmount == 0 ? U : I;
binaryOpGroup << operInfoFunc(rightShiftName, rightShiftOp, IGT, Value(IGT, -127.0f, 127.0f),
Value(gType, 0.0f, 8.0f), notUsed, 4e-3f, 0.5f, PRECMASK_LOWP_MEDIUMP,
INT_GENTYPE_FUNCS(rightShift))
<< operInfoFunc(rightShiftName, rightShiftOp, IGT, Value(IGT, -2e9f, 2e9f),
Value(gType, 0.0f, 31.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
INT_GENTYPE_FUNCS(rightShift))
<< operInfoFunc(rightShiftName, rightShiftOp, UGT, Value(UGT, 0.0f, 255.0f),
Value(gType, 0.0f, 8.0f), notUsed, 4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP,
UINT_GENTYPE_FUNCS(rightShift))
<< operInfoFunc(rightShiftName, rightShiftOp, UGT, Value(UGT, 0.0f, 4e9f),
Value(gType, 0.0f, 31.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
UINT_GENTYPE_FUNCS(rightShift))
<< operInfoFunc(rightShiftName, rightShiftOp, IV, Value(IV, -127.0f, 127.0f),
Value(sType, 0.0f, 8.0f), notUsed, 4e-3f, 0.5f, PRECMASK_LOWP_MEDIUMP,
INT_VEC_FUNCS(rightShiftVecScalar))
<< operInfoFunc(rightShiftName, rightShiftOp, IV, Value(IV, -2e9f, 2e9f),
Value(sType, 0.0f, 31.0f), notUsed, 5e-10f, 0.5f, PRECMASK_HIGHP,
INT_VEC_FUNCS(rightShiftVecScalar))
<< operInfoFunc(rightShiftName, rightShiftOp, UV, Value(UV, 0.0f, 255.0f),
Value(sType, 0.0f, 8.0f), notUsed, 4e-3f, 0.0f, PRECMASK_LOWP_MEDIUMP,
UINT_VEC_FUNCS(rightShiftVecScalar))
<< operInfoFunc(rightShiftName, rightShiftOp, UV, Value(UV, 0.0f, 4e9f),
Value(sType, 0.0f, 31.0f), notUsed, 5e-10f, 0.0f, PRECMASK_HIGHP,
UINT_VEC_FUNCS(rightShiftVecScalar));
}
}
// Rest of binary operators.
binaryOpGroup
// 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", "<", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f, 0.0f,
PRECMASK_ALL, eval_lessThan_uint, 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("less_or_equal", "<=", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f, 0.0f,
PRECMASK_ALL, eval_lessThanEqual_uint, 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", ">", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f, 0.0f,
PRECMASK_ALL, eval_greaterThan_uint, 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)
<< BuiltinOperInfo("greater_or_equal", ">=", B, Value(U, 0.0f, 16.0f), Value(U, 0.0f, 16.0f), notUsed, 1.0f,
0.0f, PRECMASK_ALL, eval_greaterThanEqual_uint, 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, -2.1f, 0.1f), notUsed, 1.0f, 0.0f,
PRECMASK_ALL, INT_GENTYPE_FUNCS(allEqual))
<< BuiltinOperInfo("equal", "==", B, Value(UGT, 0.0f, 8.0f), Value(UGT, 3.5f, 4.5f), notUsed, 1.0f, 0.0f,
PRECMASK_ALL, UINT_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, -2.1f, 0.1f), notUsed, 1.0f, 0.0f,
PRECMASK_ALL, INT_GENTYPE_FUNCS(anyNotEqual))
<< BuiltinOperInfo("not_equal", "!=", B, Value(UGT, 0.0f, 8.0f), Value(UGT, 3.5f, 4.5f), notUsed, 1.0f, 0.0f,
PRECMASK_ALL, UINT_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));
funcInfoGroups.push_back(binaryOpGroup);
// 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))
<< BuiltinFuncInfo("sinh", "sinh", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f,
0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(sinh))
<< BuiltinFuncInfo("sinh", "sinh", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f,
0.5f, PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(sinh))
<< BuiltinFuncInfo("cosh", "cosh", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f,
0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(cosh))
<< BuiltinFuncInfo("cosh", "cosh", GT, Value(GT, -1.5f, 1.5f), notUsed, notUsed, 0.5f,
0.5f, PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(cosh))
<< BuiltinFuncInfo("tanh", "tanh", GT, Value(GT, -5.0f, 5.0f), notUsed, notUsed, 0.5f,
0.5f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(tanh))
<< BuiltinFuncInfo("tanh", "tanh", GT, Value(GT, -1.5f, 5.5f), notUsed, notUsed, 0.5f,
0.5f, PRECMASK_LOWP, FLOAT_GENTYPE_FUNCS(tanh))
<< BuiltinFuncInfo("asinh", "asinh", GT, Value(GT, -1.0f, 1.0f), notUsed, notUsed, 1.0f,
0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(asinh))
<< BuiltinFuncInfo("acosh", "acosh", GT, Value(GT, 1.0f, 2.2f), notUsed, notUsed, 1.0f,
0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(acosh))
<< BuiltinFuncInfo("atanh", "atanh", GT, Value(GT, -0.99f, 0.99f), notUsed, notUsed, 1.0f,
0.0f, PRECMASK_MEDIUMP_HIGHP, FLOAT_GENTYPE_FUNCS(atanh)));
// 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("trunc", "trunc", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.7f, PRECMASK_ALL,
FLOAT_GENTYPE_FUNCS(trunc))
<< BuiltinFuncInfo("round", "round", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.7f, PRECMASK_ALL,
FLOAT_GENTYPE_FUNCS(roundToEven))
<< BuiltinFuncInfo("roundEven", "roundEven", GT, Value(GT, -2.5f, 2.5f), notUsed, notUsed, 0.2f, 0.7f,
PRECMASK_ALL, FLOAT_GENTYPE_FUNCS(roundToEven))
<< 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(modVecScalar))
<< 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(minVecScalar))
<< BuiltinFuncInfo("min", "min", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
PRECMASK_ALL, INT_GENTYPE_FUNCS(min))
<< BuiltinFuncInfo("min", "min", IGT, Value(IV, -4.0f, 4.0f), Value(I, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
PRECMASK_ALL, INT_VEC_FUNCS(minVecScalar))
<< BuiltinFuncInfo("min", "min", UGT, Value(UGT, 0.0f, 8.0f), Value(UGT, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
PRECMASK_ALL, UINT_GENTYPE_FUNCS(min))
<< BuiltinFuncInfo("min", "min", UGT, Value(UV, 0.0f, 8.0f), Value(U, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
PRECMASK_ALL, UINT_VEC_FUNCS(minVecScalar))
<< 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(maxVecScalar))
<< BuiltinFuncInfo("max", "max", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
PRECMASK_ALL, INT_GENTYPE_FUNCS(max))
<< BuiltinFuncInfo("max", "max", IGT, Value(IV, -4.0f, 4.0f), Value(I, -4.0f, 4.0f), notUsed, 0.125f, 0.5f,
PRECMASK_ALL, INT_VEC_FUNCS(maxVecScalar))
<< BuiltinFuncInfo("max", "max", UGT, Value(UGT, 0.0f, 8.0f), Value(UGT, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
PRECMASK_ALL, UINT_GENTYPE_FUNCS(max))
<< BuiltinFuncInfo("max", "max", UGT, Value(UV, 0.0f, 8.0f), Value(U, 0.0f, 8.0f), notUsed, 0.125f, 0.0f,
PRECMASK_ALL, UINT_VEC_FUNCS(maxVecScalar))
<< 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(clampVecScalarScalar))
<< BuiltinFuncInfo("clamp", "clamp", IGT, Value(IGT, -4.0f, 4.0f), Value(IGT, -2.0f, 2.0f),
Value(IGT, 2.0f, 4.0f), 0.125f, 0.5f, PRECMASK_ALL, INT_GENTYPE_FUNCS(clamp))
<< BuiltinFuncInfo("clamp", "clamp", IGT, Value(IV, -4.0f, 4.0f), Value(I, -2.0f, 2.0f), Value(I, 2.0f, 4.0f),
0.125f, 0.5f, PRECMASK_ALL, INT_VEC_FUNCS(clampVecScalarScalar))
<< BuiltinFuncInfo("clamp", "clamp", UGT, Value(UGT, 0.0f, 8.0f), Value(UGT, 2.0f, 6.0f),
Value(UGT, 6.0f, 8.0f), 0.125f, 0.0f, PRECMASK_ALL, UINT_GENTYPE_FUNCS(clamp))
<< BuiltinFuncInfo("clamp", "clamp", UGT, Value(UV, 0.0f, 8.0f), Value(U, 2.0f, 6.0f), Value(U, 6.0f, 8.0f),
0.125f, 0.0f, PRECMASK_ALL, UINT_VEC_FUNCS(clampVecScalarScalar))
<< 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(mixVecVecScalar))
<< 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(stepScalarVec))
<< 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(smoothStepScalarScalarVec)));
// 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)));
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_uintTypes[] = {TYPE_UINT, TYPE_UINT_VEC2, TYPE_UINT_VEC3, TYPE_UINT_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 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 isUintOut = (funcInfo.outValue & (VALUE_UINT | VALUE_UINT_VEC | VALUE_UINT_GENTYPE)) != 0;
bool isFloatOut = !isBoolOut && !isIntOut && !isUintOut;
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] :
isUintOut ? s_uintTypes[outScalarSize - 1] :
isBoolOut ? s_boolTypes[outScalarSize - 1] :
TYPE_LAST;
ShaderEvalFunc evalFunc = DE_NULL;
switch (inScalarSize)
{
case 1:
evalFunc = funcInfo.evalFuncScalar;
break;
case 2:
evalFunc = funcInfo.evalFuncVec2;
break;
case 3:
evalFunc = funcInfo.evalFuncVec3;
break;
case 4:
evalFunc = funcInfo.evalFuncVec4;
break;
default:
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 = "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;
shaderSpec.referenceScale = funcInfo.referenceScale;
shaderSpec.referenceBias = funcInfo.referenceBias;
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 &prevV = (inputNdx == 1) ? funcInfo.input0 :
(inputNdx == 2) ? funcInfo.input1 :
funcInfo.input2;
const Value &v = (inputNdx == 0) ? funcInfo.input0 :
(inputNdx == 1) ? funcInfo.input1 :
funcInfo.input2;
if (v.valueType == VALUE_NONE)
continue; // Skip unused input.
int prevInScalarSize = isScalarType(prevV.valueType) ? 1 : inScalarSize;
DataType prevInDataType =
isFloatType(prevV.valueType) ? s_floatTypes[prevInScalarSize - 1] :
isIntType(prevV.valueType) ? s_intTypes[prevInScalarSize - 1] :
isUintType(prevV.valueType) ? s_uintTypes[prevInScalarSize - 1] :
isBoolType(prevV.valueType) ? s_boolTypes[prevInScalarSize - 1] :
TYPE_LAST;
int curInScalarSize = isScalarType(v.valueType) ? 1 : inScalarSize;
DataType curInDataType = isFloatType(v.valueType) ? s_floatTypes[curInScalarSize - 1] :
isIntType(v.valueType) ? s_intTypes[curInScalarSize - 1] :
isUintType(v.valueType) ? s_uintTypes[curInScalarSize - 1] :
isBoolType(v.valueType) ? 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 ||
prevInDataType !=
curInDataType) // \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, 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_UINT, eval_selection_uint}, {TYPE_UINT_VEC2, eval_selection_uvec2},
{TYPE_UINT_VEC3, eval_selection_uvec3}, {TYPE_UINT_VEC4, eval_selection_uvec4},
{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);
bool isUintCase = isDataTypeUintOrUVec(curType);
const char *dataTypeStr = getDataTypeName(curType);
DE_ASSERT(isBoolCase || isFloatCase || isIntCase || isUintCase);
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 : isUintCase ? 0.5f : 0.1f;
shaderSpec.resultBias = isBoolCase ? 0.0f : isFloatCase ? 0.5f : isUintCase ? 0.0f : 0.5f;
shaderSpec.referenceScale = shaderSpec.resultScale;
shaderSpec.referenceBias = shaderSpec.resultBias;
float rangeMin = isBoolCase ? -1.0f : isFloatCase ? -1.0f : isUintCase ? 0.0f : -5.0f;
float rangeMax = isBoolCase ? 1.0f : isFloatCase ? 1.0f : isUintCase ? 2.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_uint",
"in0 + in2, in1 + in1",
3,
{TYPE_FLOAT, TYPE_UINT, TYPE_FLOAT},
TYPE_UINT,
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_uint",
"in1++, in0 = float(in1), in1 = uint(in0 + in2)",
3,
{TYPE_FLOAT, TYPE_UINT, TYPE_FLOAT},
TYPE_UINT,
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;
shaderSpec.referenceScale = shaderSpec.resultScale;
shaderSpec.referenceBias = shaderSpec.resultBias;
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 :
isDataTypeUintOrUVec(type) ? 0.0f :
-1.0f;
float rangeMax = isDataTypeFloatOrVec(type) ? 0.5f :
isDataTypeIntOrIVec(type) ? 2.0f :
isDataTypeUintOrUVec(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));
}
}
}
}
} // namespace Functional
} // namespace gles3
} // namespace deqp