1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program OpenGL ES 3.0 Module
3*35238bceSAndroid Build Coastguard Worker * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker *
5*35238bceSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker *
7*35238bceSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker *
11*35238bceSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker *
13*35238bceSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker *
19*35238bceSAndroid Build Coastguard Worker *//*!
20*35238bceSAndroid Build Coastguard Worker * \file
21*35238bceSAndroid Build Coastguard Worker * \brief Common built-in function tests.
22*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker
24*35238bceSAndroid Build Coastguard Worker #include "es3fShaderCommonFunctionTests.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "glsShaderExecUtil.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "tcuFormatUtil.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "tcuVectorUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "tcuFloat.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "deMath.h"
32*35238bceSAndroid Build Coastguard Worker #include "deString.h"
33*35238bceSAndroid Build Coastguard Worker
34*35238bceSAndroid Build Coastguard Worker namespace deqp
35*35238bceSAndroid Build Coastguard Worker {
36*35238bceSAndroid Build Coastguard Worker namespace gles3
37*35238bceSAndroid Build Coastguard Worker {
38*35238bceSAndroid Build Coastguard Worker namespace Functional
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker
41*35238bceSAndroid Build Coastguard Worker using std::string;
42*35238bceSAndroid Build Coastguard Worker using std::vector;
43*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
44*35238bceSAndroid Build Coastguard Worker using namespace gls::ShaderExecUtil;
45*35238bceSAndroid Build Coastguard Worker
46*35238bceSAndroid Build Coastguard Worker using tcu::IVec2;
47*35238bceSAndroid Build Coastguard Worker using tcu::IVec3;
48*35238bceSAndroid Build Coastguard Worker using tcu::IVec4;
49*35238bceSAndroid Build Coastguard Worker using tcu::Vec2;
50*35238bceSAndroid Build Coastguard Worker using tcu::Vec3;
51*35238bceSAndroid Build Coastguard Worker using tcu::Vec4;
52*35238bceSAndroid Build Coastguard Worker
53*35238bceSAndroid Build Coastguard Worker // Utilities
54*35238bceSAndroid Build Coastguard Worker
55*35238bceSAndroid Build Coastguard Worker template <typename T, int Size>
56*35238bceSAndroid Build Coastguard Worker struct VecArrayAccess
57*35238bceSAndroid Build Coastguard Worker {
58*35238bceSAndroid Build Coastguard Worker public:
VecArrayAccessdeqp::gles3::Functional::VecArrayAccess59*35238bceSAndroid Build Coastguard Worker VecArrayAccess(const void *ptr) : m_array((tcu::Vector<T, Size> *)ptr)
60*35238bceSAndroid Build Coastguard Worker {
61*35238bceSAndroid Build Coastguard Worker }
~VecArrayAccessdeqp::gles3::Functional::VecArrayAccess62*35238bceSAndroid Build Coastguard Worker ~VecArrayAccess(void)
63*35238bceSAndroid Build Coastguard Worker {
64*35238bceSAndroid Build Coastguard Worker }
65*35238bceSAndroid Build Coastguard Worker
operator []deqp::gles3::Functional::VecArrayAccess66*35238bceSAndroid Build Coastguard Worker const tcu::Vector<T, Size> &operator[](size_t offset) const
67*35238bceSAndroid Build Coastguard Worker {
68*35238bceSAndroid Build Coastguard Worker return m_array[offset];
69*35238bceSAndroid Build Coastguard Worker }
operator []deqp::gles3::Functional::VecArrayAccess70*35238bceSAndroid Build Coastguard Worker tcu::Vector<T, Size> &operator[](size_t offset)
71*35238bceSAndroid Build Coastguard Worker {
72*35238bceSAndroid Build Coastguard Worker return m_array[offset];
73*35238bceSAndroid Build Coastguard Worker }
74*35238bceSAndroid Build Coastguard Worker
75*35238bceSAndroid Build Coastguard Worker private:
76*35238bceSAndroid Build Coastguard Worker tcu::Vector<T, Size> *m_array;
77*35238bceSAndroid Build Coastguard Worker };
78*35238bceSAndroid Build Coastguard Worker
79*35238bceSAndroid Build Coastguard Worker template <typename T, int Size>
fillRandomVectors(de::Random & rnd,const tcu::Vector<T,Size> & minValue,const tcu::Vector<T,Size> & maxValue,void * dst,int numValues,int offset=0)80*35238bceSAndroid Build Coastguard Worker static void fillRandomVectors(de::Random &rnd, const tcu::Vector<T, Size> &minValue,
81*35238bceSAndroid Build Coastguard Worker const tcu::Vector<T, Size> &maxValue, void *dst, int numValues, int offset = 0)
82*35238bceSAndroid Build Coastguard Worker {
83*35238bceSAndroid Build Coastguard Worker VecArrayAccess<T, Size> access(dst);
84*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues; ndx++)
85*35238bceSAndroid Build Coastguard Worker access[offset + ndx] = tcu::randomVector<T, Size>(rnd, minValue, maxValue);
86*35238bceSAndroid Build Coastguard Worker }
87*35238bceSAndroid Build Coastguard Worker
88*35238bceSAndroid Build Coastguard Worker template <typename T>
fillRandomScalars(de::Random & rnd,T minValue,T maxValue,void * dst,int numValues,int offset=0)89*35238bceSAndroid Build Coastguard Worker static void fillRandomScalars(de::Random &rnd, T minValue, T maxValue, void *dst, int numValues, int offset = 0)
90*35238bceSAndroid Build Coastguard Worker {
91*35238bceSAndroid Build Coastguard Worker T *typedPtr = (T *)dst;
92*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues; ndx++)
93*35238bceSAndroid Build Coastguard Worker typedPtr[offset + ndx] = de::randomScalar<T>(rnd, minValue, maxValue);
94*35238bceSAndroid Build Coastguard Worker }
95*35238bceSAndroid Build Coastguard Worker
numBitsLostInOp(float input,float output)96*35238bceSAndroid Build Coastguard Worker inline int numBitsLostInOp(float input, float output)
97*35238bceSAndroid Build Coastguard Worker {
98*35238bceSAndroid Build Coastguard Worker const int inExp = tcu::Float32(input).exponent();
99*35238bceSAndroid Build Coastguard Worker const int outExp = tcu::Float32(output).exponent();
100*35238bceSAndroid Build Coastguard Worker
101*35238bceSAndroid Build Coastguard Worker return de::max(0, inExp - outExp); // Lost due to mantissa shift.
102*35238bceSAndroid Build Coastguard Worker }
103*35238bceSAndroid Build Coastguard Worker
getUlpDiff(float a,float b)104*35238bceSAndroid Build Coastguard Worker inline uint32_t getUlpDiff(float a, float b)
105*35238bceSAndroid Build Coastguard Worker {
106*35238bceSAndroid Build Coastguard Worker const uint32_t aBits = tcu::Float32(a).bits();
107*35238bceSAndroid Build Coastguard Worker const uint32_t bBits = tcu::Float32(b).bits();
108*35238bceSAndroid Build Coastguard Worker return aBits > bBits ? aBits - bBits : bBits - aBits;
109*35238bceSAndroid Build Coastguard Worker }
110*35238bceSAndroid Build Coastguard Worker
getUlpDiffIgnoreZeroSign(float a,float b)111*35238bceSAndroid Build Coastguard Worker inline uint32_t getUlpDiffIgnoreZeroSign(float a, float b)
112*35238bceSAndroid Build Coastguard Worker {
113*35238bceSAndroid Build Coastguard Worker if (tcu::Float32(a).isZero())
114*35238bceSAndroid Build Coastguard Worker return getUlpDiff(tcu::Float32::construct(tcu::Float32(b).sign(), 0, 0).asFloat(), b);
115*35238bceSAndroid Build Coastguard Worker else if (tcu::Float32(b).isZero())
116*35238bceSAndroid Build Coastguard Worker return getUlpDiff(a, tcu::Float32::construct(tcu::Float32(a).sign(), 0, 0).asFloat());
117*35238bceSAndroid Build Coastguard Worker else
118*35238bceSAndroid Build Coastguard Worker return getUlpDiff(a, b);
119*35238bceSAndroid Build Coastguard Worker }
120*35238bceSAndroid Build Coastguard Worker
supportsSignedZero(glu::Precision precision)121*35238bceSAndroid Build Coastguard Worker inline bool supportsSignedZero(glu::Precision precision)
122*35238bceSAndroid Build Coastguard Worker {
123*35238bceSAndroid Build Coastguard Worker // \note GLSL ES 3.0 doesn't really require support for -0, but we require it for highp
124*35238bceSAndroid Build Coastguard Worker // as it is very widely supported.
125*35238bceSAndroid Build Coastguard Worker return precision == glu::PRECISION_HIGHP;
126*35238bceSAndroid Build Coastguard Worker }
127*35238bceSAndroid Build Coastguard Worker
getEpsFromMaxUlpDiff(float value,uint32_t ulpDiff)128*35238bceSAndroid Build Coastguard Worker inline float getEpsFromMaxUlpDiff(float value, uint32_t ulpDiff)
129*35238bceSAndroid Build Coastguard Worker {
130*35238bceSAndroid Build Coastguard Worker const int exp = tcu::Float32(value).exponent();
131*35238bceSAndroid Build Coastguard Worker return tcu::Float32::construct(+1, exp, (1u << 23) | ulpDiff).asFloat() -
132*35238bceSAndroid Build Coastguard Worker tcu::Float32::construct(+1, exp, 1u << 23).asFloat();
133*35238bceSAndroid Build Coastguard Worker }
134*35238bceSAndroid Build Coastguard Worker
getMaxUlpDiffFromBits(int numAccurateBits)135*35238bceSAndroid Build Coastguard Worker inline uint32_t getMaxUlpDiffFromBits(int numAccurateBits)
136*35238bceSAndroid Build Coastguard Worker {
137*35238bceSAndroid Build Coastguard Worker const int numGarbageBits = 23 - numAccurateBits;
138*35238bceSAndroid Build Coastguard Worker const uint32_t mask = (1u << numGarbageBits) - 1u;
139*35238bceSAndroid Build Coastguard Worker
140*35238bceSAndroid Build Coastguard Worker return mask;
141*35238bceSAndroid Build Coastguard Worker }
142*35238bceSAndroid Build Coastguard Worker
getEpsFromBits(float value,int numAccurateBits)143*35238bceSAndroid Build Coastguard Worker inline float getEpsFromBits(float value, int numAccurateBits)
144*35238bceSAndroid Build Coastguard Worker {
145*35238bceSAndroid Build Coastguard Worker return getEpsFromMaxUlpDiff(value, getMaxUlpDiffFromBits(numAccurateBits));
146*35238bceSAndroid Build Coastguard Worker }
147*35238bceSAndroid Build Coastguard Worker
getMinMantissaBits(glu::Precision precision)148*35238bceSAndroid Build Coastguard Worker static int getMinMantissaBits(glu::Precision precision)
149*35238bceSAndroid Build Coastguard Worker {
150*35238bceSAndroid Build Coastguard Worker const int bits[] = {
151*35238bceSAndroid Build Coastguard Worker 7, // lowp
152*35238bceSAndroid Build Coastguard Worker 10, // mediump
153*35238bceSAndroid Build Coastguard Worker 23 // highp
154*35238bceSAndroid Build Coastguard Worker };
155*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bits) == glu::PRECISION_LAST);
156*35238bceSAndroid Build Coastguard Worker DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(bits)));
157*35238bceSAndroid Build Coastguard Worker return bits[precision];
158*35238bceSAndroid Build Coastguard Worker }
159*35238bceSAndroid Build Coastguard Worker
160*35238bceSAndroid Build Coastguard Worker // CommonFunctionCase
161*35238bceSAndroid Build Coastguard Worker
162*35238bceSAndroid Build Coastguard Worker class CommonFunctionCase : public TestCase
163*35238bceSAndroid Build Coastguard Worker {
164*35238bceSAndroid Build Coastguard Worker public:
165*35238bceSAndroid Build Coastguard Worker CommonFunctionCase(Context &context, const char *name, const char *description, glu::ShaderType shaderType);
166*35238bceSAndroid Build Coastguard Worker ~CommonFunctionCase(void);
167*35238bceSAndroid Build Coastguard Worker
168*35238bceSAndroid Build Coastguard Worker void init(void);
169*35238bceSAndroid Build Coastguard Worker void deinit(void);
170*35238bceSAndroid Build Coastguard Worker IterateResult iterate(void);
171*35238bceSAndroid Build Coastguard Worker
172*35238bceSAndroid Build Coastguard Worker protected:
173*35238bceSAndroid Build Coastguard Worker CommonFunctionCase(const CommonFunctionCase &other);
174*35238bceSAndroid Build Coastguard Worker CommonFunctionCase &operator=(const CommonFunctionCase &other);
175*35238bceSAndroid Build Coastguard Worker
176*35238bceSAndroid Build Coastguard Worker virtual void getInputValues(int numValues, void *const *values) const = 0;
177*35238bceSAndroid Build Coastguard Worker virtual bool compare(const void *const *inputs, const void *const *outputs) = 0;
178*35238bceSAndroid Build Coastguard Worker
179*35238bceSAndroid Build Coastguard Worker glu::ShaderType m_shaderType;
180*35238bceSAndroid Build Coastguard Worker ShaderSpec m_spec;
181*35238bceSAndroid Build Coastguard Worker int m_numValues;
182*35238bceSAndroid Build Coastguard Worker
183*35238bceSAndroid Build Coastguard Worker std::ostringstream m_failMsg; //!< Comparison failure help message.
184*35238bceSAndroid Build Coastguard Worker
185*35238bceSAndroid Build Coastguard Worker private:
186*35238bceSAndroid Build Coastguard Worker ShaderExecutor *m_executor;
187*35238bceSAndroid Build Coastguard Worker };
188*35238bceSAndroid Build Coastguard Worker
CommonFunctionCase(Context & context,const char * name,const char * description,glu::ShaderType shaderType)189*35238bceSAndroid Build Coastguard Worker CommonFunctionCase::CommonFunctionCase(Context &context, const char *name, const char *description,
190*35238bceSAndroid Build Coastguard Worker glu::ShaderType shaderType)
191*35238bceSAndroid Build Coastguard Worker : TestCase(context, name, description)
192*35238bceSAndroid Build Coastguard Worker , m_shaderType(shaderType)
193*35238bceSAndroid Build Coastguard Worker , m_numValues(100)
194*35238bceSAndroid Build Coastguard Worker , m_executor(DE_NULL)
195*35238bceSAndroid Build Coastguard Worker {
196*35238bceSAndroid Build Coastguard Worker m_spec.version = glu::GLSL_VERSION_300_ES;
197*35238bceSAndroid Build Coastguard Worker }
198*35238bceSAndroid Build Coastguard Worker
~CommonFunctionCase(void)199*35238bceSAndroid Build Coastguard Worker CommonFunctionCase::~CommonFunctionCase(void)
200*35238bceSAndroid Build Coastguard Worker {
201*35238bceSAndroid Build Coastguard Worker CommonFunctionCase::deinit();
202*35238bceSAndroid Build Coastguard Worker }
203*35238bceSAndroid Build Coastguard Worker
init(void)204*35238bceSAndroid Build Coastguard Worker void CommonFunctionCase::init(void)
205*35238bceSAndroid Build Coastguard Worker {
206*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!m_executor);
207*35238bceSAndroid Build Coastguard Worker
208*35238bceSAndroid Build Coastguard Worker m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec);
209*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << m_executor;
210*35238bceSAndroid Build Coastguard Worker
211*35238bceSAndroid Build Coastguard Worker if (!m_executor->isOk())
212*35238bceSAndroid Build Coastguard Worker throw tcu::TestError("Compile failed");
213*35238bceSAndroid Build Coastguard Worker }
214*35238bceSAndroid Build Coastguard Worker
deinit(void)215*35238bceSAndroid Build Coastguard Worker void CommonFunctionCase::deinit(void)
216*35238bceSAndroid Build Coastguard Worker {
217*35238bceSAndroid Build Coastguard Worker delete m_executor;
218*35238bceSAndroid Build Coastguard Worker m_executor = DE_NULL;
219*35238bceSAndroid Build Coastguard Worker }
220*35238bceSAndroid Build Coastguard Worker
getScalarSizes(const vector<Symbol> & symbols)221*35238bceSAndroid Build Coastguard Worker static vector<int> getScalarSizes(const vector<Symbol> &symbols)
222*35238bceSAndroid Build Coastguard Worker {
223*35238bceSAndroid Build Coastguard Worker vector<int> sizes(symbols.size());
224*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < (int)symbols.size(); ++ndx)
225*35238bceSAndroid Build Coastguard Worker sizes[ndx] = symbols[ndx].varType.getScalarSize();
226*35238bceSAndroid Build Coastguard Worker return sizes;
227*35238bceSAndroid Build Coastguard Worker }
228*35238bceSAndroid Build Coastguard Worker
computeTotalScalarSize(const vector<Symbol> & symbols)229*35238bceSAndroid Build Coastguard Worker static int computeTotalScalarSize(const vector<Symbol> &symbols)
230*35238bceSAndroid Build Coastguard Worker {
231*35238bceSAndroid Build Coastguard Worker int totalSize = 0;
232*35238bceSAndroid Build Coastguard Worker for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym)
233*35238bceSAndroid Build Coastguard Worker totalSize += sym->varType.getScalarSize();
234*35238bceSAndroid Build Coastguard Worker return totalSize;
235*35238bceSAndroid Build Coastguard Worker }
236*35238bceSAndroid Build Coastguard Worker
getInputOutputPointers(const vector<Symbol> & symbols,vector<uint32_t> & data,const int numValues)237*35238bceSAndroid Build Coastguard Worker static vector<void *> getInputOutputPointers(const vector<Symbol> &symbols, vector<uint32_t> &data, const int numValues)
238*35238bceSAndroid Build Coastguard Worker {
239*35238bceSAndroid Build Coastguard Worker vector<void *> pointers(symbols.size());
240*35238bceSAndroid Build Coastguard Worker int curScalarOffset = 0;
241*35238bceSAndroid Build Coastguard Worker
242*35238bceSAndroid Build Coastguard Worker for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx)
243*35238bceSAndroid Build Coastguard Worker {
244*35238bceSAndroid Build Coastguard Worker const Symbol &var = symbols[varNdx];
245*35238bceSAndroid Build Coastguard Worker const int scalarSize = var.varType.getScalarSize();
246*35238bceSAndroid Build Coastguard Worker
247*35238bceSAndroid Build Coastguard Worker // Uses planar layout as input/output specs do not support strides.
248*35238bceSAndroid Build Coastguard Worker pointers[varNdx] = &data[curScalarOffset];
249*35238bceSAndroid Build Coastguard Worker curScalarOffset += scalarSize * numValues;
250*35238bceSAndroid Build Coastguard Worker }
251*35238bceSAndroid Build Coastguard Worker
252*35238bceSAndroid Build Coastguard Worker DE_ASSERT(curScalarOffset == (int)data.size());
253*35238bceSAndroid Build Coastguard Worker
254*35238bceSAndroid Build Coastguard Worker return pointers;
255*35238bceSAndroid Build Coastguard Worker }
256*35238bceSAndroid Build Coastguard Worker
257*35238bceSAndroid Build Coastguard Worker // \todo [2013-08-08 pyry] Make generic utility and move to glu?
258*35238bceSAndroid Build Coastguard Worker
259*35238bceSAndroid Build Coastguard Worker struct HexFloat
260*35238bceSAndroid Build Coastguard Worker {
261*35238bceSAndroid Build Coastguard Worker const float value;
HexFloatdeqp::gles3::Functional::HexFloat262*35238bceSAndroid Build Coastguard Worker HexFloat(const float value_) : value(value_)
263*35238bceSAndroid Build Coastguard Worker {
264*35238bceSAndroid Build Coastguard Worker }
265*35238bceSAndroid Build Coastguard Worker };
266*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & str,const HexFloat & v)267*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const HexFloat &v)
268*35238bceSAndroid Build Coastguard Worker {
269*35238bceSAndroid Build Coastguard Worker return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits());
270*35238bceSAndroid Build Coastguard Worker }
271*35238bceSAndroid Build Coastguard Worker
272*35238bceSAndroid Build Coastguard Worker struct HexBool
273*35238bceSAndroid Build Coastguard Worker {
274*35238bceSAndroid Build Coastguard Worker const uint32_t value;
HexBooldeqp::gles3::Functional::HexBool275*35238bceSAndroid Build Coastguard Worker HexBool(const uint32_t value_) : value(value_)
276*35238bceSAndroid Build Coastguard Worker {
277*35238bceSAndroid Build Coastguard Worker }
278*35238bceSAndroid Build Coastguard Worker };
279*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & str,const HexBool & v)280*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const HexBool &v)
281*35238bceSAndroid Build Coastguard Worker {
282*35238bceSAndroid Build Coastguard Worker return str << (v.value ? "true" : "false") << " / " << tcu::toHex(v.value);
283*35238bceSAndroid Build Coastguard Worker }
284*35238bceSAndroid Build Coastguard Worker
285*35238bceSAndroid Build Coastguard Worker struct VarValue
286*35238bceSAndroid Build Coastguard Worker {
287*35238bceSAndroid Build Coastguard Worker const glu::VarType &type;
288*35238bceSAndroid Build Coastguard Worker const void *value;
289*35238bceSAndroid Build Coastguard Worker
VarValuedeqp::gles3::Functional::VarValue290*35238bceSAndroid Build Coastguard Worker VarValue(const glu::VarType &type_, const void *value_) : type(type_), value(value_)
291*35238bceSAndroid Build Coastguard Worker {
292*35238bceSAndroid Build Coastguard Worker }
293*35238bceSAndroid Build Coastguard Worker };
294*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & str,const VarValue & varValue)295*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const VarValue &varValue)
296*35238bceSAndroid Build Coastguard Worker {
297*35238bceSAndroid Build Coastguard Worker DE_ASSERT(varValue.type.isBasicType());
298*35238bceSAndroid Build Coastguard Worker
299*35238bceSAndroid Build Coastguard Worker const glu::DataType basicType = varValue.type.getBasicType();
300*35238bceSAndroid Build Coastguard Worker const glu::DataType scalarType = glu::getDataTypeScalarType(basicType);
301*35238bceSAndroid Build Coastguard Worker const int numComponents = glu::getDataTypeScalarSize(basicType);
302*35238bceSAndroid Build Coastguard Worker
303*35238bceSAndroid Build Coastguard Worker if (numComponents > 1)
304*35238bceSAndroid Build Coastguard Worker str << glu::getDataTypeName(basicType) << "(";
305*35238bceSAndroid Build Coastguard Worker
306*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < numComponents; compNdx++)
307*35238bceSAndroid Build Coastguard Worker {
308*35238bceSAndroid Build Coastguard Worker if (compNdx != 0)
309*35238bceSAndroid Build Coastguard Worker str << ", ";
310*35238bceSAndroid Build Coastguard Worker
311*35238bceSAndroid Build Coastguard Worker switch (scalarType)
312*35238bceSAndroid Build Coastguard Worker {
313*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT:
314*35238bceSAndroid Build Coastguard Worker str << HexFloat(((const float *)varValue.value)[compNdx]);
315*35238bceSAndroid Build Coastguard Worker break;
316*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT:
317*35238bceSAndroid Build Coastguard Worker str << ((const int32_t *)varValue.value)[compNdx];
318*35238bceSAndroid Build Coastguard Worker break;
319*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT:
320*35238bceSAndroid Build Coastguard Worker str << tcu::toHex(((const uint32_t *)varValue.value)[compNdx]);
321*35238bceSAndroid Build Coastguard Worker break;
322*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL:
323*35238bceSAndroid Build Coastguard Worker str << HexBool(((const uint32_t *)varValue.value)[compNdx]);
324*35238bceSAndroid Build Coastguard Worker break;
325*35238bceSAndroid Build Coastguard Worker
326*35238bceSAndroid Build Coastguard Worker default:
327*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
328*35238bceSAndroid Build Coastguard Worker }
329*35238bceSAndroid Build Coastguard Worker }
330*35238bceSAndroid Build Coastguard Worker
331*35238bceSAndroid Build Coastguard Worker if (numComponents > 1)
332*35238bceSAndroid Build Coastguard Worker str << ")";
333*35238bceSAndroid Build Coastguard Worker
334*35238bceSAndroid Build Coastguard Worker return str;
335*35238bceSAndroid Build Coastguard Worker }
336*35238bceSAndroid Build Coastguard Worker
iterate(void)337*35238bceSAndroid Build Coastguard Worker CommonFunctionCase::IterateResult CommonFunctionCase::iterate(void)
338*35238bceSAndroid Build Coastguard Worker {
339*35238bceSAndroid Build Coastguard Worker const int numInputScalars = computeTotalScalarSize(m_spec.inputs);
340*35238bceSAndroid Build Coastguard Worker const int numOutputScalars = computeTotalScalarSize(m_spec.outputs);
341*35238bceSAndroid Build Coastguard Worker vector<uint32_t> inputData(numInputScalars * m_numValues);
342*35238bceSAndroid Build Coastguard Worker vector<uint32_t> outputData(numOutputScalars * m_numValues);
343*35238bceSAndroid Build Coastguard Worker const vector<void *> inputPointers = getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
344*35238bceSAndroid Build Coastguard Worker const vector<void *> outputPointers = getInputOutputPointers(m_spec.outputs, outputData, m_numValues);
345*35238bceSAndroid Build Coastguard Worker
346*35238bceSAndroid Build Coastguard Worker // Initialize input data.
347*35238bceSAndroid Build Coastguard Worker getInputValues(m_numValues, &inputPointers[0]);
348*35238bceSAndroid Build Coastguard Worker
349*35238bceSAndroid Build Coastguard Worker // Execute shader.
350*35238bceSAndroid Build Coastguard Worker m_executor->useProgram();
351*35238bceSAndroid Build Coastguard Worker m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]);
352*35238bceSAndroid Build Coastguard Worker
353*35238bceSAndroid Build Coastguard Worker // Compare results.
354*35238bceSAndroid Build Coastguard Worker {
355*35238bceSAndroid Build Coastguard Worker const vector<int> inScalarSizes = getScalarSizes(m_spec.inputs);
356*35238bceSAndroid Build Coastguard Worker const vector<int> outScalarSizes = getScalarSizes(m_spec.outputs);
357*35238bceSAndroid Build Coastguard Worker vector<void *> curInputPtr(inputPointers.size());
358*35238bceSAndroid Build Coastguard Worker vector<void *> curOutputPtr(outputPointers.size());
359*35238bceSAndroid Build Coastguard Worker int numFailed = 0;
360*35238bceSAndroid Build Coastguard Worker
361*35238bceSAndroid Build Coastguard Worker for (int valNdx = 0; valNdx < m_numValues; valNdx++)
362*35238bceSAndroid Build Coastguard Worker {
363*35238bceSAndroid Build Coastguard Worker // Set up pointers for comparison.
364*35238bceSAndroid Build Coastguard Worker for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
365*35238bceSAndroid Build Coastguard Worker curInputPtr[inNdx] = (uint32_t *)inputPointers[inNdx] + inScalarSizes[inNdx] * valNdx;
366*35238bceSAndroid Build Coastguard Worker
367*35238bceSAndroid Build Coastguard Worker for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
368*35238bceSAndroid Build Coastguard Worker curOutputPtr[outNdx] = (uint32_t *)outputPointers[outNdx] + outScalarSizes[outNdx] * valNdx;
369*35238bceSAndroid Build Coastguard Worker
370*35238bceSAndroid Build Coastguard Worker if (!compare(&curInputPtr[0], &curOutputPtr[0]))
371*35238bceSAndroid Build Coastguard Worker {
372*35238bceSAndroid Build Coastguard Worker // \todo [2013-08-08 pyry] We probably want to log reference value as well?
373*35238bceSAndroid Build Coastguard Worker
374*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n "
375*35238bceSAndroid Build Coastguard Worker << m_failMsg.str() << TestLog::EndMessage;
376*35238bceSAndroid Build Coastguard Worker
377*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << " inputs:" << TestLog::EndMessage;
378*35238bceSAndroid Build Coastguard Worker for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
379*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << " " << m_spec.inputs[inNdx].name << " = "
380*35238bceSAndroid Build Coastguard Worker << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
381*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
382*35238bceSAndroid Build Coastguard Worker
383*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << " outputs:" << TestLog::EndMessage;
384*35238bceSAndroid Build Coastguard Worker for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
385*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << " " << m_spec.outputs[outNdx].name << " = "
386*35238bceSAndroid Build Coastguard Worker << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
387*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
388*35238bceSAndroid Build Coastguard Worker
389*35238bceSAndroid Build Coastguard Worker m_failMsg.str("");
390*35238bceSAndroid Build Coastguard Worker m_failMsg.clear();
391*35238bceSAndroid Build Coastguard Worker numFailed += 1;
392*35238bceSAndroid Build Coastguard Worker }
393*35238bceSAndroid Build Coastguard Worker }
394*35238bceSAndroid Build Coastguard Worker
395*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed"
396*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
397*35238bceSAndroid Build Coastguard Worker
398*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
399*35238bceSAndroid Build Coastguard Worker numFailed == 0 ? "Pass" : "Result comparison failed");
400*35238bceSAndroid Build Coastguard Worker }
401*35238bceSAndroid Build Coastguard Worker
402*35238bceSAndroid Build Coastguard Worker return STOP;
403*35238bceSAndroid Build Coastguard Worker }
404*35238bceSAndroid Build Coastguard Worker
getCommonFuncCaseName(glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)405*35238bceSAndroid Build Coastguard Worker static std::string getCommonFuncCaseName(glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
406*35238bceSAndroid Build Coastguard Worker {
407*35238bceSAndroid Build Coastguard Worker return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType);
408*35238bceSAndroid Build Coastguard Worker }
409*35238bceSAndroid Build Coastguard Worker
410*35238bceSAndroid Build Coastguard Worker class AbsCase : public CommonFunctionCase
411*35238bceSAndroid Build Coastguard Worker {
412*35238bceSAndroid Build Coastguard Worker public:
AbsCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)413*35238bceSAndroid Build Coastguard Worker AbsCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
414*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "abs", shaderType)
415*35238bceSAndroid Build Coastguard Worker {
416*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
417*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
418*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = abs(in0);";
419*35238bceSAndroid Build Coastguard Worker }
420*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const421*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
422*35238bceSAndroid Build Coastguard Worker {
423*35238bceSAndroid Build Coastguard Worker const Vec2 floatRanges[] = {
424*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
425*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
426*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
427*35238bceSAndroid Build Coastguard Worker };
428*35238bceSAndroid Build Coastguard Worker const IVec2 intRanges[] = {IVec2(-(1 << 7) + 1, (1 << 7) - 1), IVec2(-(1 << 15) + 1, (1 << 15) - 1),
429*35238bceSAndroid Build Coastguard Worker IVec2(0x80000001, 0x7fffffff)};
430*35238bceSAndroid Build Coastguard Worker
431*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0x235facu);
432*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
433*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
434*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
435*35238bceSAndroid Build Coastguard Worker
436*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeFloatOrVec(type))
437*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), values[0],
438*35238bceSAndroid Build Coastguard Worker numValues * scalarSize);
439*35238bceSAndroid Build Coastguard Worker else
440*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), values[0],
441*35238bceSAndroid Build Coastguard Worker numValues * scalarSize);
442*35238bceSAndroid Build Coastguard Worker }
443*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)444*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
445*35238bceSAndroid Build Coastguard Worker {
446*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
447*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
448*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
449*35238bceSAndroid Build Coastguard Worker
450*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeFloatOrVec(type))
451*35238bceSAndroid Build Coastguard Worker {
452*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
453*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = (1u << (23 - mantissaBits)) - 1u;
454*35238bceSAndroid Build Coastguard Worker
455*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
456*35238bceSAndroid Build Coastguard Worker {
457*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
458*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
459*35238bceSAndroid Build Coastguard Worker const float ref0 = de::abs(in0);
460*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff0 = getUlpDiff(out0, ref0);
461*35238bceSAndroid Build Coastguard Worker
462*35238bceSAndroid Build Coastguard Worker if (ulpDiff0 > maxUlpDiff)
463*35238bceSAndroid Build Coastguard Worker {
464*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold "
465*35238bceSAndroid Build Coastguard Worker << maxUlpDiff << ", got ULP diff " << ulpDiff0;
466*35238bceSAndroid Build Coastguard Worker return false;
467*35238bceSAndroid Build Coastguard Worker }
468*35238bceSAndroid Build Coastguard Worker }
469*35238bceSAndroid Build Coastguard Worker }
470*35238bceSAndroid Build Coastguard Worker else
471*35238bceSAndroid Build Coastguard Worker {
472*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
473*35238bceSAndroid Build Coastguard Worker {
474*35238bceSAndroid Build Coastguard Worker const int in0 = ((const int *)inputs[0])[compNdx];
475*35238bceSAndroid Build Coastguard Worker const int out0 = ((const int *)outputs[0])[compNdx];
476*35238bceSAndroid Build Coastguard Worker const int ref0 = de::abs(in0);
477*35238bceSAndroid Build Coastguard Worker
478*35238bceSAndroid Build Coastguard Worker if (out0 != ref0)
479*35238bceSAndroid Build Coastguard Worker {
480*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << ref0;
481*35238bceSAndroid Build Coastguard Worker return false;
482*35238bceSAndroid Build Coastguard Worker }
483*35238bceSAndroid Build Coastguard Worker }
484*35238bceSAndroid Build Coastguard Worker }
485*35238bceSAndroid Build Coastguard Worker
486*35238bceSAndroid Build Coastguard Worker return true;
487*35238bceSAndroid Build Coastguard Worker }
488*35238bceSAndroid Build Coastguard Worker };
489*35238bceSAndroid Build Coastguard Worker
490*35238bceSAndroid Build Coastguard Worker class SignCase : public CommonFunctionCase
491*35238bceSAndroid Build Coastguard Worker {
492*35238bceSAndroid Build Coastguard Worker public:
SignCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)493*35238bceSAndroid Build Coastguard Worker SignCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
494*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "sign",
495*35238bceSAndroid Build Coastguard Worker shaderType)
496*35238bceSAndroid Build Coastguard Worker {
497*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
498*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
499*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = sign(in0);";
500*35238bceSAndroid Build Coastguard Worker }
501*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const502*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
503*35238bceSAndroid Build Coastguard Worker {
504*35238bceSAndroid Build Coastguard Worker const Vec2 floatRanges[] = {
505*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
506*35238bceSAndroid Build Coastguard Worker Vec2(-1e4f, 1e4f), // mediump - note: may end up as inf
507*35238bceSAndroid Build Coastguard Worker Vec2(-1e8f, 1e8f) // highp - note: may end up as inf
508*35238bceSAndroid Build Coastguard Worker };
509*35238bceSAndroid Build Coastguard Worker const IVec2 intRanges[] = {IVec2(-(1 << 7), (1 << 7) - 1), IVec2(-(1 << 15), (1 << 15) - 1),
510*35238bceSAndroid Build Coastguard Worker IVec2(0x80000000, 0x7fffffff)};
511*35238bceSAndroid Build Coastguard Worker
512*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0x324u);
513*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
514*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
515*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
516*35238bceSAndroid Build Coastguard Worker
517*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeFloatOrVec(type))
518*35238bceSAndroid Build Coastguard Worker {
519*35238bceSAndroid Build Coastguard Worker // Special cases.
520*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0], (float *)values[0] + scalarSize, +1.0f);
521*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0] + scalarSize * 1, (float *)values[0] + scalarSize * 2, -1.0f);
522*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0] + scalarSize * 2, (float *)values[0] + scalarSize * 3, 0.0f);
523*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(),
524*35238bceSAndroid Build Coastguard Worker (float *)values[0] + scalarSize * 3, (numValues - 3) * scalarSize);
525*35238bceSAndroid Build Coastguard Worker }
526*35238bceSAndroid Build Coastguard Worker else
527*35238bceSAndroid Build Coastguard Worker {
528*35238bceSAndroid Build Coastguard Worker std::fill((int *)values[0], (int *)values[0] + scalarSize, +1);
529*35238bceSAndroid Build Coastguard Worker std::fill((int *)values[0] + scalarSize * 1, (int *)values[0] + scalarSize * 2, -1);
530*35238bceSAndroid Build Coastguard Worker std::fill((int *)values[0] + scalarSize * 2, (int *)values[0] + scalarSize * 3, 0);
531*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(),
532*35238bceSAndroid Build Coastguard Worker (int *)values[0] + scalarSize * 3, (numValues - 3) * scalarSize);
533*35238bceSAndroid Build Coastguard Worker }
534*35238bceSAndroid Build Coastguard Worker }
535*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)536*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
537*35238bceSAndroid Build Coastguard Worker {
538*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
539*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
540*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
541*35238bceSAndroid Build Coastguard Worker
542*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeFloatOrVec(type))
543*35238bceSAndroid Build Coastguard Worker {
544*35238bceSAndroid Build Coastguard Worker // Both highp and mediump should be able to represent -1, 0, and +1 exactly
545*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff =
546*35238bceSAndroid Build Coastguard Worker precision == glu::PRECISION_LOWP ? getMaxUlpDiffFromBits(getMinMantissaBits(precision)) : 0;
547*35238bceSAndroid Build Coastguard Worker
548*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
549*35238bceSAndroid Build Coastguard Worker {
550*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
551*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
552*35238bceSAndroid Build Coastguard Worker const float ref0 = in0 < 0.0f ? -1.0f : in0 > 0.0f ? +1.0f : 0.0f;
553*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff0 = getUlpDiff(out0, ref0);
554*35238bceSAndroid Build Coastguard Worker
555*35238bceSAndroid Build Coastguard Worker if (ulpDiff0 > maxUlpDiff)
556*35238bceSAndroid Build Coastguard Worker {
557*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold "
558*35238bceSAndroid Build Coastguard Worker << maxUlpDiff << ", got ULP diff " << ulpDiff0;
559*35238bceSAndroid Build Coastguard Worker return false;
560*35238bceSAndroid Build Coastguard Worker }
561*35238bceSAndroid Build Coastguard Worker }
562*35238bceSAndroid Build Coastguard Worker }
563*35238bceSAndroid Build Coastguard Worker else
564*35238bceSAndroid Build Coastguard Worker {
565*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
566*35238bceSAndroid Build Coastguard Worker {
567*35238bceSAndroid Build Coastguard Worker const int in0 = ((const int *)inputs[0])[compNdx];
568*35238bceSAndroid Build Coastguard Worker const int out0 = ((const int *)outputs[0])[compNdx];
569*35238bceSAndroid Build Coastguard Worker const int ref0 = in0 < 0 ? -1 : in0 > 0 ? +1 : 0;
570*35238bceSAndroid Build Coastguard Worker
571*35238bceSAndroid Build Coastguard Worker if (out0 != ref0)
572*35238bceSAndroid Build Coastguard Worker {
573*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << ref0;
574*35238bceSAndroid Build Coastguard Worker return false;
575*35238bceSAndroid Build Coastguard Worker }
576*35238bceSAndroid Build Coastguard Worker }
577*35238bceSAndroid Build Coastguard Worker }
578*35238bceSAndroid Build Coastguard Worker
579*35238bceSAndroid Build Coastguard Worker return true;
580*35238bceSAndroid Build Coastguard Worker }
581*35238bceSAndroid Build Coastguard Worker };
582*35238bceSAndroid Build Coastguard Worker
roundEven(float v)583*35238bceSAndroid Build Coastguard Worker static float roundEven(float v)
584*35238bceSAndroid Build Coastguard Worker {
585*35238bceSAndroid Build Coastguard Worker const float q = deFloatFrac(v);
586*35238bceSAndroid Build Coastguard Worker const int truncated = int(v - q);
587*35238bceSAndroid Build Coastguard Worker const int rounded = (q > 0.5f) ? (truncated + 1) : // Rounded up
588*35238bceSAndroid Build Coastguard Worker (q == 0.5f && (truncated % 2 != 0)) ? (truncated + 1) : // Round to nearest even at 0.5
589*35238bceSAndroid Build Coastguard Worker truncated; // Rounded down
590*35238bceSAndroid Build Coastguard Worker
591*35238bceSAndroid Build Coastguard Worker return float(rounded);
592*35238bceSAndroid Build Coastguard Worker }
593*35238bceSAndroid Build Coastguard Worker
594*35238bceSAndroid Build Coastguard Worker class RoundEvenCase : public CommonFunctionCase
595*35238bceSAndroid Build Coastguard Worker {
596*35238bceSAndroid Build Coastguard Worker public:
RoundEvenCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)597*35238bceSAndroid Build Coastguard Worker RoundEvenCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
598*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "roundEven",
599*35238bceSAndroid Build Coastguard Worker shaderType)
600*35238bceSAndroid Build Coastguard Worker {
601*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
602*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
603*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = roundEven(in0);";
604*35238bceSAndroid Build Coastguard Worker }
605*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const606*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
607*35238bceSAndroid Build Coastguard Worker {
608*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
609*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
610*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
611*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
612*35238bceSAndroid Build Coastguard Worker };
613*35238bceSAndroid Build Coastguard Worker
614*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
615*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
616*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
617*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
618*35238bceSAndroid Build Coastguard Worker int numSpecialCases = 0;
619*35238bceSAndroid Build Coastguard Worker
620*35238bceSAndroid Build Coastguard Worker // Special cases.
621*35238bceSAndroid Build Coastguard Worker if (precision != glu::PRECISION_LOWP)
622*35238bceSAndroid Build Coastguard Worker {
623*35238bceSAndroid Build Coastguard Worker DE_ASSERT(numValues >= 20);
624*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < 20; ndx++)
625*35238bceSAndroid Build Coastguard Worker {
626*35238bceSAndroid Build Coastguard Worker const float v = de::clamp(float(ndx) - 10.5f, ranges[precision].x(), ranges[precision].y());
627*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0], (float *)values[0] + scalarSize, v);
628*35238bceSAndroid Build Coastguard Worker numSpecialCases += 1;
629*35238bceSAndroid Build Coastguard Worker }
630*35238bceSAndroid Build Coastguard Worker }
631*35238bceSAndroid Build Coastguard Worker
632*35238bceSAndroid Build Coastguard Worker // Random cases.
633*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(),
634*35238bceSAndroid Build Coastguard Worker (float *)values[0] + numSpecialCases * scalarSize,
635*35238bceSAndroid Build Coastguard Worker (numValues - numSpecialCases) * scalarSize);
636*35238bceSAndroid Build Coastguard Worker
637*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
638*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
639*35238bceSAndroid Build Coastguard Worker {
640*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
641*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
642*35238bceSAndroid Build Coastguard Worker }
643*35238bceSAndroid Build Coastguard Worker }
644*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)645*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
646*35238bceSAndroid Build Coastguard Worker {
647*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
648*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
649*35238bceSAndroid Build Coastguard Worker const bool hasSignedZero = supportsSignedZero(precision);
650*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
651*35238bceSAndroid Build Coastguard Worker
652*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
653*35238bceSAndroid Build Coastguard Worker {
654*35238bceSAndroid Build Coastguard Worker // Require exact rounding result.
655*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
656*35238bceSAndroid Build Coastguard Worker {
657*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
658*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
659*35238bceSAndroid Build Coastguard Worker const float ref = roundEven(in0);
660*35238bceSAndroid Build Coastguard Worker
661*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
662*35238bceSAndroid Build Coastguard Worker
663*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
664*35238bceSAndroid Build Coastguard Worker {
665*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
666*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
667*35238bceSAndroid Build Coastguard Worker return false;
668*35238bceSAndroid Build Coastguard Worker }
669*35238bceSAndroid Build Coastguard Worker }
670*35238bceSAndroid Build Coastguard Worker }
671*35238bceSAndroid Build Coastguard Worker else
672*35238bceSAndroid Build Coastguard Worker {
673*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
674*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
675*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
676*35238bceSAndroid Build Coastguard Worker
677*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
678*35238bceSAndroid Build Coastguard Worker {
679*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
680*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
681*35238bceSAndroid Build Coastguard Worker const int minRes = int(roundEven(in0 - eps));
682*35238bceSAndroid Build Coastguard Worker const int maxRes = int(roundEven(in0 + eps));
683*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
684*35238bceSAndroid Build Coastguard Worker
685*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
686*35238bceSAndroid Build Coastguard Worker {
687*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
688*35238bceSAndroid Build Coastguard Worker
689*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
690*35238bceSAndroid Build Coastguard Worker {
691*35238bceSAndroid Build Coastguard Worker anyOk = true;
692*35238bceSAndroid Build Coastguard Worker break;
693*35238bceSAndroid Build Coastguard Worker }
694*35238bceSAndroid Build Coastguard Worker }
695*35238bceSAndroid Build Coastguard Worker
696*35238bceSAndroid Build Coastguard Worker if (!anyOk)
697*35238bceSAndroid Build Coastguard Worker {
698*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
699*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
700*35238bceSAndroid Build Coastguard Worker return false;
701*35238bceSAndroid Build Coastguard Worker }
702*35238bceSAndroid Build Coastguard Worker }
703*35238bceSAndroid Build Coastguard Worker }
704*35238bceSAndroid Build Coastguard Worker
705*35238bceSAndroid Build Coastguard Worker return true;
706*35238bceSAndroid Build Coastguard Worker }
707*35238bceSAndroid Build Coastguard Worker };
708*35238bceSAndroid Build Coastguard Worker
709*35238bceSAndroid Build Coastguard Worker class ModfCase : public CommonFunctionCase
710*35238bceSAndroid Build Coastguard Worker {
711*35238bceSAndroid Build Coastguard Worker public:
ModfCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)712*35238bceSAndroid Build Coastguard Worker ModfCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
713*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "modf",
714*35238bceSAndroid Build Coastguard Worker shaderType)
715*35238bceSAndroid Build Coastguard Worker {
716*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
717*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
718*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out1", glu::VarType(baseType, precision)));
719*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = modf(in0, out1);";
720*35238bceSAndroid Build Coastguard Worker }
721*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const722*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
723*35238bceSAndroid Build Coastguard Worker {
724*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
725*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
726*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
727*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
728*35238bceSAndroid Build Coastguard Worker };
729*35238bceSAndroid Build Coastguard Worker
730*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
731*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
732*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
733*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
734*35238bceSAndroid Build Coastguard Worker
735*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues * scalarSize);
736*35238bceSAndroid Build Coastguard Worker }
737*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)738*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
739*35238bceSAndroid Build Coastguard Worker {
740*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
741*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
742*35238bceSAndroid Build Coastguard Worker const bool hasZeroSign = supportsSignedZero(precision);
743*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
744*35238bceSAndroid Build Coastguard Worker
745*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
746*35238bceSAndroid Build Coastguard Worker
747*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
748*35238bceSAndroid Build Coastguard Worker {
749*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
750*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
751*35238bceSAndroid Build Coastguard Worker const float out1 = ((const float *)outputs[1])[compNdx];
752*35238bceSAndroid Build Coastguard Worker
753*35238bceSAndroid Build Coastguard Worker const float refOut1 = float(int(in0));
754*35238bceSAndroid Build Coastguard Worker const float refOut0 = in0 - refOut1;
755*35238bceSAndroid Build Coastguard Worker
756*35238bceSAndroid Build Coastguard Worker const int bitsLost = precision != glu::PRECISION_HIGHP ? numBitsLostInOp(in0, refOut0) : 0;
757*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(de::max(mantissaBits - bitsLost, 0));
758*35238bceSAndroid Build Coastguard Worker
759*35238bceSAndroid Build Coastguard Worker const float resSum = out0 + out1;
760*35238bceSAndroid Build Coastguard Worker
761*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasZeroSign ? getUlpDiff(resSum, in0) : getUlpDiffIgnoreZeroSign(resSum, in0);
762*35238bceSAndroid Build Coastguard Worker
763*35238bceSAndroid Build Coastguard Worker if (ulpDiff > maxUlpDiff)
764*35238bceSAndroid Build Coastguard Worker {
765*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = (" << HexFloat(refOut0) << ") + (" << HexFloat(refOut1)
766*35238bceSAndroid Build Coastguard Worker << ") = " << HexFloat(in0) << " with ULP threshold " << tcu::toHex(maxUlpDiff)
767*35238bceSAndroid Build Coastguard Worker << ", got ULP diff " << tcu::toHex(ulpDiff);
768*35238bceSAndroid Build Coastguard Worker return false;
769*35238bceSAndroid Build Coastguard Worker }
770*35238bceSAndroid Build Coastguard Worker }
771*35238bceSAndroid Build Coastguard Worker
772*35238bceSAndroid Build Coastguard Worker return true;
773*35238bceSAndroid Build Coastguard Worker }
774*35238bceSAndroid Build Coastguard Worker };
775*35238bceSAndroid Build Coastguard Worker
776*35238bceSAndroid Build Coastguard Worker class IsnanCase : public CommonFunctionCase
777*35238bceSAndroid Build Coastguard Worker {
778*35238bceSAndroid Build Coastguard Worker public:
IsnanCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)779*35238bceSAndroid Build Coastguard Worker IsnanCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
780*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isnan",
781*35238bceSAndroid Build Coastguard Worker shaderType)
782*35238bceSAndroid Build Coastguard Worker {
783*35238bceSAndroid Build Coastguard Worker DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
784*35238bceSAndroid Build Coastguard Worker
785*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
786*35238bceSAndroid Build Coastguard Worker const glu::DataType boolType = vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
787*35238bceSAndroid Build Coastguard Worker
788*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
789*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
790*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = isnan(in0);";
791*35238bceSAndroid Build Coastguard Worker }
792*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const793*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
794*35238bceSAndroid Build Coastguard Worker {
795*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xc2a39fu);
796*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
797*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
798*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
799*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
800*35238bceSAndroid Build Coastguard Worker const uint32_t mantissaMask = ~getMaxUlpDiffFromBits(mantissaBits) & ((1u << 23) - 1u);
801*35238bceSAndroid Build Coastguard Worker
802*35238bceSAndroid Build Coastguard Worker for (int valNdx = 0; valNdx < numValues * scalarSize; valNdx++)
803*35238bceSAndroid Build Coastguard Worker {
804*35238bceSAndroid Build Coastguard Worker const bool isNan = rnd.getFloat() > 0.3f;
805*35238bceSAndroid Build Coastguard Worker const bool isInf = !isNan && rnd.getFloat() > 0.4f;
806*35238bceSAndroid Build Coastguard Worker const uint32_t mantissa = !isInf ? ((1u << 22) | (rnd.getUint32() & mantissaMask)) : 0;
807*35238bceSAndroid Build Coastguard Worker const uint32_t exp = !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
808*35238bceSAndroid Build Coastguard Worker const uint32_t sign = rnd.getUint32() & 0x1u;
809*35238bceSAndroid Build Coastguard Worker const uint32_t value = (sign << 31) | (exp << 23) | mantissa;
810*35238bceSAndroid Build Coastguard Worker
811*35238bceSAndroid Build Coastguard Worker DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
812*35238bceSAndroid Build Coastguard Worker
813*35238bceSAndroid Build Coastguard Worker ((uint32_t *)values[0])[valNdx] = value;
814*35238bceSAndroid Build Coastguard Worker }
815*35238bceSAndroid Build Coastguard Worker }
816*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)817*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
818*35238bceSAndroid Build Coastguard Worker {
819*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
820*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
821*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
822*35238bceSAndroid Build Coastguard Worker
823*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP)
824*35238bceSAndroid Build Coastguard Worker {
825*35238bceSAndroid Build Coastguard Worker // Only highp is required to support inf/nan
826*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
827*35238bceSAndroid Build Coastguard Worker {
828*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
829*35238bceSAndroid Build Coastguard Worker const uint32_t out0 = ((const uint32_t *)outputs[0])[compNdx];
830*35238bceSAndroid Build Coastguard Worker const uint32_t ref = tcu::Float32(in0).isNaN() ? 1u : 0u;
831*35238bceSAndroid Build Coastguard Worker
832*35238bceSAndroid Build Coastguard Worker if (out0 != ref)
833*35238bceSAndroid Build Coastguard Worker {
834*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
835*35238bceSAndroid Build Coastguard Worker return false;
836*35238bceSAndroid Build Coastguard Worker }
837*35238bceSAndroid Build Coastguard Worker }
838*35238bceSAndroid Build Coastguard Worker }
839*35238bceSAndroid Build Coastguard Worker else
840*35238bceSAndroid Build Coastguard Worker {
841*35238bceSAndroid Build Coastguard Worker // Value can be either 0 or 1
842*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
843*35238bceSAndroid Build Coastguard Worker {
844*35238bceSAndroid Build Coastguard Worker const int out0 = ((const int *)outputs[0])[compNdx];
845*35238bceSAndroid Build Coastguard Worker
846*35238bceSAndroid Build Coastguard Worker if (out0 != 0 && out0 != 1)
847*35238bceSAndroid Build Coastguard Worker {
848*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = 0 / 1";
849*35238bceSAndroid Build Coastguard Worker return false;
850*35238bceSAndroid Build Coastguard Worker }
851*35238bceSAndroid Build Coastguard Worker }
852*35238bceSAndroid Build Coastguard Worker }
853*35238bceSAndroid Build Coastguard Worker
854*35238bceSAndroid Build Coastguard Worker return true;
855*35238bceSAndroid Build Coastguard Worker }
856*35238bceSAndroid Build Coastguard Worker };
857*35238bceSAndroid Build Coastguard Worker
858*35238bceSAndroid Build Coastguard Worker class IsinfCase : public CommonFunctionCase
859*35238bceSAndroid Build Coastguard Worker {
860*35238bceSAndroid Build Coastguard Worker public:
IsinfCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)861*35238bceSAndroid Build Coastguard Worker IsinfCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
862*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isinf",
863*35238bceSAndroid Build Coastguard Worker shaderType)
864*35238bceSAndroid Build Coastguard Worker {
865*35238bceSAndroid Build Coastguard Worker DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
866*35238bceSAndroid Build Coastguard Worker
867*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
868*35238bceSAndroid Build Coastguard Worker const glu::DataType boolType = vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
869*35238bceSAndroid Build Coastguard Worker
870*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
871*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
872*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = isinf(in0);";
873*35238bceSAndroid Build Coastguard Worker }
874*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const875*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
876*35238bceSAndroid Build Coastguard Worker {
877*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xc2a39fu);
878*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
879*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
880*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
881*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
882*35238bceSAndroid Build Coastguard Worker const uint32_t mantissaMask = ~getMaxUlpDiffFromBits(mantissaBits) & ((1u << 23) - 1u);
883*35238bceSAndroid Build Coastguard Worker
884*35238bceSAndroid Build Coastguard Worker for (int valNdx = 0; valNdx < numValues * scalarSize; valNdx++)
885*35238bceSAndroid Build Coastguard Worker {
886*35238bceSAndroid Build Coastguard Worker const bool isInf = rnd.getFloat() > 0.3f;
887*35238bceSAndroid Build Coastguard Worker const bool isNan = !isInf && rnd.getFloat() > 0.4f;
888*35238bceSAndroid Build Coastguard Worker const uint32_t mantissa = !isInf ? ((1u << 22) | (rnd.getUint32() & mantissaMask)) : 0;
889*35238bceSAndroid Build Coastguard Worker const uint32_t exp = !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
890*35238bceSAndroid Build Coastguard Worker const uint32_t sign = rnd.getUint32() & 0x1u;
891*35238bceSAndroid Build Coastguard Worker const uint32_t value = (sign << 31) | (exp << 23) | mantissa;
892*35238bceSAndroid Build Coastguard Worker
893*35238bceSAndroid Build Coastguard Worker DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
894*35238bceSAndroid Build Coastguard Worker
895*35238bceSAndroid Build Coastguard Worker ((uint32_t *)values[0])[valNdx] = value;
896*35238bceSAndroid Build Coastguard Worker }
897*35238bceSAndroid Build Coastguard Worker }
898*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)899*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
900*35238bceSAndroid Build Coastguard Worker {
901*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
902*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
903*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
904*35238bceSAndroid Build Coastguard Worker
905*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP)
906*35238bceSAndroid Build Coastguard Worker {
907*35238bceSAndroid Build Coastguard Worker // Only highp is required to support inf/nan
908*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
909*35238bceSAndroid Build Coastguard Worker {
910*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
911*35238bceSAndroid Build Coastguard Worker const uint32_t out0 = ((const uint32_t *)outputs[0])[compNdx];
912*35238bceSAndroid Build Coastguard Worker const uint32_t ref = tcu::Float32(in0).isInf() ? 1u : 0u;
913*35238bceSAndroid Build Coastguard Worker
914*35238bceSAndroid Build Coastguard Worker if (out0 != ref)
915*35238bceSAndroid Build Coastguard Worker {
916*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
917*35238bceSAndroid Build Coastguard Worker return false;
918*35238bceSAndroid Build Coastguard Worker }
919*35238bceSAndroid Build Coastguard Worker }
920*35238bceSAndroid Build Coastguard Worker }
921*35238bceSAndroid Build Coastguard Worker else
922*35238bceSAndroid Build Coastguard Worker {
923*35238bceSAndroid Build Coastguard Worker // Value can be either 0 or 1
924*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
925*35238bceSAndroid Build Coastguard Worker {
926*35238bceSAndroid Build Coastguard Worker const int out0 = ((const int *)outputs[0])[compNdx];
927*35238bceSAndroid Build Coastguard Worker
928*35238bceSAndroid Build Coastguard Worker if (out0 != 0 && out0 != 1)
929*35238bceSAndroid Build Coastguard Worker {
930*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = 0 / 1";
931*35238bceSAndroid Build Coastguard Worker return false;
932*35238bceSAndroid Build Coastguard Worker }
933*35238bceSAndroid Build Coastguard Worker }
934*35238bceSAndroid Build Coastguard Worker }
935*35238bceSAndroid Build Coastguard Worker
936*35238bceSAndroid Build Coastguard Worker return true;
937*35238bceSAndroid Build Coastguard Worker }
938*35238bceSAndroid Build Coastguard Worker };
939*35238bceSAndroid Build Coastguard Worker
940*35238bceSAndroid Build Coastguard Worker class FloatBitsToUintIntCase : public CommonFunctionCase
941*35238bceSAndroid Build Coastguard Worker {
942*35238bceSAndroid Build Coastguard Worker public:
FloatBitsToUintIntCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType,bool outIsSigned)943*35238bceSAndroid Build Coastguard Worker FloatBitsToUintIntCase(Context &context, glu::DataType baseType, glu::Precision precision,
944*35238bceSAndroid Build Coastguard Worker glu::ShaderType shaderType, bool outIsSigned)
945*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(),
946*35238bceSAndroid Build Coastguard Worker outIsSigned ? "floatBitsToInt" : "floatBitsToUint", shaderType)
947*35238bceSAndroid Build Coastguard Worker {
948*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
949*35238bceSAndroid Build Coastguard Worker const glu::DataType intType = outIsSigned ? (vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT) :
950*35238bceSAndroid Build Coastguard Worker (vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT);
951*35238bceSAndroid Build Coastguard Worker
952*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
953*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(intType, glu::PRECISION_HIGHP)));
954*35238bceSAndroid Build Coastguard Worker m_spec.source = outIsSigned ? "out0 = floatBitsToInt(in0);" : "out0 = floatBitsToUint(in0);";
955*35238bceSAndroid Build Coastguard Worker }
956*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const957*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
958*35238bceSAndroid Build Coastguard Worker {
959*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
960*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
961*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
962*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
963*35238bceSAndroid Build Coastguard Worker };
964*35238bceSAndroid Build Coastguard Worker
965*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0x2790au);
966*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
967*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
968*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
969*35238bceSAndroid Build Coastguard Worker
970*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues * scalarSize);
971*35238bceSAndroid Build Coastguard Worker }
972*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)973*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
974*35238bceSAndroid Build Coastguard Worker {
975*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
976*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
977*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
978*35238bceSAndroid Build Coastguard Worker
979*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
980*35238bceSAndroid Build Coastguard Worker const int maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits);
981*35238bceSAndroid Build Coastguard Worker
982*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
983*35238bceSAndroid Build Coastguard Worker {
984*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
985*35238bceSAndroid Build Coastguard Worker const uint32_t out0 = ((const uint32_t *)outputs[0])[compNdx];
986*35238bceSAndroid Build Coastguard Worker const uint32_t refOut0 = tcu::Float32(in0).bits();
987*35238bceSAndroid Build Coastguard Worker const int ulpDiff = de::abs((int)out0 - (int)refOut0);
988*35238bceSAndroid Build Coastguard Worker
989*35238bceSAndroid Build Coastguard Worker if (ulpDiff > maxUlpDiff)
990*35238bceSAndroid Build Coastguard Worker {
991*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(refOut0) << " with threshold "
992*35238bceSAndroid Build Coastguard Worker << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
993*35238bceSAndroid Build Coastguard Worker return false;
994*35238bceSAndroid Build Coastguard Worker }
995*35238bceSAndroid Build Coastguard Worker }
996*35238bceSAndroid Build Coastguard Worker
997*35238bceSAndroid Build Coastguard Worker return true;
998*35238bceSAndroid Build Coastguard Worker }
999*35238bceSAndroid Build Coastguard Worker };
1000*35238bceSAndroid Build Coastguard Worker
1001*35238bceSAndroid Build Coastguard Worker class FloatBitsToIntCase : public FloatBitsToUintIntCase
1002*35238bceSAndroid Build Coastguard Worker {
1003*35238bceSAndroid Build Coastguard Worker public:
FloatBitsToIntCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1004*35238bceSAndroid Build Coastguard Worker FloatBitsToIntCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1005*35238bceSAndroid Build Coastguard Worker : FloatBitsToUintIntCase(context, baseType, precision, shaderType, true)
1006*35238bceSAndroid Build Coastguard Worker {
1007*35238bceSAndroid Build Coastguard Worker }
1008*35238bceSAndroid Build Coastguard Worker };
1009*35238bceSAndroid Build Coastguard Worker
1010*35238bceSAndroid Build Coastguard Worker class FloatBitsToUintCase : public FloatBitsToUintIntCase
1011*35238bceSAndroid Build Coastguard Worker {
1012*35238bceSAndroid Build Coastguard Worker public:
FloatBitsToUintCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1013*35238bceSAndroid Build Coastguard Worker FloatBitsToUintCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1014*35238bceSAndroid Build Coastguard Worker : FloatBitsToUintIntCase(context, baseType, precision, shaderType, false)
1015*35238bceSAndroid Build Coastguard Worker {
1016*35238bceSAndroid Build Coastguard Worker }
1017*35238bceSAndroid Build Coastguard Worker };
1018*35238bceSAndroid Build Coastguard Worker
1019*35238bceSAndroid Build Coastguard Worker class BitsToFloatCase : public CommonFunctionCase
1020*35238bceSAndroid Build Coastguard Worker {
1021*35238bceSAndroid Build Coastguard Worker public:
BitsToFloatCase(Context & context,glu::DataType baseType,glu::ShaderType shaderType)1022*35238bceSAndroid Build Coastguard Worker BitsToFloatCase(Context &context, glu::DataType baseType, glu::ShaderType shaderType)
1023*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, glu::PRECISION_HIGHP, shaderType).c_str(),
1024*35238bceSAndroid Build Coastguard Worker glu::isDataTypeIntOrIVec(baseType) ? "intBitsToFloat" : "uintBitsToFloat", shaderType)
1025*35238bceSAndroid Build Coastguard Worker {
1026*35238bceSAndroid Build Coastguard Worker const bool inIsSigned = glu::isDataTypeIntOrIVec(baseType);
1027*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
1028*35238bceSAndroid Build Coastguard Worker const glu::DataType floatType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
1029*35238bceSAndroid Build Coastguard Worker
1030*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
1031*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(floatType, glu::PRECISION_HIGHP)));
1032*35238bceSAndroid Build Coastguard Worker m_spec.source = inIsSigned ? "out0 = intBitsToFloat(in0);" : "out0 = uintBitsToFloat(in0);";
1033*35238bceSAndroid Build Coastguard Worker }
1034*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1035*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1036*35238bceSAndroid Build Coastguard Worker {
1037*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xbbb225u);
1038*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1039*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1040*35238bceSAndroid Build Coastguard Worker const Vec2 range(-1e8f, +1e8f);
1041*35238bceSAndroid Build Coastguard Worker
1042*35238bceSAndroid Build Coastguard Worker // \note Filled as floats.
1043*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, range.x(), range.y(), values[0], numValues * scalarSize);
1044*35238bceSAndroid Build Coastguard Worker }
1045*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1046*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1047*35238bceSAndroid Build Coastguard Worker {
1048*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1049*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1050*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = 0;
1051*35238bceSAndroid Build Coastguard Worker
1052*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1053*35238bceSAndroid Build Coastguard Worker {
1054*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1055*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1056*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiff(in0, out0);
1057*35238bceSAndroid Build Coastguard Worker
1058*35238bceSAndroid Build Coastguard Worker if (ulpDiff > maxUlpDiff)
1059*35238bceSAndroid Build Coastguard Worker {
1060*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(tcu::Float32(in0).bits())
1061*35238bceSAndroid Build Coastguard Worker << " with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got ULP diff "
1062*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1063*35238bceSAndroid Build Coastguard Worker return false;
1064*35238bceSAndroid Build Coastguard Worker }
1065*35238bceSAndroid Build Coastguard Worker }
1066*35238bceSAndroid Build Coastguard Worker
1067*35238bceSAndroid Build Coastguard Worker return true;
1068*35238bceSAndroid Build Coastguard Worker }
1069*35238bceSAndroid Build Coastguard Worker };
1070*35238bceSAndroid Build Coastguard Worker
1071*35238bceSAndroid Build Coastguard Worker class FloorCase : public CommonFunctionCase
1072*35238bceSAndroid Build Coastguard Worker {
1073*35238bceSAndroid Build Coastguard Worker public:
FloorCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1074*35238bceSAndroid Build Coastguard Worker FloorCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1075*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "floor",
1076*35238bceSAndroid Build Coastguard Worker shaderType)
1077*35238bceSAndroid Build Coastguard Worker {
1078*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1079*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1080*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = floor(in0);";
1081*35238bceSAndroid Build Coastguard Worker }
1082*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1083*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1084*35238bceSAndroid Build Coastguard Worker {
1085*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1086*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1087*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1088*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1089*35238bceSAndroid Build Coastguard Worker };
1090*35238bceSAndroid Build Coastguard Worker
1091*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1092*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1093*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1094*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1095*35238bceSAndroid Build Coastguard Worker // Random cases.
1096*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float *)values[0],
1097*35238bceSAndroid Build Coastguard Worker numValues * scalarSize);
1098*35238bceSAndroid Build Coastguard Worker
1099*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1100*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1101*35238bceSAndroid Build Coastguard Worker {
1102*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1103*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1104*35238bceSAndroid Build Coastguard Worker }
1105*35238bceSAndroid Build Coastguard Worker }
1106*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1107*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1108*35238bceSAndroid Build Coastguard Worker {
1109*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1110*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1111*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1112*35238bceSAndroid Build Coastguard Worker
1113*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1114*35238bceSAndroid Build Coastguard Worker {
1115*35238bceSAndroid Build Coastguard Worker // Require exact result.
1116*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1117*35238bceSAndroid Build Coastguard Worker {
1118*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1119*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1120*35238bceSAndroid Build Coastguard Worker const float ref = deFloatFloor(in0);
1121*35238bceSAndroid Build Coastguard Worker
1122*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiff(out0, ref);
1123*35238bceSAndroid Build Coastguard Worker
1124*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1125*35238bceSAndroid Build Coastguard Worker {
1126*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1127*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1128*35238bceSAndroid Build Coastguard Worker return false;
1129*35238bceSAndroid Build Coastguard Worker }
1130*35238bceSAndroid Build Coastguard Worker }
1131*35238bceSAndroid Build Coastguard Worker }
1132*35238bceSAndroid Build Coastguard Worker else
1133*35238bceSAndroid Build Coastguard Worker {
1134*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1135*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
1136*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1137*35238bceSAndroid Build Coastguard Worker
1138*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1139*35238bceSAndroid Build Coastguard Worker {
1140*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1141*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1142*35238bceSAndroid Build Coastguard Worker const int minRes = int(deFloatFloor(in0 - eps));
1143*35238bceSAndroid Build Coastguard Worker const int maxRes = int(deFloatFloor(in0 + eps));
1144*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
1145*35238bceSAndroid Build Coastguard Worker
1146*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
1147*35238bceSAndroid Build Coastguard Worker {
1148*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiff(out0, float(roundedVal));
1149*35238bceSAndroid Build Coastguard Worker
1150*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
1151*35238bceSAndroid Build Coastguard Worker {
1152*35238bceSAndroid Build Coastguard Worker anyOk = true;
1153*35238bceSAndroid Build Coastguard Worker break;
1154*35238bceSAndroid Build Coastguard Worker }
1155*35238bceSAndroid Build Coastguard Worker }
1156*35238bceSAndroid Build Coastguard Worker
1157*35238bceSAndroid Build Coastguard Worker if (!anyOk)
1158*35238bceSAndroid Build Coastguard Worker {
1159*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
1160*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
1161*35238bceSAndroid Build Coastguard Worker return false;
1162*35238bceSAndroid Build Coastguard Worker }
1163*35238bceSAndroid Build Coastguard Worker }
1164*35238bceSAndroid Build Coastguard Worker }
1165*35238bceSAndroid Build Coastguard Worker
1166*35238bceSAndroid Build Coastguard Worker return true;
1167*35238bceSAndroid Build Coastguard Worker }
1168*35238bceSAndroid Build Coastguard Worker };
1169*35238bceSAndroid Build Coastguard Worker
1170*35238bceSAndroid Build Coastguard Worker class TruncCase : public CommonFunctionCase
1171*35238bceSAndroid Build Coastguard Worker {
1172*35238bceSAndroid Build Coastguard Worker public:
TruncCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1173*35238bceSAndroid Build Coastguard Worker TruncCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1174*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "trunc",
1175*35238bceSAndroid Build Coastguard Worker shaderType)
1176*35238bceSAndroid Build Coastguard Worker {
1177*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1178*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1179*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = trunc(in0);";
1180*35238bceSAndroid Build Coastguard Worker }
1181*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1182*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1183*35238bceSAndroid Build Coastguard Worker {
1184*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1185*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1186*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1187*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1188*35238bceSAndroid Build Coastguard Worker };
1189*35238bceSAndroid Build Coastguard Worker
1190*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1191*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1192*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1193*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1194*35238bceSAndroid Build Coastguard Worker const float specialCases[] = {0.0f, -0.0f, -0.9f, 0.9f, 1.0f, -1.0f};
1195*35238bceSAndroid Build Coastguard Worker const int numSpecialCases = DE_LENGTH_OF_ARRAY(specialCases);
1196*35238bceSAndroid Build Coastguard Worker
1197*35238bceSAndroid Build Coastguard Worker // Special cases
1198*35238bceSAndroid Build Coastguard Worker for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
1199*35238bceSAndroid Build Coastguard Worker {
1200*35238bceSAndroid Build Coastguard Worker for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
1201*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[caseNdx * scalarSize + scalarNdx] = specialCases[caseNdx];
1202*35238bceSAndroid Build Coastguard Worker }
1203*35238bceSAndroid Build Coastguard Worker
1204*35238bceSAndroid Build Coastguard Worker // Random cases.
1205*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(),
1206*35238bceSAndroid Build Coastguard Worker (float *)values[0] + scalarSize * numSpecialCases,
1207*35238bceSAndroid Build Coastguard Worker (numValues - numSpecialCases) * scalarSize);
1208*35238bceSAndroid Build Coastguard Worker
1209*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1210*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1211*35238bceSAndroid Build Coastguard Worker {
1212*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1213*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1214*35238bceSAndroid Build Coastguard Worker }
1215*35238bceSAndroid Build Coastguard Worker }
1216*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1217*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1218*35238bceSAndroid Build Coastguard Worker {
1219*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1220*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1221*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1222*35238bceSAndroid Build Coastguard Worker
1223*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1224*35238bceSAndroid Build Coastguard Worker {
1225*35238bceSAndroid Build Coastguard Worker // Require exact result.
1226*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1227*35238bceSAndroid Build Coastguard Worker {
1228*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1229*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1230*35238bceSAndroid Build Coastguard Worker const bool isNeg = tcu::Float32(in0).sign() < 0;
1231*35238bceSAndroid Build Coastguard Worker const float ref = isNeg ? (-float(int(-in0))) : float(int(in0));
1232*35238bceSAndroid Build Coastguard Worker
1233*35238bceSAndroid Build Coastguard Worker // \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero.
1234*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, ref);
1235*35238bceSAndroid Build Coastguard Worker
1236*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1237*35238bceSAndroid Build Coastguard Worker {
1238*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1239*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1240*35238bceSAndroid Build Coastguard Worker return false;
1241*35238bceSAndroid Build Coastguard Worker }
1242*35238bceSAndroid Build Coastguard Worker }
1243*35238bceSAndroid Build Coastguard Worker }
1244*35238bceSAndroid Build Coastguard Worker else
1245*35238bceSAndroid Build Coastguard Worker {
1246*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1247*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
1248*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1249*35238bceSAndroid Build Coastguard Worker
1250*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1251*35238bceSAndroid Build Coastguard Worker {
1252*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1253*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1254*35238bceSAndroid Build Coastguard Worker const int minRes = int(in0 - eps);
1255*35238bceSAndroid Build Coastguard Worker const int maxRes = int(in0 + eps);
1256*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
1257*35238bceSAndroid Build Coastguard Worker
1258*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
1259*35238bceSAndroid Build Coastguard Worker {
1260*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
1261*35238bceSAndroid Build Coastguard Worker
1262*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
1263*35238bceSAndroid Build Coastguard Worker {
1264*35238bceSAndroid Build Coastguard Worker anyOk = true;
1265*35238bceSAndroid Build Coastguard Worker break;
1266*35238bceSAndroid Build Coastguard Worker }
1267*35238bceSAndroid Build Coastguard Worker }
1268*35238bceSAndroid Build Coastguard Worker
1269*35238bceSAndroid Build Coastguard Worker if (!anyOk)
1270*35238bceSAndroid Build Coastguard Worker {
1271*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
1272*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
1273*35238bceSAndroid Build Coastguard Worker return false;
1274*35238bceSAndroid Build Coastguard Worker }
1275*35238bceSAndroid Build Coastguard Worker }
1276*35238bceSAndroid Build Coastguard Worker }
1277*35238bceSAndroid Build Coastguard Worker
1278*35238bceSAndroid Build Coastguard Worker return true;
1279*35238bceSAndroid Build Coastguard Worker }
1280*35238bceSAndroid Build Coastguard Worker };
1281*35238bceSAndroid Build Coastguard Worker
1282*35238bceSAndroid Build Coastguard Worker class RoundCase : public CommonFunctionCase
1283*35238bceSAndroid Build Coastguard Worker {
1284*35238bceSAndroid Build Coastguard Worker public:
RoundCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1285*35238bceSAndroid Build Coastguard Worker RoundCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1286*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "round",
1287*35238bceSAndroid Build Coastguard Worker shaderType)
1288*35238bceSAndroid Build Coastguard Worker {
1289*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1290*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1291*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = round(in0);";
1292*35238bceSAndroid Build Coastguard Worker }
1293*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1294*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1295*35238bceSAndroid Build Coastguard Worker {
1296*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1297*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1298*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1299*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1300*35238bceSAndroid Build Coastguard Worker };
1301*35238bceSAndroid Build Coastguard Worker
1302*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1303*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1304*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1305*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1306*35238bceSAndroid Build Coastguard Worker int numSpecialCases = 0;
1307*35238bceSAndroid Build Coastguard Worker
1308*35238bceSAndroid Build Coastguard Worker // Special cases.
1309*35238bceSAndroid Build Coastguard Worker if (precision != glu::PRECISION_LOWP)
1310*35238bceSAndroid Build Coastguard Worker {
1311*35238bceSAndroid Build Coastguard Worker DE_ASSERT(numValues >= 10);
1312*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < 10; ndx++)
1313*35238bceSAndroid Build Coastguard Worker {
1314*35238bceSAndroid Build Coastguard Worker const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
1315*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0], (float *)values[0] + scalarSize, v);
1316*35238bceSAndroid Build Coastguard Worker numSpecialCases += 1;
1317*35238bceSAndroid Build Coastguard Worker }
1318*35238bceSAndroid Build Coastguard Worker }
1319*35238bceSAndroid Build Coastguard Worker
1320*35238bceSAndroid Build Coastguard Worker // Random cases.
1321*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(),
1322*35238bceSAndroid Build Coastguard Worker (float *)values[0] + numSpecialCases * scalarSize,
1323*35238bceSAndroid Build Coastguard Worker (numValues - numSpecialCases) * scalarSize);
1324*35238bceSAndroid Build Coastguard Worker
1325*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1326*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1327*35238bceSAndroid Build Coastguard Worker {
1328*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1329*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1330*35238bceSAndroid Build Coastguard Worker }
1331*35238bceSAndroid Build Coastguard Worker }
1332*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1333*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1334*35238bceSAndroid Build Coastguard Worker {
1335*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1336*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1337*35238bceSAndroid Build Coastguard Worker const bool hasZeroSign = supportsSignedZero(precision);
1338*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1339*35238bceSAndroid Build Coastguard Worker
1340*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1341*35238bceSAndroid Build Coastguard Worker {
1342*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1343*35238bceSAndroid Build Coastguard Worker {
1344*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1345*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1346*35238bceSAndroid Build Coastguard Worker
1347*35238bceSAndroid Build Coastguard Worker if (deFloatFrac(in0) == 0.5f)
1348*35238bceSAndroid Build Coastguard Worker {
1349*35238bceSAndroid Build Coastguard Worker // Allow both ceil(in) and floor(in)
1350*35238bceSAndroid Build Coastguard Worker const float ref0 = deFloatFloor(in0);
1351*35238bceSAndroid Build Coastguard Worker const float ref1 = deFloatCeil(in0);
1352*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff0 =
1353*35238bceSAndroid Build Coastguard Worker hasZeroSign ? getUlpDiff(out0, ref0) : getUlpDiffIgnoreZeroSign(out0, ref0);
1354*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff1 =
1355*35238bceSAndroid Build Coastguard Worker hasZeroSign ? getUlpDiff(out0, ref1) : getUlpDiffIgnoreZeroSign(out0, ref1);
1356*35238bceSAndroid Build Coastguard Worker
1357*35238bceSAndroid Build Coastguard Worker if (ulpDiff0 > 0 && ulpDiff1 > 0)
1358*35238bceSAndroid Build Coastguard Worker {
1359*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " or " << HexFloat(ref1)
1360*35238bceSAndroid Build Coastguard Worker << ", got ULP diff " << tcu::toHex(de::min(ulpDiff0, ulpDiff1));
1361*35238bceSAndroid Build Coastguard Worker return false;
1362*35238bceSAndroid Build Coastguard Worker }
1363*35238bceSAndroid Build Coastguard Worker }
1364*35238bceSAndroid Build Coastguard Worker else
1365*35238bceSAndroid Build Coastguard Worker {
1366*35238bceSAndroid Build Coastguard Worker // Require exact result
1367*35238bceSAndroid Build Coastguard Worker const float ref = roundEven(in0);
1368*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
1369*35238bceSAndroid Build Coastguard Worker
1370*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1371*35238bceSAndroid Build Coastguard Worker {
1372*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1373*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1374*35238bceSAndroid Build Coastguard Worker return false;
1375*35238bceSAndroid Build Coastguard Worker }
1376*35238bceSAndroid Build Coastguard Worker }
1377*35238bceSAndroid Build Coastguard Worker }
1378*35238bceSAndroid Build Coastguard Worker }
1379*35238bceSAndroid Build Coastguard Worker else
1380*35238bceSAndroid Build Coastguard Worker {
1381*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1382*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
1383*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1384*35238bceSAndroid Build Coastguard Worker
1385*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1386*35238bceSAndroid Build Coastguard Worker {
1387*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1388*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1389*35238bceSAndroid Build Coastguard Worker const int minRes = int(roundEven(in0 - eps));
1390*35238bceSAndroid Build Coastguard Worker const int maxRes = int(roundEven(in0 + eps));
1391*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
1392*35238bceSAndroid Build Coastguard Worker
1393*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
1394*35238bceSAndroid Build Coastguard Worker {
1395*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
1396*35238bceSAndroid Build Coastguard Worker
1397*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
1398*35238bceSAndroid Build Coastguard Worker {
1399*35238bceSAndroid Build Coastguard Worker anyOk = true;
1400*35238bceSAndroid Build Coastguard Worker break;
1401*35238bceSAndroid Build Coastguard Worker }
1402*35238bceSAndroid Build Coastguard Worker }
1403*35238bceSAndroid Build Coastguard Worker
1404*35238bceSAndroid Build Coastguard Worker if (!anyOk)
1405*35238bceSAndroid Build Coastguard Worker {
1406*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
1407*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
1408*35238bceSAndroid Build Coastguard Worker return false;
1409*35238bceSAndroid Build Coastguard Worker }
1410*35238bceSAndroid Build Coastguard Worker }
1411*35238bceSAndroid Build Coastguard Worker }
1412*35238bceSAndroid Build Coastguard Worker
1413*35238bceSAndroid Build Coastguard Worker return true;
1414*35238bceSAndroid Build Coastguard Worker }
1415*35238bceSAndroid Build Coastguard Worker };
1416*35238bceSAndroid Build Coastguard Worker
1417*35238bceSAndroid Build Coastguard Worker class CeilCase : public CommonFunctionCase
1418*35238bceSAndroid Build Coastguard Worker {
1419*35238bceSAndroid Build Coastguard Worker public:
CeilCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1420*35238bceSAndroid Build Coastguard Worker CeilCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1421*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ceil",
1422*35238bceSAndroid Build Coastguard Worker shaderType)
1423*35238bceSAndroid Build Coastguard Worker {
1424*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1425*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1426*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = ceil(in0);";
1427*35238bceSAndroid Build Coastguard Worker }
1428*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1429*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1430*35238bceSAndroid Build Coastguard Worker {
1431*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1432*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1433*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1434*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1435*35238bceSAndroid Build Coastguard Worker };
1436*35238bceSAndroid Build Coastguard Worker
1437*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1438*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1439*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1440*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1441*35238bceSAndroid Build Coastguard Worker
1442*35238bceSAndroid Build Coastguard Worker // Random cases.
1443*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float *)values[0],
1444*35238bceSAndroid Build Coastguard Worker numValues * scalarSize);
1445*35238bceSAndroid Build Coastguard Worker
1446*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1447*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1448*35238bceSAndroid Build Coastguard Worker {
1449*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1450*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1451*35238bceSAndroid Build Coastguard Worker }
1452*35238bceSAndroid Build Coastguard Worker }
1453*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1454*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1455*35238bceSAndroid Build Coastguard Worker {
1456*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1457*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1458*35238bceSAndroid Build Coastguard Worker const bool hasZeroSign = supportsSignedZero(precision);
1459*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1460*35238bceSAndroid Build Coastguard Worker
1461*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1462*35238bceSAndroid Build Coastguard Worker {
1463*35238bceSAndroid Build Coastguard Worker // Require exact result.
1464*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1465*35238bceSAndroid Build Coastguard Worker {
1466*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1467*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1468*35238bceSAndroid Build Coastguard Worker const float ref = deFloatCeil(in0);
1469*35238bceSAndroid Build Coastguard Worker
1470*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
1471*35238bceSAndroid Build Coastguard Worker
1472*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1473*35238bceSAndroid Build Coastguard Worker {
1474*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1475*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1476*35238bceSAndroid Build Coastguard Worker return false;
1477*35238bceSAndroid Build Coastguard Worker }
1478*35238bceSAndroid Build Coastguard Worker }
1479*35238bceSAndroid Build Coastguard Worker }
1480*35238bceSAndroid Build Coastguard Worker else
1481*35238bceSAndroid Build Coastguard Worker {
1482*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1483*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
1484*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1485*35238bceSAndroid Build Coastguard Worker
1486*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1487*35238bceSAndroid Build Coastguard Worker {
1488*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1489*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1490*35238bceSAndroid Build Coastguard Worker const int minRes = int(deFloatCeil(in0 - eps));
1491*35238bceSAndroid Build Coastguard Worker const int maxRes = int(deFloatCeil(in0 + eps));
1492*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
1493*35238bceSAndroid Build Coastguard Worker
1494*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
1495*35238bceSAndroid Build Coastguard Worker {
1496*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
1497*35238bceSAndroid Build Coastguard Worker
1498*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
1499*35238bceSAndroid Build Coastguard Worker {
1500*35238bceSAndroid Build Coastguard Worker anyOk = true;
1501*35238bceSAndroid Build Coastguard Worker break;
1502*35238bceSAndroid Build Coastguard Worker }
1503*35238bceSAndroid Build Coastguard Worker }
1504*35238bceSAndroid Build Coastguard Worker
1505*35238bceSAndroid Build Coastguard Worker if (!anyOk && de::inRange(0, minRes, maxRes))
1506*35238bceSAndroid Build Coastguard Worker {
1507*35238bceSAndroid Build Coastguard Worker // Allow -0 as well.
1508*35238bceSAndroid Build Coastguard Worker const int ulpDiff = de::abs((int)tcu::Float32(out0).bits() - (int)0x80000000u);
1509*35238bceSAndroid Build Coastguard Worker anyOk = ((uint32_t)ulpDiff <= maxUlpDiff);
1510*35238bceSAndroid Build Coastguard Worker }
1511*35238bceSAndroid Build Coastguard Worker
1512*35238bceSAndroid Build Coastguard Worker if (!anyOk)
1513*35238bceSAndroid Build Coastguard Worker {
1514*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
1515*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
1516*35238bceSAndroid Build Coastguard Worker return false;
1517*35238bceSAndroid Build Coastguard Worker }
1518*35238bceSAndroid Build Coastguard Worker }
1519*35238bceSAndroid Build Coastguard Worker }
1520*35238bceSAndroid Build Coastguard Worker
1521*35238bceSAndroid Build Coastguard Worker return true;
1522*35238bceSAndroid Build Coastguard Worker }
1523*35238bceSAndroid Build Coastguard Worker };
1524*35238bceSAndroid Build Coastguard Worker
1525*35238bceSAndroid Build Coastguard Worker class FractCase : public CommonFunctionCase
1526*35238bceSAndroid Build Coastguard Worker {
1527*35238bceSAndroid Build Coastguard Worker public:
FractCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1528*35238bceSAndroid Build Coastguard Worker FractCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1529*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fract",
1530*35238bceSAndroid Build Coastguard Worker shaderType)
1531*35238bceSAndroid Build Coastguard Worker {
1532*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1533*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1534*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = fract(in0);";
1535*35238bceSAndroid Build Coastguard Worker }
1536*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1537*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1538*35238bceSAndroid Build Coastguard Worker {
1539*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1540*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1541*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1542*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1543*35238bceSAndroid Build Coastguard Worker };
1544*35238bceSAndroid Build Coastguard Worker
1545*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1546*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1547*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1548*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1549*35238bceSAndroid Build Coastguard Worker int numSpecialCases = 0;
1550*35238bceSAndroid Build Coastguard Worker
1551*35238bceSAndroid Build Coastguard Worker // Special cases.
1552*35238bceSAndroid Build Coastguard Worker if (precision != glu::PRECISION_LOWP)
1553*35238bceSAndroid Build Coastguard Worker {
1554*35238bceSAndroid Build Coastguard Worker DE_ASSERT(numValues >= 10);
1555*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < 10; ndx++)
1556*35238bceSAndroid Build Coastguard Worker {
1557*35238bceSAndroid Build Coastguard Worker const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
1558*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0], (float *)values[0] + scalarSize, v);
1559*35238bceSAndroid Build Coastguard Worker numSpecialCases += 1;
1560*35238bceSAndroid Build Coastguard Worker }
1561*35238bceSAndroid Build Coastguard Worker }
1562*35238bceSAndroid Build Coastguard Worker
1563*35238bceSAndroid Build Coastguard Worker // Random cases.
1564*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(),
1565*35238bceSAndroid Build Coastguard Worker (float *)values[0] + numSpecialCases * scalarSize,
1566*35238bceSAndroid Build Coastguard Worker (numValues - numSpecialCases) * scalarSize);
1567*35238bceSAndroid Build Coastguard Worker
1568*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1569*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1570*35238bceSAndroid Build Coastguard Worker {
1571*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1572*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1573*35238bceSAndroid Build Coastguard Worker }
1574*35238bceSAndroid Build Coastguard Worker }
1575*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1576*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1577*35238bceSAndroid Build Coastguard Worker {
1578*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1579*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1580*35238bceSAndroid Build Coastguard Worker const bool hasZeroSign = supportsSignedZero(precision);
1581*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1582*35238bceSAndroid Build Coastguard Worker
1583*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1584*35238bceSAndroid Build Coastguard Worker {
1585*35238bceSAndroid Build Coastguard Worker // Require exact result.
1586*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1587*35238bceSAndroid Build Coastguard Worker {
1588*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1589*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1590*35238bceSAndroid Build Coastguard Worker const float ref = deFloatFrac(in0);
1591*35238bceSAndroid Build Coastguard Worker
1592*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
1593*35238bceSAndroid Build Coastguard Worker
1594*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1595*35238bceSAndroid Build Coastguard Worker {
1596*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1597*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1598*35238bceSAndroid Build Coastguard Worker return false;
1599*35238bceSAndroid Build Coastguard Worker }
1600*35238bceSAndroid Build Coastguard Worker }
1601*35238bceSAndroid Build Coastguard Worker }
1602*35238bceSAndroid Build Coastguard Worker else
1603*35238bceSAndroid Build Coastguard Worker {
1604*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1605*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1606*35238bceSAndroid Build Coastguard Worker
1607*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1608*35238bceSAndroid Build Coastguard Worker {
1609*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1610*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1611*35238bceSAndroid Build Coastguard Worker
1612*35238bceSAndroid Build Coastguard Worker if (int(deFloatFloor(in0 - eps)) == int(deFloatFloor(in0 + eps)))
1613*35238bceSAndroid Build Coastguard Worker {
1614*35238bceSAndroid Build Coastguard Worker const float ref = deFloatFrac(in0);
1615*35238bceSAndroid Build Coastguard Worker const int bitsLost = numBitsLostInOp(in0, ref);
1616*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(
1617*35238bceSAndroid Build Coastguard Worker de::max(0, mantissaBits - bitsLost)); // ULP diff for rounded integer value.
1618*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, ref);
1619*35238bceSAndroid Build Coastguard Worker
1620*35238bceSAndroid Build Coastguard Worker if (ulpDiff > maxUlpDiff)
1621*35238bceSAndroid Build Coastguard Worker {
1622*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold "
1623*35238bceSAndroid Build Coastguard Worker << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
1624*35238bceSAndroid Build Coastguard Worker return false;
1625*35238bceSAndroid Build Coastguard Worker }
1626*35238bceSAndroid Build Coastguard Worker }
1627*35238bceSAndroid Build Coastguard Worker else
1628*35238bceSAndroid Build Coastguard Worker {
1629*35238bceSAndroid Build Coastguard Worker if (out0 >= 1.0f)
1630*35238bceSAndroid Build Coastguard Worker {
1631*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] < 1.0";
1632*35238bceSAndroid Build Coastguard Worker return false;
1633*35238bceSAndroid Build Coastguard Worker }
1634*35238bceSAndroid Build Coastguard Worker }
1635*35238bceSAndroid Build Coastguard Worker }
1636*35238bceSAndroid Build Coastguard Worker }
1637*35238bceSAndroid Build Coastguard Worker
1638*35238bceSAndroid Build Coastguard Worker return true;
1639*35238bceSAndroid Build Coastguard Worker }
1640*35238bceSAndroid Build Coastguard Worker };
1641*35238bceSAndroid Build Coastguard Worker
ShaderCommonFunctionTests(Context & context)1642*35238bceSAndroid Build Coastguard Worker ShaderCommonFunctionTests::ShaderCommonFunctionTests(Context &context)
1643*35238bceSAndroid Build Coastguard Worker : TestCaseGroup(context, "common", "Common function tests")
1644*35238bceSAndroid Build Coastguard Worker {
1645*35238bceSAndroid Build Coastguard Worker }
1646*35238bceSAndroid Build Coastguard Worker
~ShaderCommonFunctionTests(void)1647*35238bceSAndroid Build Coastguard Worker ShaderCommonFunctionTests::~ShaderCommonFunctionTests(void)
1648*35238bceSAndroid Build Coastguard Worker {
1649*35238bceSAndroid Build Coastguard Worker }
1650*35238bceSAndroid Build Coastguard Worker
1651*35238bceSAndroid Build Coastguard Worker template <class TestClass>
addFunctionCases(TestCaseGroup * parent,const char * functionName,bool floatTypes,bool intTypes,bool uintTypes)1652*35238bceSAndroid Build Coastguard Worker static void addFunctionCases(TestCaseGroup *parent, const char *functionName, bool floatTypes, bool intTypes,
1653*35238bceSAndroid Build Coastguard Worker bool uintTypes)
1654*35238bceSAndroid Build Coastguard Worker {
1655*35238bceSAndroid Build Coastguard Worker tcu::TestCaseGroup *group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);
1656*35238bceSAndroid Build Coastguard Worker parent->addChild(group);
1657*35238bceSAndroid Build Coastguard Worker
1658*35238bceSAndroid Build Coastguard Worker const glu::DataType scalarTypes[] = {glu::TYPE_FLOAT, glu::TYPE_INT, glu::TYPE_UINT};
1659*35238bceSAndroid Build Coastguard Worker
1660*35238bceSAndroid Build Coastguard Worker for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++)
1661*35238bceSAndroid Build Coastguard Worker {
1662*35238bceSAndroid Build Coastguard Worker const glu::DataType scalarType = scalarTypes[scalarTypeNdx];
1663*35238bceSAndroid Build Coastguard Worker
1664*35238bceSAndroid Build Coastguard Worker if ((!floatTypes && scalarType == glu::TYPE_FLOAT) || (!intTypes && scalarType == glu::TYPE_INT) ||
1665*35238bceSAndroid Build Coastguard Worker (!uintTypes && scalarType == glu::TYPE_UINT))
1666*35238bceSAndroid Build Coastguard Worker continue;
1667*35238bceSAndroid Build Coastguard Worker
1668*35238bceSAndroid Build Coastguard Worker for (int vecSize = 1; vecSize <= 4; vecSize++)
1669*35238bceSAndroid Build Coastguard Worker {
1670*35238bceSAndroid Build Coastguard Worker for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++)
1671*35238bceSAndroid Build Coastguard Worker {
1672*35238bceSAndroid Build Coastguard Worker for (int shaderType = glu::SHADERTYPE_VERTEX; shaderType <= glu::SHADERTYPE_FRAGMENT; shaderType++)
1673*35238bceSAndroid Build Coastguard Worker group->addChild(new TestClass(parent->getContext(), glu::DataType(scalarType + vecSize - 1),
1674*35238bceSAndroid Build Coastguard Worker glu::Precision(prec), glu::ShaderType(shaderType)));
1675*35238bceSAndroid Build Coastguard Worker }
1676*35238bceSAndroid Build Coastguard Worker }
1677*35238bceSAndroid Build Coastguard Worker }
1678*35238bceSAndroid Build Coastguard Worker }
1679*35238bceSAndroid Build Coastguard Worker
init(void)1680*35238bceSAndroid Build Coastguard Worker void ShaderCommonFunctionTests::init(void)
1681*35238bceSAndroid Build Coastguard Worker {
1682*35238bceSAndroid Build Coastguard Worker // Float? Int? Uint?
1683*35238bceSAndroid Build Coastguard Worker addFunctionCases<AbsCase>(this, "abs", true, true, false);
1684*35238bceSAndroid Build Coastguard Worker addFunctionCases<SignCase>(this, "sign", true, true, false);
1685*35238bceSAndroid Build Coastguard Worker addFunctionCases<FloorCase>(this, "floor", true, false, false);
1686*35238bceSAndroid Build Coastguard Worker addFunctionCases<TruncCase>(this, "trunc", true, false, false);
1687*35238bceSAndroid Build Coastguard Worker addFunctionCases<RoundCase>(this, "round", true, false, false);
1688*35238bceSAndroid Build Coastguard Worker addFunctionCases<RoundEvenCase>(this, "roundeven", true, false, false);
1689*35238bceSAndroid Build Coastguard Worker addFunctionCases<CeilCase>(this, "ceil", true, false, false);
1690*35238bceSAndroid Build Coastguard Worker addFunctionCases<FractCase>(this, "fract", true, false, false);
1691*35238bceSAndroid Build Coastguard Worker // mod
1692*35238bceSAndroid Build Coastguard Worker addFunctionCases<ModfCase>(this, "modf", true, false, false);
1693*35238bceSAndroid Build Coastguard Worker // min
1694*35238bceSAndroid Build Coastguard Worker // max
1695*35238bceSAndroid Build Coastguard Worker // clamp
1696*35238bceSAndroid Build Coastguard Worker // mix
1697*35238bceSAndroid Build Coastguard Worker // step
1698*35238bceSAndroid Build Coastguard Worker // smoothstep
1699*35238bceSAndroid Build Coastguard Worker addFunctionCases<IsnanCase>(this, "isnan", true, false, false);
1700*35238bceSAndroid Build Coastguard Worker addFunctionCases<IsinfCase>(this, "isinf", true, false, false);
1701*35238bceSAndroid Build Coastguard Worker addFunctionCases<FloatBitsToIntCase>(this, "floatbitstoint", true, false, false);
1702*35238bceSAndroid Build Coastguard Worker addFunctionCases<FloatBitsToUintCase>(this, "floatbitstouint", true, false, false);
1703*35238bceSAndroid Build Coastguard Worker
1704*35238bceSAndroid Build Coastguard Worker // (u)intBitsToFloat()
1705*35238bceSAndroid Build Coastguard Worker {
1706*35238bceSAndroid Build Coastguard Worker tcu::TestCaseGroup *intGroup = new tcu::TestCaseGroup(m_testCtx, "intbitstofloat", "intBitsToFloat() Tests");
1707*35238bceSAndroid Build Coastguard Worker tcu::TestCaseGroup *uintGroup = new tcu::TestCaseGroup(m_testCtx, "uintbitstofloat", "uintBitsToFloat() Tests");
1708*35238bceSAndroid Build Coastguard Worker
1709*35238bceSAndroid Build Coastguard Worker addChild(intGroup);
1710*35238bceSAndroid Build Coastguard Worker addChild(uintGroup);
1711*35238bceSAndroid Build Coastguard Worker
1712*35238bceSAndroid Build Coastguard Worker for (int vecSize = 1; vecSize < 4; vecSize++)
1713*35238bceSAndroid Build Coastguard Worker {
1714*35238bceSAndroid Build Coastguard Worker const glu::DataType intType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
1715*35238bceSAndroid Build Coastguard Worker const glu::DataType uintType = vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
1716*35238bceSAndroid Build Coastguard Worker
1717*35238bceSAndroid Build Coastguard Worker for (int shaderType = glu::SHADERTYPE_VERTEX; shaderType <= glu::SHADERTYPE_FRAGMENT; shaderType++)
1718*35238bceSAndroid Build Coastguard Worker {
1719*35238bceSAndroid Build Coastguard Worker intGroup->addChild(new BitsToFloatCase(m_context, intType, glu::ShaderType(shaderType)));
1720*35238bceSAndroid Build Coastguard Worker uintGroup->addChild(new BitsToFloatCase(m_context, uintType, glu::ShaderType(shaderType)));
1721*35238bceSAndroid Build Coastguard Worker }
1722*35238bceSAndroid Build Coastguard Worker }
1723*35238bceSAndroid Build Coastguard Worker }
1724*35238bceSAndroid Build Coastguard Worker }
1725*35238bceSAndroid Build Coastguard Worker
1726*35238bceSAndroid Build Coastguard Worker } // namespace Functional
1727*35238bceSAndroid Build Coastguard Worker } // namespace gles3
1728*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1729