1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program OpenGL ES 3.1 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 "es31fShaderCommonFunctionTests.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "gluContextInfo.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "glsShaderExecUtil.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "tcuFormatUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "tcuFloat.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "tcuInterval.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "tcuFloatFormat.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "tcuVectorUtil.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "deMath.h"
35*35238bceSAndroid Build Coastguard Worker #include "deString.h"
36*35238bceSAndroid Build Coastguard Worker #include "deArrayUtil.hpp"
37*35238bceSAndroid Build Coastguard Worker
38*35238bceSAndroid Build Coastguard Worker namespace deqp
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker namespace gles31
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker namespace Functional
43*35238bceSAndroid Build Coastguard Worker {
44*35238bceSAndroid Build Coastguard Worker
45*35238bceSAndroid Build Coastguard Worker using std::string;
46*35238bceSAndroid Build Coastguard Worker using std::vector;
47*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
48*35238bceSAndroid Build Coastguard Worker using namespace gls::ShaderExecUtil;
49*35238bceSAndroid Build Coastguard Worker
50*35238bceSAndroid Build Coastguard Worker using tcu::IVec2;
51*35238bceSAndroid Build Coastguard Worker using tcu::IVec3;
52*35238bceSAndroid Build Coastguard Worker using tcu::IVec4;
53*35238bceSAndroid Build Coastguard Worker using tcu::Vec2;
54*35238bceSAndroid Build Coastguard Worker using tcu::Vec3;
55*35238bceSAndroid Build Coastguard Worker using tcu::Vec4;
56*35238bceSAndroid Build Coastguard Worker
57*35238bceSAndroid Build Coastguard Worker // Utilities
58*35238bceSAndroid Build Coastguard Worker
59*35238bceSAndroid Build Coastguard Worker template <typename T, int Size>
60*35238bceSAndroid Build Coastguard Worker struct VecArrayAccess
61*35238bceSAndroid Build Coastguard Worker {
62*35238bceSAndroid Build Coastguard Worker public:
VecArrayAccessdeqp::gles31::Functional::VecArrayAccess63*35238bceSAndroid Build Coastguard Worker VecArrayAccess(const void *ptr) : m_array((tcu::Vector<T, Size> *)ptr)
64*35238bceSAndroid Build Coastguard Worker {
65*35238bceSAndroid Build Coastguard Worker }
~VecArrayAccessdeqp::gles31::Functional::VecArrayAccess66*35238bceSAndroid Build Coastguard Worker ~VecArrayAccess(void)
67*35238bceSAndroid Build Coastguard Worker {
68*35238bceSAndroid Build Coastguard Worker }
69*35238bceSAndroid Build Coastguard Worker
operator []deqp::gles31::Functional::VecArrayAccess70*35238bceSAndroid Build Coastguard Worker const tcu::Vector<T, Size> &operator[](size_t offset) const
71*35238bceSAndroid Build Coastguard Worker {
72*35238bceSAndroid Build Coastguard Worker return m_array[offset];
73*35238bceSAndroid Build Coastguard Worker }
operator []deqp::gles31::Functional::VecArrayAccess74*35238bceSAndroid Build Coastguard Worker tcu::Vector<T, Size> &operator[](size_t offset)
75*35238bceSAndroid Build Coastguard Worker {
76*35238bceSAndroid Build Coastguard Worker return m_array[offset];
77*35238bceSAndroid Build Coastguard Worker }
78*35238bceSAndroid Build Coastguard Worker
79*35238bceSAndroid Build Coastguard Worker private:
80*35238bceSAndroid Build Coastguard Worker tcu::Vector<T, Size> *m_array;
81*35238bceSAndroid Build Coastguard Worker };
82*35238bceSAndroid Build Coastguard Worker
83*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)84*35238bceSAndroid Build Coastguard Worker static void fillRandomVectors(de::Random &rnd, const tcu::Vector<T, Size> &minValue,
85*35238bceSAndroid Build Coastguard Worker const tcu::Vector<T, Size> &maxValue, void *dst, int numValues, int offset = 0)
86*35238bceSAndroid Build Coastguard Worker {
87*35238bceSAndroid Build Coastguard Worker VecArrayAccess<T, Size> access(dst);
88*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues; ndx++)
89*35238bceSAndroid Build Coastguard Worker access[offset + ndx] = tcu::randomVector<T, Size>(rnd, minValue, maxValue);
90*35238bceSAndroid Build Coastguard Worker }
91*35238bceSAndroid Build Coastguard Worker
92*35238bceSAndroid Build Coastguard Worker template <typename T>
fillRandomScalars(de::Random & rnd,T minValue,T maxValue,void * dst,int numValues,int offset=0)93*35238bceSAndroid Build Coastguard Worker static void fillRandomScalars(de::Random &rnd, T minValue, T maxValue, void *dst, int numValues, int offset = 0)
94*35238bceSAndroid Build Coastguard Worker {
95*35238bceSAndroid Build Coastguard Worker T *typedPtr = (T *)dst;
96*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues; ndx++)
97*35238bceSAndroid Build Coastguard Worker typedPtr[offset + ndx] = de::randomScalar<T>(rnd, minValue, maxValue);
98*35238bceSAndroid Build Coastguard Worker }
99*35238bceSAndroid Build Coastguard Worker
numBitsLostInOp(float input,float output)100*35238bceSAndroid Build Coastguard Worker inline int numBitsLostInOp(float input, float output)
101*35238bceSAndroid Build Coastguard Worker {
102*35238bceSAndroid Build Coastguard Worker const int inExp = tcu::Float32(input).exponent();
103*35238bceSAndroid Build Coastguard Worker const int outExp = tcu::Float32(output).exponent();
104*35238bceSAndroid Build Coastguard Worker
105*35238bceSAndroid Build Coastguard Worker return de::max(0, inExp - outExp); // Lost due to mantissa shift.
106*35238bceSAndroid Build Coastguard Worker }
107*35238bceSAndroid Build Coastguard Worker
getUlpDiff(float a,float b)108*35238bceSAndroid Build Coastguard Worker inline uint32_t getUlpDiff(float a, float b)
109*35238bceSAndroid Build Coastguard Worker {
110*35238bceSAndroid Build Coastguard Worker const uint32_t aBits = tcu::Float32(a).bits();
111*35238bceSAndroid Build Coastguard Worker const uint32_t bBits = tcu::Float32(b).bits();
112*35238bceSAndroid Build Coastguard Worker return aBits > bBits ? aBits - bBits : bBits - aBits;
113*35238bceSAndroid Build Coastguard Worker }
114*35238bceSAndroid Build Coastguard Worker
getUlpDiffIgnoreZeroSign(float a,float b)115*35238bceSAndroid Build Coastguard Worker inline uint32_t getUlpDiffIgnoreZeroSign(float a, float b)
116*35238bceSAndroid Build Coastguard Worker {
117*35238bceSAndroid Build Coastguard Worker if (tcu::Float32(a).isZero())
118*35238bceSAndroid Build Coastguard Worker return getUlpDiff(tcu::Float32::construct(tcu::Float32(b).sign(), 0, 0).asFloat(), b);
119*35238bceSAndroid Build Coastguard Worker else if (tcu::Float32(b).isZero())
120*35238bceSAndroid Build Coastguard Worker return getUlpDiff(a, tcu::Float32::construct(tcu::Float32(a).sign(), 0, 0).asFloat());
121*35238bceSAndroid Build Coastguard Worker else
122*35238bceSAndroid Build Coastguard Worker return getUlpDiff(a, b);
123*35238bceSAndroid Build Coastguard Worker }
124*35238bceSAndroid Build Coastguard Worker
supportsSignedZero(glu::Precision precision)125*35238bceSAndroid Build Coastguard Worker inline bool supportsSignedZero(glu::Precision precision)
126*35238bceSAndroid Build Coastguard Worker {
127*35238bceSAndroid Build Coastguard Worker // \note GLSL ES 3.1 doesn't really require support for -0, but we require it for highp
128*35238bceSAndroid Build Coastguard Worker // as it is very widely supported.
129*35238bceSAndroid Build Coastguard Worker return precision == glu::PRECISION_HIGHP;
130*35238bceSAndroid Build Coastguard Worker }
131*35238bceSAndroid Build Coastguard Worker
getEpsFromMaxUlpDiff(float value,uint32_t ulpDiff)132*35238bceSAndroid Build Coastguard Worker inline float getEpsFromMaxUlpDiff(float value, uint32_t ulpDiff)
133*35238bceSAndroid Build Coastguard Worker {
134*35238bceSAndroid Build Coastguard Worker const int exp = tcu::Float32(value).exponent();
135*35238bceSAndroid Build Coastguard Worker return tcu::Float32::construct(+1, exp, (1u << 23) | ulpDiff).asFloat() -
136*35238bceSAndroid Build Coastguard Worker tcu::Float32::construct(+1, exp, 1u << 23).asFloat();
137*35238bceSAndroid Build Coastguard Worker }
138*35238bceSAndroid Build Coastguard Worker
getMaxUlpDiffFromBits(int numAccurateBits)139*35238bceSAndroid Build Coastguard Worker inline uint32_t getMaxUlpDiffFromBits(int numAccurateBits)
140*35238bceSAndroid Build Coastguard Worker {
141*35238bceSAndroid Build Coastguard Worker const int numGarbageBits = 23 - numAccurateBits;
142*35238bceSAndroid Build Coastguard Worker const uint32_t mask = (1u << numGarbageBits) - 1u;
143*35238bceSAndroid Build Coastguard Worker
144*35238bceSAndroid Build Coastguard Worker return mask;
145*35238bceSAndroid Build Coastguard Worker }
146*35238bceSAndroid Build Coastguard Worker
getEpsFromBits(float value,int numAccurateBits)147*35238bceSAndroid Build Coastguard Worker inline float getEpsFromBits(float value, int numAccurateBits)
148*35238bceSAndroid Build Coastguard Worker {
149*35238bceSAndroid Build Coastguard Worker return getEpsFromMaxUlpDiff(value, getMaxUlpDiffFromBits(numAccurateBits));
150*35238bceSAndroid Build Coastguard Worker }
151*35238bceSAndroid Build Coastguard Worker
getMinMantissaBits(glu::Precision precision)152*35238bceSAndroid Build Coastguard Worker static int getMinMantissaBits(glu::Precision precision)
153*35238bceSAndroid Build Coastguard Worker {
154*35238bceSAndroid Build Coastguard Worker const int bits[] = {
155*35238bceSAndroid Build Coastguard Worker 7, // lowp
156*35238bceSAndroid Build Coastguard Worker 10, // mediump
157*35238bceSAndroid Build Coastguard Worker 23 // highp
158*35238bceSAndroid Build Coastguard Worker };
159*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bits) == glu::PRECISION_LAST);
160*35238bceSAndroid Build Coastguard Worker DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(bits)));
161*35238bceSAndroid Build Coastguard Worker return bits[precision];
162*35238bceSAndroid Build Coastguard Worker }
163*35238bceSAndroid Build Coastguard Worker
getMaxNormalizedValueExponent(glu::Precision precision)164*35238bceSAndroid Build Coastguard Worker static int getMaxNormalizedValueExponent(glu::Precision precision)
165*35238bceSAndroid Build Coastguard Worker {
166*35238bceSAndroid Build Coastguard Worker const int exponent[] = {
167*35238bceSAndroid Build Coastguard Worker 0, // lowp
168*35238bceSAndroid Build Coastguard Worker 13, // mediump
169*35238bceSAndroid Build Coastguard Worker 127 // highp
170*35238bceSAndroid Build Coastguard Worker };
171*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(exponent) == glu::PRECISION_LAST);
172*35238bceSAndroid Build Coastguard Worker DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(exponent)));
173*35238bceSAndroid Build Coastguard Worker return exponent[precision];
174*35238bceSAndroid Build Coastguard Worker }
175*35238bceSAndroid Build Coastguard Worker
getMinNormalizedValueExponent(glu::Precision precision)176*35238bceSAndroid Build Coastguard Worker static int getMinNormalizedValueExponent(glu::Precision precision)
177*35238bceSAndroid Build Coastguard Worker {
178*35238bceSAndroid Build Coastguard Worker const int exponent[] = {
179*35238bceSAndroid Build Coastguard Worker -7, // lowp
180*35238bceSAndroid Build Coastguard Worker -13, // mediump
181*35238bceSAndroid Build Coastguard Worker -126 // highp
182*35238bceSAndroid Build Coastguard Worker };
183*35238bceSAndroid Build Coastguard Worker DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(exponent) == glu::PRECISION_LAST);
184*35238bceSAndroid Build Coastguard Worker DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(exponent)));
185*35238bceSAndroid Build Coastguard Worker return exponent[precision];
186*35238bceSAndroid Build Coastguard Worker }
187*35238bceSAndroid Build Coastguard Worker
makeFloatRepresentable(float f,glu::Precision precision)188*35238bceSAndroid Build Coastguard Worker static float makeFloatRepresentable(float f, glu::Precision precision)
189*35238bceSAndroid Build Coastguard Worker {
190*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP)
191*35238bceSAndroid Build Coastguard Worker {
192*35238bceSAndroid Build Coastguard Worker // \note: assuming f is not extended-precision
193*35238bceSAndroid Build Coastguard Worker return f;
194*35238bceSAndroid Build Coastguard Worker }
195*35238bceSAndroid Build Coastguard Worker else
196*35238bceSAndroid Build Coastguard Worker {
197*35238bceSAndroid Build Coastguard Worker const int numMantissaBits = getMinMantissaBits(precision);
198*35238bceSAndroid Build Coastguard Worker const int maxNormalizedValueExponent = getMaxNormalizedValueExponent(precision);
199*35238bceSAndroid Build Coastguard Worker const int minNormalizedValueExponent = getMinNormalizedValueExponent(precision);
200*35238bceSAndroid Build Coastguard Worker const uint32_t representableMantissaMask = ((uint32_t(1) << numMantissaBits) - 1)
201*35238bceSAndroid Build Coastguard Worker << (23 - (uint32_t)numMantissaBits);
202*35238bceSAndroid Build Coastguard Worker const float largestRepresentableValue =
203*35238bceSAndroid Build Coastguard Worker tcu::Float32::constructBits(+1, maxNormalizedValueExponent,
204*35238bceSAndroid Build Coastguard Worker ((1u << numMantissaBits) - 1u) << (23u - (uint32_t)numMantissaBits))
205*35238bceSAndroid Build Coastguard Worker .asFloat();
206*35238bceSAndroid Build Coastguard Worker const bool zeroNotRepresentable = (precision == glu::PRECISION_LOWP);
207*35238bceSAndroid Build Coastguard Worker
208*35238bceSAndroid Build Coastguard Worker // if zero is not required to be representable, use smallest positive non-subnormal value
209*35238bceSAndroid Build Coastguard Worker const float zeroValue = (zeroNotRepresentable) ?
210*35238bceSAndroid Build Coastguard Worker (tcu::Float32::constructBits(+1, minNormalizedValueExponent, 1).asFloat()) :
211*35238bceSAndroid Build Coastguard Worker (0.0f);
212*35238bceSAndroid Build Coastguard Worker
213*35238bceSAndroid Build Coastguard Worker const tcu::Float32 float32Representation(f);
214*35238bceSAndroid Build Coastguard Worker
215*35238bceSAndroid Build Coastguard Worker if (float32Representation.exponent() < minNormalizedValueExponent)
216*35238bceSAndroid Build Coastguard Worker {
217*35238bceSAndroid Build Coastguard Worker // flush too small values to zero
218*35238bceSAndroid Build Coastguard Worker return zeroValue;
219*35238bceSAndroid Build Coastguard Worker }
220*35238bceSAndroid Build Coastguard Worker else if (float32Representation.exponent() > maxNormalizedValueExponent)
221*35238bceSAndroid Build Coastguard Worker {
222*35238bceSAndroid Build Coastguard Worker // clamp too large values
223*35238bceSAndroid Build Coastguard Worker return (float32Representation.sign() == +1) ? (largestRepresentableValue) : (-largestRepresentableValue);
224*35238bceSAndroid Build Coastguard Worker }
225*35238bceSAndroid Build Coastguard Worker else
226*35238bceSAndroid Build Coastguard Worker {
227*35238bceSAndroid Build Coastguard Worker // remove unrepresentable mantissa bits
228*35238bceSAndroid Build Coastguard Worker const tcu::Float32 targetRepresentation(
229*35238bceSAndroid Build Coastguard Worker tcu::Float32::constructBits(float32Representation.sign(), float32Representation.exponent(),
230*35238bceSAndroid Build Coastguard Worker float32Representation.mantissaBits() & representableMantissaMask));
231*35238bceSAndroid Build Coastguard Worker
232*35238bceSAndroid Build Coastguard Worker return targetRepresentation.asFloat();
233*35238bceSAndroid Build Coastguard Worker }
234*35238bceSAndroid Build Coastguard Worker }
235*35238bceSAndroid Build Coastguard Worker }
236*35238bceSAndroid Build Coastguard Worker
237*35238bceSAndroid Build Coastguard Worker // CommonFunctionCase
238*35238bceSAndroid Build Coastguard Worker
239*35238bceSAndroid Build Coastguard Worker class CommonFunctionCase : public TestCase
240*35238bceSAndroid Build Coastguard Worker {
241*35238bceSAndroid Build Coastguard Worker public:
242*35238bceSAndroid Build Coastguard Worker CommonFunctionCase(Context &context, const char *name, const char *description, glu::ShaderType shaderType);
243*35238bceSAndroid Build Coastguard Worker ~CommonFunctionCase(void);
244*35238bceSAndroid Build Coastguard Worker
245*35238bceSAndroid Build Coastguard Worker void init(void);
246*35238bceSAndroid Build Coastguard Worker void deinit(void);
247*35238bceSAndroid Build Coastguard Worker IterateResult iterate(void);
248*35238bceSAndroid Build Coastguard Worker
249*35238bceSAndroid Build Coastguard Worker protected:
250*35238bceSAndroid Build Coastguard Worker CommonFunctionCase(const CommonFunctionCase &other);
251*35238bceSAndroid Build Coastguard Worker CommonFunctionCase &operator=(const CommonFunctionCase &other);
252*35238bceSAndroid Build Coastguard Worker
253*35238bceSAndroid Build Coastguard Worker virtual void getInputValues(int numValues, void *const *values) const = 0;
254*35238bceSAndroid Build Coastguard Worker virtual bool compare(const void *const *inputs, const void *const *outputs) = 0;
255*35238bceSAndroid Build Coastguard Worker
256*35238bceSAndroid Build Coastguard Worker glu::ShaderType m_shaderType;
257*35238bceSAndroid Build Coastguard Worker ShaderSpec m_spec;
258*35238bceSAndroid Build Coastguard Worker int m_numValues;
259*35238bceSAndroid Build Coastguard Worker
260*35238bceSAndroid Build Coastguard Worker std::ostringstream m_failMsg; //!< Comparison failure help message.
261*35238bceSAndroid Build Coastguard Worker
262*35238bceSAndroid Build Coastguard Worker private:
263*35238bceSAndroid Build Coastguard Worker ShaderExecutor *m_executor;
264*35238bceSAndroid Build Coastguard Worker };
265*35238bceSAndroid Build Coastguard Worker
CommonFunctionCase(Context & context,const char * name,const char * description,glu::ShaderType shaderType)266*35238bceSAndroid Build Coastguard Worker CommonFunctionCase::CommonFunctionCase(Context &context, const char *name, const char *description,
267*35238bceSAndroid Build Coastguard Worker glu::ShaderType shaderType)
268*35238bceSAndroid Build Coastguard Worker : TestCase(context, name, description)
269*35238bceSAndroid Build Coastguard Worker , m_shaderType(shaderType)
270*35238bceSAndroid Build Coastguard Worker , m_numValues(100)
271*35238bceSAndroid Build Coastguard Worker , m_executor(DE_NULL)
272*35238bceSAndroid Build Coastguard Worker {
273*35238bceSAndroid Build Coastguard Worker }
274*35238bceSAndroid Build Coastguard Worker
~CommonFunctionCase(void)275*35238bceSAndroid Build Coastguard Worker CommonFunctionCase::~CommonFunctionCase(void)
276*35238bceSAndroid Build Coastguard Worker {
277*35238bceSAndroid Build Coastguard Worker CommonFunctionCase::deinit();
278*35238bceSAndroid Build Coastguard Worker }
279*35238bceSAndroid Build Coastguard Worker
init(void)280*35238bceSAndroid Build Coastguard Worker void CommonFunctionCase::init(void)
281*35238bceSAndroid Build Coastguard Worker {
282*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!m_executor);
283*35238bceSAndroid Build Coastguard Worker
284*35238bceSAndroid Build Coastguard Worker glu::ContextType contextType = m_context.getRenderContext().getType();
285*35238bceSAndroid Build Coastguard Worker m_spec.version = glu::getContextTypeGLSLVersion(contextType);
286*35238bceSAndroid Build Coastguard Worker
287*35238bceSAndroid Build Coastguard Worker m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec);
288*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << m_executor;
289*35238bceSAndroid Build Coastguard Worker
290*35238bceSAndroid Build Coastguard Worker if (!m_executor->isOk())
291*35238bceSAndroid Build Coastguard Worker throw tcu::TestError("Compile failed");
292*35238bceSAndroid Build Coastguard Worker }
293*35238bceSAndroid Build Coastguard Worker
deinit(void)294*35238bceSAndroid Build Coastguard Worker void CommonFunctionCase::deinit(void)
295*35238bceSAndroid Build Coastguard Worker {
296*35238bceSAndroid Build Coastguard Worker delete m_executor;
297*35238bceSAndroid Build Coastguard Worker m_executor = DE_NULL;
298*35238bceSAndroid Build Coastguard Worker }
299*35238bceSAndroid Build Coastguard Worker
getScalarSizes(const vector<Symbol> & symbols)300*35238bceSAndroid Build Coastguard Worker static vector<int> getScalarSizes(const vector<Symbol> &symbols)
301*35238bceSAndroid Build Coastguard Worker {
302*35238bceSAndroid Build Coastguard Worker vector<int> sizes(symbols.size());
303*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < (int)symbols.size(); ++ndx)
304*35238bceSAndroid Build Coastguard Worker sizes[ndx] = symbols[ndx].varType.getScalarSize();
305*35238bceSAndroid Build Coastguard Worker return sizes;
306*35238bceSAndroid Build Coastguard Worker }
307*35238bceSAndroid Build Coastguard Worker
computeTotalScalarSize(const vector<Symbol> & symbols)308*35238bceSAndroid Build Coastguard Worker static int computeTotalScalarSize(const vector<Symbol> &symbols)
309*35238bceSAndroid Build Coastguard Worker {
310*35238bceSAndroid Build Coastguard Worker int totalSize = 0;
311*35238bceSAndroid Build Coastguard Worker for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym)
312*35238bceSAndroid Build Coastguard Worker totalSize += sym->varType.getScalarSize();
313*35238bceSAndroid Build Coastguard Worker return totalSize;
314*35238bceSAndroid Build Coastguard Worker }
315*35238bceSAndroid Build Coastguard Worker
getInputOutputPointers(const vector<Symbol> & symbols,vector<uint32_t> & data,const int numValues)316*35238bceSAndroid Build Coastguard Worker static vector<void *> getInputOutputPointers(const vector<Symbol> &symbols, vector<uint32_t> &data, const int numValues)
317*35238bceSAndroid Build Coastguard Worker {
318*35238bceSAndroid Build Coastguard Worker vector<void *> pointers(symbols.size());
319*35238bceSAndroid Build Coastguard Worker int curScalarOffset = 0;
320*35238bceSAndroid Build Coastguard Worker
321*35238bceSAndroid Build Coastguard Worker for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx)
322*35238bceSAndroid Build Coastguard Worker {
323*35238bceSAndroid Build Coastguard Worker const Symbol &var = symbols[varNdx];
324*35238bceSAndroid Build Coastguard Worker const int scalarSize = var.varType.getScalarSize();
325*35238bceSAndroid Build Coastguard Worker
326*35238bceSAndroid Build Coastguard Worker // Uses planar layout as input/output specs do not support strides.
327*35238bceSAndroid Build Coastguard Worker pointers[varNdx] = &data[curScalarOffset];
328*35238bceSAndroid Build Coastguard Worker curScalarOffset += scalarSize * numValues;
329*35238bceSAndroid Build Coastguard Worker }
330*35238bceSAndroid Build Coastguard Worker
331*35238bceSAndroid Build Coastguard Worker DE_ASSERT(curScalarOffset == (int)data.size());
332*35238bceSAndroid Build Coastguard Worker
333*35238bceSAndroid Build Coastguard Worker return pointers;
334*35238bceSAndroid Build Coastguard Worker }
335*35238bceSAndroid Build Coastguard Worker
336*35238bceSAndroid Build Coastguard Worker // \todo [2013-08-08 pyry] Make generic utility and move to glu?
337*35238bceSAndroid Build Coastguard Worker
338*35238bceSAndroid Build Coastguard Worker struct HexFloat
339*35238bceSAndroid Build Coastguard Worker {
340*35238bceSAndroid Build Coastguard Worker const float value;
HexFloatdeqp::gles31::Functional::HexFloat341*35238bceSAndroid Build Coastguard Worker HexFloat(const float value_) : value(value_)
342*35238bceSAndroid Build Coastguard Worker {
343*35238bceSAndroid Build Coastguard Worker }
344*35238bceSAndroid Build Coastguard Worker };
345*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & str,const HexFloat & v)346*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const HexFloat &v)
347*35238bceSAndroid Build Coastguard Worker {
348*35238bceSAndroid Build Coastguard Worker return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits());
349*35238bceSAndroid Build Coastguard Worker }
350*35238bceSAndroid Build Coastguard Worker
351*35238bceSAndroid Build Coastguard Worker struct HexBool
352*35238bceSAndroid Build Coastguard Worker {
353*35238bceSAndroid Build Coastguard Worker const uint32_t value;
HexBooldeqp::gles31::Functional::HexBool354*35238bceSAndroid Build Coastguard Worker HexBool(const uint32_t value_) : value(value_)
355*35238bceSAndroid Build Coastguard Worker {
356*35238bceSAndroid Build Coastguard Worker }
357*35238bceSAndroid Build Coastguard Worker };
358*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & str,const HexBool & v)359*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const HexBool &v)
360*35238bceSAndroid Build Coastguard Worker {
361*35238bceSAndroid Build Coastguard Worker return str << (v.value ? "true" : "false") << " / " << tcu::toHex(v.value);
362*35238bceSAndroid Build Coastguard Worker }
363*35238bceSAndroid Build Coastguard Worker
364*35238bceSAndroid Build Coastguard Worker struct VarValue
365*35238bceSAndroid Build Coastguard Worker {
366*35238bceSAndroid Build Coastguard Worker const glu::VarType &type;
367*35238bceSAndroid Build Coastguard Worker const void *value;
368*35238bceSAndroid Build Coastguard Worker
VarValuedeqp::gles31::Functional::VarValue369*35238bceSAndroid Build Coastguard Worker VarValue(const glu::VarType &type_, const void *value_) : type(type_), value(value_)
370*35238bceSAndroid Build Coastguard Worker {
371*35238bceSAndroid Build Coastguard Worker }
372*35238bceSAndroid Build Coastguard Worker };
373*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & str,const VarValue & varValue)374*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const VarValue &varValue)
375*35238bceSAndroid Build Coastguard Worker {
376*35238bceSAndroid Build Coastguard Worker DE_ASSERT(varValue.type.isBasicType());
377*35238bceSAndroid Build Coastguard Worker
378*35238bceSAndroid Build Coastguard Worker const glu::DataType basicType = varValue.type.getBasicType();
379*35238bceSAndroid Build Coastguard Worker const glu::DataType scalarType = glu::getDataTypeScalarType(basicType);
380*35238bceSAndroid Build Coastguard Worker const int numComponents = glu::getDataTypeScalarSize(basicType);
381*35238bceSAndroid Build Coastguard Worker
382*35238bceSAndroid Build Coastguard Worker if (numComponents > 1)
383*35238bceSAndroid Build Coastguard Worker str << glu::getDataTypeName(basicType) << "(";
384*35238bceSAndroid Build Coastguard Worker
385*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < numComponents; compNdx++)
386*35238bceSAndroid Build Coastguard Worker {
387*35238bceSAndroid Build Coastguard Worker if (compNdx != 0)
388*35238bceSAndroid Build Coastguard Worker str << ", ";
389*35238bceSAndroid Build Coastguard Worker
390*35238bceSAndroid Build Coastguard Worker switch (scalarType)
391*35238bceSAndroid Build Coastguard Worker {
392*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT:
393*35238bceSAndroid Build Coastguard Worker str << HexFloat(((const float *)varValue.value)[compNdx]);
394*35238bceSAndroid Build Coastguard Worker break;
395*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT:
396*35238bceSAndroid Build Coastguard Worker str << ((const int32_t *)varValue.value)[compNdx];
397*35238bceSAndroid Build Coastguard Worker break;
398*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT:
399*35238bceSAndroid Build Coastguard Worker str << tcu::toHex(((const uint32_t *)varValue.value)[compNdx]);
400*35238bceSAndroid Build Coastguard Worker break;
401*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL:
402*35238bceSAndroid Build Coastguard Worker str << HexBool(((const uint32_t *)varValue.value)[compNdx]);
403*35238bceSAndroid Build Coastguard Worker break;
404*35238bceSAndroid Build Coastguard Worker
405*35238bceSAndroid Build Coastguard Worker default:
406*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
407*35238bceSAndroid Build Coastguard Worker }
408*35238bceSAndroid Build Coastguard Worker }
409*35238bceSAndroid Build Coastguard Worker
410*35238bceSAndroid Build Coastguard Worker if (numComponents > 1)
411*35238bceSAndroid Build Coastguard Worker str << ")";
412*35238bceSAndroid Build Coastguard Worker
413*35238bceSAndroid Build Coastguard Worker return str;
414*35238bceSAndroid Build Coastguard Worker }
415*35238bceSAndroid Build Coastguard Worker
iterate(void)416*35238bceSAndroid Build Coastguard Worker CommonFunctionCase::IterateResult CommonFunctionCase::iterate(void)
417*35238bceSAndroid Build Coastguard Worker {
418*35238bceSAndroid Build Coastguard Worker const int numInputScalars = computeTotalScalarSize(m_spec.inputs);
419*35238bceSAndroid Build Coastguard Worker const int numOutputScalars = computeTotalScalarSize(m_spec.outputs);
420*35238bceSAndroid Build Coastguard Worker vector<uint32_t> inputData(numInputScalars * m_numValues);
421*35238bceSAndroid Build Coastguard Worker vector<uint32_t> outputData(numOutputScalars * m_numValues);
422*35238bceSAndroid Build Coastguard Worker const vector<void *> inputPointers = getInputOutputPointers(m_spec.inputs, inputData, m_numValues);
423*35238bceSAndroid Build Coastguard Worker const vector<void *> outputPointers = getInputOutputPointers(m_spec.outputs, outputData, m_numValues);
424*35238bceSAndroid Build Coastguard Worker
425*35238bceSAndroid Build Coastguard Worker // Initialize input data.
426*35238bceSAndroid Build Coastguard Worker getInputValues(m_numValues, &inputPointers[0]);
427*35238bceSAndroid Build Coastguard Worker
428*35238bceSAndroid Build Coastguard Worker // Execute shader.
429*35238bceSAndroid Build Coastguard Worker m_executor->useProgram();
430*35238bceSAndroid Build Coastguard Worker m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]);
431*35238bceSAndroid Build Coastguard Worker
432*35238bceSAndroid Build Coastguard Worker // Compare results.
433*35238bceSAndroid Build Coastguard Worker {
434*35238bceSAndroid Build Coastguard Worker const vector<int> inScalarSizes = getScalarSizes(m_spec.inputs);
435*35238bceSAndroid Build Coastguard Worker const vector<int> outScalarSizes = getScalarSizes(m_spec.outputs);
436*35238bceSAndroid Build Coastguard Worker vector<void *> curInputPtr(inputPointers.size());
437*35238bceSAndroid Build Coastguard Worker vector<void *> curOutputPtr(outputPointers.size());
438*35238bceSAndroid Build Coastguard Worker int numFailed = 0;
439*35238bceSAndroid Build Coastguard Worker
440*35238bceSAndroid Build Coastguard Worker for (int valNdx = 0; valNdx < m_numValues; valNdx++)
441*35238bceSAndroid Build Coastguard Worker {
442*35238bceSAndroid Build Coastguard Worker // Set up pointers for comparison.
443*35238bceSAndroid Build Coastguard Worker for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx)
444*35238bceSAndroid Build Coastguard Worker curInputPtr[inNdx] = (uint32_t *)inputPointers[inNdx] + inScalarSizes[inNdx] * valNdx;
445*35238bceSAndroid Build Coastguard Worker
446*35238bceSAndroid Build Coastguard Worker for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx)
447*35238bceSAndroid Build Coastguard Worker curOutputPtr[outNdx] = (uint32_t *)outputPointers[outNdx] + outScalarSizes[outNdx] * valNdx;
448*35238bceSAndroid Build Coastguard Worker
449*35238bceSAndroid Build Coastguard Worker if (!compare(&curInputPtr[0], &curOutputPtr[0]))
450*35238bceSAndroid Build Coastguard Worker {
451*35238bceSAndroid Build Coastguard Worker // \todo [2013-08-08 pyry] We probably want to log reference value as well?
452*35238bceSAndroid Build Coastguard Worker
453*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n "
454*35238bceSAndroid Build Coastguard Worker << m_failMsg.str() << TestLog::EndMessage;
455*35238bceSAndroid Build Coastguard Worker
456*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << " inputs:" << TestLog::EndMessage;
457*35238bceSAndroid Build Coastguard Worker for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++)
458*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << " " << m_spec.inputs[inNdx].name << " = "
459*35238bceSAndroid Build Coastguard Worker << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx])
460*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
461*35238bceSAndroid Build Coastguard Worker
462*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << " outputs:" << TestLog::EndMessage;
463*35238bceSAndroid Build Coastguard Worker for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++)
464*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << " " << m_spec.outputs[outNdx].name << " = "
465*35238bceSAndroid Build Coastguard Worker << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx])
466*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
467*35238bceSAndroid Build Coastguard Worker
468*35238bceSAndroid Build Coastguard Worker m_failMsg.str("");
469*35238bceSAndroid Build Coastguard Worker m_failMsg.clear();
470*35238bceSAndroid Build Coastguard Worker numFailed += 1;
471*35238bceSAndroid Build Coastguard Worker }
472*35238bceSAndroid Build Coastguard Worker }
473*35238bceSAndroid Build Coastguard Worker
474*35238bceSAndroid Build Coastguard Worker m_testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed"
475*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
476*35238bceSAndroid Build Coastguard Worker
477*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
478*35238bceSAndroid Build Coastguard Worker numFailed == 0 ? "Pass" : "Result comparison failed");
479*35238bceSAndroid Build Coastguard Worker }
480*35238bceSAndroid Build Coastguard Worker
481*35238bceSAndroid Build Coastguard Worker return STOP;
482*35238bceSAndroid Build Coastguard Worker }
483*35238bceSAndroid Build Coastguard Worker
getCommonFuncCaseName(glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)484*35238bceSAndroid Build Coastguard Worker static std::string getCommonFuncCaseName(glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
485*35238bceSAndroid Build Coastguard Worker {
486*35238bceSAndroid Build Coastguard Worker return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType);
487*35238bceSAndroid Build Coastguard Worker }
488*35238bceSAndroid Build Coastguard Worker
489*35238bceSAndroid Build Coastguard Worker class AbsCase : public CommonFunctionCase
490*35238bceSAndroid Build Coastguard Worker {
491*35238bceSAndroid Build Coastguard Worker public:
AbsCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)492*35238bceSAndroid Build Coastguard Worker AbsCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
493*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "abs", shaderType)
494*35238bceSAndroid Build Coastguard Worker {
495*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
496*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
497*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = abs(in0);";
498*35238bceSAndroid Build Coastguard Worker }
499*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const500*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
501*35238bceSAndroid Build Coastguard Worker {
502*35238bceSAndroid Build Coastguard Worker const Vec2 floatRanges[] = {
503*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
504*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
505*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
506*35238bceSAndroid Build Coastguard Worker };
507*35238bceSAndroid Build Coastguard Worker const IVec2 intRanges[] = {IVec2(-(1 << 7) + 1, (1 << 7) - 1), IVec2(-(1 << 15) + 1, (1 << 15) - 1),
508*35238bceSAndroid Build Coastguard Worker IVec2(0x80000001, 0x7fffffff)};
509*35238bceSAndroid Build Coastguard Worker
510*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0x235facu);
511*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
512*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
513*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
514*35238bceSAndroid Build Coastguard Worker
515*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeFloatOrVec(type))
516*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), values[0],
517*35238bceSAndroid Build Coastguard Worker numValues * scalarSize);
518*35238bceSAndroid Build Coastguard Worker else
519*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), values[0],
520*35238bceSAndroid Build Coastguard Worker numValues * scalarSize);
521*35238bceSAndroid Build Coastguard Worker }
522*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)523*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
524*35238bceSAndroid Build Coastguard Worker {
525*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
526*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
527*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
528*35238bceSAndroid Build Coastguard Worker
529*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeFloatOrVec(type))
530*35238bceSAndroid Build Coastguard Worker {
531*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
532*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = (1u << (23 - mantissaBits)) - 1u;
533*35238bceSAndroid Build Coastguard Worker
534*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
535*35238bceSAndroid Build Coastguard Worker {
536*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
537*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
538*35238bceSAndroid Build Coastguard Worker const float ref0 = de::abs(in0);
539*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff0 = getUlpDiff(out0, ref0);
540*35238bceSAndroid Build Coastguard Worker
541*35238bceSAndroid Build Coastguard Worker if (ulpDiff0 > maxUlpDiff)
542*35238bceSAndroid Build Coastguard Worker {
543*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold "
544*35238bceSAndroid Build Coastguard Worker << maxUlpDiff << ", got ULP diff " << ulpDiff0;
545*35238bceSAndroid Build Coastguard Worker return false;
546*35238bceSAndroid Build Coastguard Worker }
547*35238bceSAndroid Build Coastguard Worker }
548*35238bceSAndroid Build Coastguard Worker }
549*35238bceSAndroid Build Coastguard Worker else
550*35238bceSAndroid Build Coastguard Worker {
551*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
552*35238bceSAndroid Build Coastguard Worker {
553*35238bceSAndroid Build Coastguard Worker const int in0 = ((const int *)inputs[0])[compNdx];
554*35238bceSAndroid Build Coastguard Worker const int out0 = ((const int *)outputs[0])[compNdx];
555*35238bceSAndroid Build Coastguard Worker const int ref0 = de::abs(in0);
556*35238bceSAndroid Build Coastguard Worker
557*35238bceSAndroid Build Coastguard Worker if (out0 != ref0)
558*35238bceSAndroid Build Coastguard Worker {
559*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << ref0;
560*35238bceSAndroid Build Coastguard Worker return false;
561*35238bceSAndroid Build Coastguard Worker }
562*35238bceSAndroid Build Coastguard Worker }
563*35238bceSAndroid Build Coastguard Worker }
564*35238bceSAndroid Build Coastguard Worker
565*35238bceSAndroid Build Coastguard Worker return true;
566*35238bceSAndroid Build Coastguard Worker }
567*35238bceSAndroid Build Coastguard Worker };
568*35238bceSAndroid Build Coastguard Worker
569*35238bceSAndroid Build Coastguard Worker class SignCase : public CommonFunctionCase
570*35238bceSAndroid Build Coastguard Worker {
571*35238bceSAndroid Build Coastguard Worker public:
SignCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)572*35238bceSAndroid Build Coastguard Worker SignCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
573*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "sign",
574*35238bceSAndroid Build Coastguard Worker shaderType)
575*35238bceSAndroid Build Coastguard Worker {
576*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
577*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
578*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = sign(in0);";
579*35238bceSAndroid Build Coastguard Worker }
580*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const581*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
582*35238bceSAndroid Build Coastguard Worker {
583*35238bceSAndroid Build Coastguard Worker const Vec2 floatRanges[] = {
584*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
585*35238bceSAndroid Build Coastguard Worker Vec2(-1e4f, 1e4f), // mediump - note: may end up as inf
586*35238bceSAndroid Build Coastguard Worker Vec2(-1e8f, 1e8f) // highp - note: may end up as inf
587*35238bceSAndroid Build Coastguard Worker };
588*35238bceSAndroid Build Coastguard Worker const IVec2 intRanges[] = {IVec2(-(1 << 7), (1 << 7) - 1), IVec2(-(1 << 15), (1 << 15) - 1),
589*35238bceSAndroid Build Coastguard Worker IVec2(0x80000000, 0x7fffffff)};
590*35238bceSAndroid Build Coastguard Worker
591*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0x324u);
592*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
593*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
594*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
595*35238bceSAndroid Build Coastguard Worker
596*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeFloatOrVec(type))
597*35238bceSAndroid Build Coastguard Worker {
598*35238bceSAndroid Build Coastguard Worker // Special cases.
599*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0], (float *)values[0] + scalarSize, +1.0f);
600*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0] + scalarSize * 1, (float *)values[0] + scalarSize * 2, -1.0f);
601*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0] + scalarSize * 2, (float *)values[0] + scalarSize * 3, 0.0f);
602*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(),
603*35238bceSAndroid Build Coastguard Worker (float *)values[0] + scalarSize * 3, (numValues - 3) * scalarSize);
604*35238bceSAndroid Build Coastguard Worker }
605*35238bceSAndroid Build Coastguard Worker else
606*35238bceSAndroid Build Coastguard Worker {
607*35238bceSAndroid Build Coastguard Worker std::fill((int *)values[0], (int *)values[0] + scalarSize, +1);
608*35238bceSAndroid Build Coastguard Worker std::fill((int *)values[0] + scalarSize * 1, (int *)values[0] + scalarSize * 2, -1);
609*35238bceSAndroid Build Coastguard Worker std::fill((int *)values[0] + scalarSize * 2, (int *)values[0] + scalarSize * 3, 0);
610*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(),
611*35238bceSAndroid Build Coastguard Worker (int *)values[0] + scalarSize * 3, (numValues - 3) * scalarSize);
612*35238bceSAndroid Build Coastguard Worker }
613*35238bceSAndroid Build Coastguard Worker }
614*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)615*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
616*35238bceSAndroid Build Coastguard Worker {
617*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
618*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
619*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
620*35238bceSAndroid Build Coastguard Worker
621*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeFloatOrVec(type))
622*35238bceSAndroid Build Coastguard Worker {
623*35238bceSAndroid Build Coastguard Worker // Both highp and mediump should be able to represent -1, 0, and +1 exactly
624*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff =
625*35238bceSAndroid Build Coastguard Worker precision == glu::PRECISION_LOWP ? getMaxUlpDiffFromBits(getMinMantissaBits(precision)) : 0;
626*35238bceSAndroid Build Coastguard Worker
627*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
628*35238bceSAndroid Build Coastguard Worker {
629*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
630*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
631*35238bceSAndroid Build Coastguard Worker const float ref0 = in0 < 0.0f ? -1.0f : in0 > 0.0f ? +1.0f : 0.0f;
632*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff0 = getUlpDiff(out0, ref0);
633*35238bceSAndroid Build Coastguard Worker
634*35238bceSAndroid Build Coastguard Worker if (ulpDiff0 > maxUlpDiff)
635*35238bceSAndroid Build Coastguard Worker {
636*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold "
637*35238bceSAndroid Build Coastguard Worker << maxUlpDiff << ", got ULP diff " << ulpDiff0;
638*35238bceSAndroid Build Coastguard Worker return false;
639*35238bceSAndroid Build Coastguard Worker }
640*35238bceSAndroid Build Coastguard Worker }
641*35238bceSAndroid Build Coastguard Worker }
642*35238bceSAndroid Build Coastguard Worker else
643*35238bceSAndroid Build Coastguard Worker {
644*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
645*35238bceSAndroid Build Coastguard Worker {
646*35238bceSAndroid Build Coastguard Worker const int in0 = ((const int *)inputs[0])[compNdx];
647*35238bceSAndroid Build Coastguard Worker const int out0 = ((const int *)outputs[0])[compNdx];
648*35238bceSAndroid Build Coastguard Worker const int ref0 = in0 < 0 ? -1 : in0 > 0 ? +1 : 0;
649*35238bceSAndroid Build Coastguard Worker
650*35238bceSAndroid Build Coastguard Worker if (out0 != ref0)
651*35238bceSAndroid Build Coastguard Worker {
652*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << ref0;
653*35238bceSAndroid Build Coastguard Worker return false;
654*35238bceSAndroid Build Coastguard Worker }
655*35238bceSAndroid Build Coastguard Worker }
656*35238bceSAndroid Build Coastguard Worker }
657*35238bceSAndroid Build Coastguard Worker
658*35238bceSAndroid Build Coastguard Worker return true;
659*35238bceSAndroid Build Coastguard Worker }
660*35238bceSAndroid Build Coastguard Worker };
661*35238bceSAndroid Build Coastguard Worker
roundEven(float v)662*35238bceSAndroid Build Coastguard Worker static float roundEven(float v)
663*35238bceSAndroid Build Coastguard Worker {
664*35238bceSAndroid Build Coastguard Worker const float q = deFloatFrac(v);
665*35238bceSAndroid Build Coastguard Worker const int truncated = int(v - q);
666*35238bceSAndroid Build Coastguard Worker const int rounded = (q > 0.5f) ? (truncated + 1) : // Rounded up
667*35238bceSAndroid Build Coastguard Worker (q == 0.5f && (truncated % 2 != 0)) ? (truncated + 1) : // Round to nearest even at 0.5
668*35238bceSAndroid Build Coastguard Worker truncated; // Rounded down
669*35238bceSAndroid Build Coastguard Worker
670*35238bceSAndroid Build Coastguard Worker return float(rounded);
671*35238bceSAndroid Build Coastguard Worker }
672*35238bceSAndroid Build Coastguard Worker
673*35238bceSAndroid Build Coastguard Worker class RoundEvenCase : public CommonFunctionCase
674*35238bceSAndroid Build Coastguard Worker {
675*35238bceSAndroid Build Coastguard Worker public:
RoundEvenCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)676*35238bceSAndroid Build Coastguard Worker RoundEvenCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
677*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "roundEven",
678*35238bceSAndroid Build Coastguard Worker shaderType)
679*35238bceSAndroid Build Coastguard Worker {
680*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
681*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
682*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = roundEven(in0);";
683*35238bceSAndroid Build Coastguard Worker }
684*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const685*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
686*35238bceSAndroid Build Coastguard Worker {
687*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
688*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
689*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
690*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
691*35238bceSAndroid Build Coastguard Worker };
692*35238bceSAndroid Build Coastguard Worker
693*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
694*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
695*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
696*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
697*35238bceSAndroid Build Coastguard Worker int numSpecialCases = 0;
698*35238bceSAndroid Build Coastguard Worker
699*35238bceSAndroid Build Coastguard Worker // Special cases.
700*35238bceSAndroid Build Coastguard Worker if (precision != glu::PRECISION_LOWP)
701*35238bceSAndroid Build Coastguard Worker {
702*35238bceSAndroid Build Coastguard Worker DE_ASSERT(numValues >= 20);
703*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < 20; ndx++)
704*35238bceSAndroid Build Coastguard Worker {
705*35238bceSAndroid Build Coastguard Worker const float v = de::clamp(float(ndx) - 10.5f, ranges[precision].x(), ranges[precision].y());
706*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0], (float *)values[0] + scalarSize, v);
707*35238bceSAndroid Build Coastguard Worker numSpecialCases += 1;
708*35238bceSAndroid Build Coastguard Worker }
709*35238bceSAndroid Build Coastguard Worker }
710*35238bceSAndroid Build Coastguard Worker
711*35238bceSAndroid Build Coastguard Worker // Random cases.
712*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(),
713*35238bceSAndroid Build Coastguard Worker (float *)values[0] + numSpecialCases * scalarSize,
714*35238bceSAndroid Build Coastguard Worker (numValues - numSpecialCases) * scalarSize);
715*35238bceSAndroid Build Coastguard Worker
716*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
717*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
718*35238bceSAndroid Build Coastguard Worker {
719*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
720*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
721*35238bceSAndroid Build Coastguard Worker }
722*35238bceSAndroid Build Coastguard Worker }
723*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)724*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
725*35238bceSAndroid Build Coastguard Worker {
726*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
727*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
728*35238bceSAndroid Build Coastguard Worker const bool hasSignedZero = supportsSignedZero(precision);
729*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
730*35238bceSAndroid Build Coastguard Worker
731*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
732*35238bceSAndroid Build Coastguard Worker {
733*35238bceSAndroid Build Coastguard Worker // Require exact rounding result.
734*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
735*35238bceSAndroid Build Coastguard Worker {
736*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
737*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
738*35238bceSAndroid Build Coastguard Worker const float ref = roundEven(in0);
739*35238bceSAndroid Build Coastguard Worker
740*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
741*35238bceSAndroid Build Coastguard Worker
742*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
743*35238bceSAndroid Build Coastguard Worker {
744*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
745*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
746*35238bceSAndroid Build Coastguard Worker return false;
747*35238bceSAndroid Build Coastguard Worker }
748*35238bceSAndroid Build Coastguard Worker }
749*35238bceSAndroid Build Coastguard Worker }
750*35238bceSAndroid Build Coastguard Worker else
751*35238bceSAndroid Build Coastguard Worker {
752*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
753*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
754*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
755*35238bceSAndroid Build Coastguard Worker
756*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
757*35238bceSAndroid Build Coastguard Worker {
758*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
759*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
760*35238bceSAndroid Build Coastguard Worker const int minRes = int(roundEven(in0 - eps));
761*35238bceSAndroid Build Coastguard Worker const int maxRes = int(roundEven(in0 + eps));
762*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
763*35238bceSAndroid Build Coastguard Worker
764*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
765*35238bceSAndroid Build Coastguard Worker {
766*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
767*35238bceSAndroid Build Coastguard Worker
768*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
769*35238bceSAndroid Build Coastguard Worker {
770*35238bceSAndroid Build Coastguard Worker anyOk = true;
771*35238bceSAndroid Build Coastguard Worker break;
772*35238bceSAndroid Build Coastguard Worker }
773*35238bceSAndroid Build Coastguard Worker }
774*35238bceSAndroid Build Coastguard Worker
775*35238bceSAndroid Build Coastguard Worker if (!anyOk)
776*35238bceSAndroid Build Coastguard Worker {
777*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
778*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
779*35238bceSAndroid Build Coastguard Worker return false;
780*35238bceSAndroid Build Coastguard Worker }
781*35238bceSAndroid Build Coastguard Worker }
782*35238bceSAndroid Build Coastguard Worker }
783*35238bceSAndroid Build Coastguard Worker
784*35238bceSAndroid Build Coastguard Worker return true;
785*35238bceSAndroid Build Coastguard Worker }
786*35238bceSAndroid Build Coastguard Worker };
787*35238bceSAndroid Build Coastguard Worker
788*35238bceSAndroid Build Coastguard Worker class ModfCase : public CommonFunctionCase
789*35238bceSAndroid Build Coastguard Worker {
790*35238bceSAndroid Build Coastguard Worker public:
ModfCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)791*35238bceSAndroid Build Coastguard Worker ModfCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
792*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "modf",
793*35238bceSAndroid Build Coastguard Worker shaderType)
794*35238bceSAndroid Build Coastguard Worker {
795*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
796*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
797*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out1", glu::VarType(baseType, precision)));
798*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = modf(in0, out1);";
799*35238bceSAndroid Build Coastguard Worker }
800*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const801*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
802*35238bceSAndroid Build Coastguard Worker {
803*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
804*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
805*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
806*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
807*35238bceSAndroid Build Coastguard Worker };
808*35238bceSAndroid Build Coastguard Worker
809*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
810*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
811*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
812*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
813*35238bceSAndroid Build Coastguard Worker
814*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues * scalarSize);
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 bool hasZeroSign = supportsSignedZero(precision);
822*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
823*35238bceSAndroid Build Coastguard Worker
824*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
825*35238bceSAndroid Build Coastguard Worker
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 float out0 = ((const float *)outputs[0])[compNdx];
830*35238bceSAndroid Build Coastguard Worker const float out1 = ((const float *)outputs[1])[compNdx];
831*35238bceSAndroid Build Coastguard Worker
832*35238bceSAndroid Build Coastguard Worker const float refOut1 = float(int(in0));
833*35238bceSAndroid Build Coastguard Worker const float refOut0 = in0 - refOut1;
834*35238bceSAndroid Build Coastguard Worker
835*35238bceSAndroid Build Coastguard Worker const int bitsLost = precision != glu::PRECISION_HIGHP ? numBitsLostInOp(in0, refOut0) : 0;
836*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(de::max(mantissaBits - bitsLost, 0));
837*35238bceSAndroid Build Coastguard Worker
838*35238bceSAndroid Build Coastguard Worker const float resSum = out0 + out1;
839*35238bceSAndroid Build Coastguard Worker
840*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasZeroSign ? getUlpDiff(resSum, in0) : getUlpDiffIgnoreZeroSign(resSum, in0);
841*35238bceSAndroid Build Coastguard Worker
842*35238bceSAndroid Build Coastguard Worker if (ulpDiff > maxUlpDiff)
843*35238bceSAndroid Build Coastguard Worker {
844*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = (" << HexFloat(refOut0) << ") + (" << HexFloat(refOut1)
845*35238bceSAndroid Build Coastguard Worker << ") = " << HexFloat(in0) << " with ULP threshold " << tcu::toHex(maxUlpDiff)
846*35238bceSAndroid Build Coastguard Worker << ", got ULP diff " << tcu::toHex(ulpDiff);
847*35238bceSAndroid Build Coastguard Worker return false;
848*35238bceSAndroid Build Coastguard Worker }
849*35238bceSAndroid Build Coastguard Worker }
850*35238bceSAndroid Build Coastguard Worker
851*35238bceSAndroid Build Coastguard Worker return true;
852*35238bceSAndroid Build Coastguard Worker }
853*35238bceSAndroid Build Coastguard Worker };
854*35238bceSAndroid Build Coastguard Worker
855*35238bceSAndroid Build Coastguard Worker class IsnanCase : public CommonFunctionCase
856*35238bceSAndroid Build Coastguard Worker {
857*35238bceSAndroid Build Coastguard Worker public:
IsnanCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)858*35238bceSAndroid Build Coastguard Worker IsnanCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
859*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isnan",
860*35238bceSAndroid Build Coastguard Worker shaderType)
861*35238bceSAndroid Build Coastguard Worker {
862*35238bceSAndroid Build Coastguard Worker DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
863*35238bceSAndroid Build Coastguard Worker
864*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
865*35238bceSAndroid Build Coastguard Worker const glu::DataType boolType = vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
866*35238bceSAndroid Build Coastguard Worker
867*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
868*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
869*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = isnan(in0);";
870*35238bceSAndroid Build Coastguard Worker }
871*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const872*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
873*35238bceSAndroid Build Coastguard Worker {
874*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xc2a39fu);
875*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
876*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
877*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
878*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
879*35238bceSAndroid Build Coastguard Worker const uint32_t mantissaMask = ~getMaxUlpDiffFromBits(mantissaBits) & ((1u << 23) - 1u);
880*35238bceSAndroid Build Coastguard Worker
881*35238bceSAndroid Build Coastguard Worker for (int valNdx = 0; valNdx < numValues * scalarSize; valNdx++)
882*35238bceSAndroid Build Coastguard Worker {
883*35238bceSAndroid Build Coastguard Worker const bool isNan = rnd.getFloat() > 0.3f;
884*35238bceSAndroid Build Coastguard Worker const bool isInf = !isNan && rnd.getFloat() > 0.4f;
885*35238bceSAndroid Build Coastguard Worker const uint32_t mantissa = !isInf ? ((1u << 22) | (rnd.getUint32() & mantissaMask)) : 0;
886*35238bceSAndroid Build Coastguard Worker const uint32_t exp = !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
887*35238bceSAndroid Build Coastguard Worker const uint32_t sign = rnd.getUint32() & 0x1u;
888*35238bceSAndroid Build Coastguard Worker const uint32_t value = (sign << 31) | (exp << 23) | mantissa;
889*35238bceSAndroid Build Coastguard Worker
890*35238bceSAndroid Build Coastguard Worker DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
891*35238bceSAndroid Build Coastguard Worker
892*35238bceSAndroid Build Coastguard Worker ((uint32_t *)values[0])[valNdx] = value;
893*35238bceSAndroid Build Coastguard Worker }
894*35238bceSAndroid Build Coastguard Worker }
895*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)896*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
897*35238bceSAndroid Build Coastguard Worker {
898*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
899*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
900*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
901*35238bceSAndroid Build Coastguard Worker
902*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP)
903*35238bceSAndroid Build Coastguard Worker {
904*35238bceSAndroid Build Coastguard Worker // Only highp is required to support inf/nan
905*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
906*35238bceSAndroid Build Coastguard Worker {
907*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
908*35238bceSAndroid Build Coastguard Worker const bool out0 = ((const uint32_t *)outputs[0])[compNdx] != 0;
909*35238bceSAndroid Build Coastguard Worker const bool ref = tcu::Float32(in0).isNaN();
910*35238bceSAndroid Build Coastguard Worker
911*35238bceSAndroid Build Coastguard Worker if (out0 != ref)
912*35238bceSAndroid Build Coastguard Worker {
913*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << (ref ? "true" : "false");
914*35238bceSAndroid Build Coastguard Worker return false;
915*35238bceSAndroid Build Coastguard Worker }
916*35238bceSAndroid Build Coastguard Worker }
917*35238bceSAndroid Build Coastguard Worker }
918*35238bceSAndroid Build Coastguard Worker else if (precision == glu::PRECISION_MEDIUMP || precision == glu::PRECISION_LOWP)
919*35238bceSAndroid Build Coastguard Worker {
920*35238bceSAndroid Build Coastguard Worker // NaN support is optional, check that inputs that are not NaN don't result in true.
921*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
922*35238bceSAndroid Build Coastguard Worker {
923*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
924*35238bceSAndroid Build Coastguard Worker const bool out0 = ((const uint32_t *)outputs[0])[compNdx] != 0;
925*35238bceSAndroid Build Coastguard Worker const bool ref = tcu::Float32(in0).isNaN();
926*35238bceSAndroid Build Coastguard Worker
927*35238bceSAndroid Build Coastguard Worker if (!ref && out0)
928*35238bceSAndroid Build Coastguard Worker {
929*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << (ref ? "true" : "false");
930*35238bceSAndroid Build Coastguard Worker return false;
931*35238bceSAndroid Build Coastguard Worker }
932*35238bceSAndroid Build Coastguard Worker }
933*35238bceSAndroid Build Coastguard Worker }
934*35238bceSAndroid Build Coastguard Worker
935*35238bceSAndroid Build Coastguard Worker return true;
936*35238bceSAndroid Build Coastguard Worker }
937*35238bceSAndroid Build Coastguard Worker };
938*35238bceSAndroid Build Coastguard Worker
939*35238bceSAndroid Build Coastguard Worker class IsinfCase : public CommonFunctionCase
940*35238bceSAndroid Build Coastguard Worker {
941*35238bceSAndroid Build Coastguard Worker public:
IsinfCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)942*35238bceSAndroid Build Coastguard Worker IsinfCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
943*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isinf",
944*35238bceSAndroid Build Coastguard Worker shaderType)
945*35238bceSAndroid Build Coastguard Worker {
946*35238bceSAndroid Build Coastguard Worker DE_ASSERT(glu::isDataTypeFloatOrVec(baseType));
947*35238bceSAndroid Build Coastguard Worker
948*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
949*35238bceSAndroid Build Coastguard Worker const glu::DataType boolType = vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL;
950*35238bceSAndroid Build Coastguard Worker
951*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
952*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST)));
953*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = isinf(in0);";
954*35238bceSAndroid Build Coastguard Worker }
955*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const956*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
957*35238bceSAndroid Build Coastguard Worker {
958*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xc2a39fu);
959*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
960*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
961*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
962*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
963*35238bceSAndroid Build Coastguard Worker const uint32_t mantissaMask = ~getMaxUlpDiffFromBits(mantissaBits) & ((1u << 23) - 1u);
964*35238bceSAndroid Build Coastguard Worker
965*35238bceSAndroid Build Coastguard Worker for (int valNdx = 0; valNdx < numValues * scalarSize; valNdx++)
966*35238bceSAndroid Build Coastguard Worker {
967*35238bceSAndroid Build Coastguard Worker const bool isInf = rnd.getFloat() > 0.3f;
968*35238bceSAndroid Build Coastguard Worker const bool isNan = !isInf && rnd.getFloat() > 0.4f;
969*35238bceSAndroid Build Coastguard Worker const uint32_t mantissa = !isInf ? ((1u << 22) | (rnd.getUint32() & mantissaMask)) : 0;
970*35238bceSAndroid Build Coastguard Worker const uint32_t exp = !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu;
971*35238bceSAndroid Build Coastguard Worker const uint32_t sign = rnd.getUint32() & 0x1u;
972*35238bceSAndroid Build Coastguard Worker const uint32_t value = (sign << 31) | (exp << 23) | mantissa;
973*35238bceSAndroid Build Coastguard Worker
974*35238bceSAndroid Build Coastguard Worker DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan);
975*35238bceSAndroid Build Coastguard Worker
976*35238bceSAndroid Build Coastguard Worker ((uint32_t *)values[0])[valNdx] = value;
977*35238bceSAndroid Build Coastguard Worker }
978*35238bceSAndroid Build Coastguard Worker }
979*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)980*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
981*35238bceSAndroid Build Coastguard Worker {
982*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
983*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
984*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
985*35238bceSAndroid Build Coastguard Worker
986*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP)
987*35238bceSAndroid Build Coastguard Worker {
988*35238bceSAndroid Build Coastguard Worker // Only highp is required to support inf/nan
989*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
990*35238bceSAndroid Build Coastguard Worker {
991*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
992*35238bceSAndroid Build Coastguard Worker const bool out0 = ((const uint32_t *)outputs[0])[compNdx] != 0;
993*35238bceSAndroid Build Coastguard Worker const bool ref = tcu::Float32(in0).isInf();
994*35238bceSAndroid Build Coastguard Worker
995*35238bceSAndroid Build Coastguard Worker if (out0 != ref)
996*35238bceSAndroid Build Coastguard Worker {
997*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref);
998*35238bceSAndroid Build Coastguard Worker return false;
999*35238bceSAndroid Build Coastguard Worker }
1000*35238bceSAndroid Build Coastguard Worker }
1001*35238bceSAndroid Build Coastguard Worker }
1002*35238bceSAndroid Build Coastguard Worker else if (precision == glu::PRECISION_MEDIUMP)
1003*35238bceSAndroid Build Coastguard Worker {
1004*35238bceSAndroid Build Coastguard Worker // Inf support is optional, check that inputs that are not Inf in mediump don't result in true.
1005*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1006*35238bceSAndroid Build Coastguard Worker {
1007*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1008*35238bceSAndroid Build Coastguard Worker const bool out0 = ((const uint32_t *)outputs[0])[compNdx] != 0;
1009*35238bceSAndroid Build Coastguard Worker const bool ref = tcu::Float16(in0).isInf();
1010*35238bceSAndroid Build Coastguard Worker
1011*35238bceSAndroid Build Coastguard Worker if (!ref && out0)
1012*35238bceSAndroid Build Coastguard Worker {
1013*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << (ref ? "true" : "false");
1014*35238bceSAndroid Build Coastguard Worker return false;
1015*35238bceSAndroid Build Coastguard Worker }
1016*35238bceSAndroid Build Coastguard Worker }
1017*35238bceSAndroid Build Coastguard Worker }
1018*35238bceSAndroid Build Coastguard Worker // else: no verification can be performed
1019*35238bceSAndroid Build Coastguard Worker
1020*35238bceSAndroid Build Coastguard Worker return true;
1021*35238bceSAndroid Build Coastguard Worker }
1022*35238bceSAndroid Build Coastguard Worker };
1023*35238bceSAndroid Build Coastguard Worker
1024*35238bceSAndroid Build Coastguard Worker class FloatBitsToUintIntCase : public CommonFunctionCase
1025*35238bceSAndroid Build Coastguard Worker {
1026*35238bceSAndroid Build Coastguard Worker public:
FloatBitsToUintIntCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType,bool outIsSigned)1027*35238bceSAndroid Build Coastguard Worker FloatBitsToUintIntCase(Context &context, glu::DataType baseType, glu::Precision precision,
1028*35238bceSAndroid Build Coastguard Worker glu::ShaderType shaderType, bool outIsSigned)
1029*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(),
1030*35238bceSAndroid Build Coastguard Worker outIsSigned ? "floatBitsToInt" : "floatBitsToUint", shaderType)
1031*35238bceSAndroid Build Coastguard Worker {
1032*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
1033*35238bceSAndroid Build Coastguard Worker const glu::DataType intType = outIsSigned ? (vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT) :
1034*35238bceSAndroid Build Coastguard Worker (vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT);
1035*35238bceSAndroid Build Coastguard Worker
1036*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1037*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(intType, glu::PRECISION_HIGHP)));
1038*35238bceSAndroid Build Coastguard Worker m_spec.source = outIsSigned ? "out0 = floatBitsToInt(in0);" : "out0 = floatBitsToUint(in0);";
1039*35238bceSAndroid Build Coastguard Worker }
1040*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1041*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1042*35238bceSAndroid Build Coastguard Worker {
1043*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1044*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1045*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1046*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1047*35238bceSAndroid Build Coastguard Worker };
1048*35238bceSAndroid Build Coastguard Worker
1049*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0x2790au);
1050*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1051*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1052*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1053*35238bceSAndroid Build Coastguard Worker
1054*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues * scalarSize);
1055*35238bceSAndroid Build Coastguard Worker }
1056*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1057*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1058*35238bceSAndroid Build Coastguard Worker {
1059*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1060*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1061*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1062*35238bceSAndroid Build Coastguard Worker
1063*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1064*35238bceSAndroid Build Coastguard Worker const int maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits);
1065*35238bceSAndroid Build Coastguard Worker
1066*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1067*35238bceSAndroid Build Coastguard Worker {
1068*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1069*35238bceSAndroid Build Coastguard Worker const uint32_t out0 = ((const uint32_t *)outputs[0])[compNdx];
1070*35238bceSAndroid Build Coastguard Worker const uint32_t refOut0 = tcu::Float32(in0).bits();
1071*35238bceSAndroid Build Coastguard Worker const int ulpDiff = de::abs((int)out0 - (int)refOut0);
1072*35238bceSAndroid Build Coastguard Worker
1073*35238bceSAndroid Build Coastguard Worker if (ulpDiff > maxUlpDiff)
1074*35238bceSAndroid Build Coastguard Worker {
1075*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(refOut0) << " with threshold "
1076*35238bceSAndroid Build Coastguard Worker << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
1077*35238bceSAndroid Build Coastguard Worker return false;
1078*35238bceSAndroid Build Coastguard Worker }
1079*35238bceSAndroid Build Coastguard Worker }
1080*35238bceSAndroid Build Coastguard Worker
1081*35238bceSAndroid Build Coastguard Worker return true;
1082*35238bceSAndroid Build Coastguard Worker }
1083*35238bceSAndroid Build Coastguard Worker };
1084*35238bceSAndroid Build Coastguard Worker
1085*35238bceSAndroid Build Coastguard Worker class FloatBitsToIntCase : public FloatBitsToUintIntCase
1086*35238bceSAndroid Build Coastguard Worker {
1087*35238bceSAndroid Build Coastguard Worker public:
FloatBitsToIntCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1088*35238bceSAndroid Build Coastguard Worker FloatBitsToIntCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1089*35238bceSAndroid Build Coastguard Worker : FloatBitsToUintIntCase(context, baseType, precision, shaderType, true)
1090*35238bceSAndroid Build Coastguard Worker {
1091*35238bceSAndroid Build Coastguard Worker }
1092*35238bceSAndroid Build Coastguard Worker };
1093*35238bceSAndroid Build Coastguard Worker
1094*35238bceSAndroid Build Coastguard Worker class FloatBitsToUintCase : public FloatBitsToUintIntCase
1095*35238bceSAndroid Build Coastguard Worker {
1096*35238bceSAndroid Build Coastguard Worker public:
FloatBitsToUintCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1097*35238bceSAndroid Build Coastguard Worker FloatBitsToUintCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1098*35238bceSAndroid Build Coastguard Worker : FloatBitsToUintIntCase(context, baseType, precision, shaderType, false)
1099*35238bceSAndroid Build Coastguard Worker {
1100*35238bceSAndroid Build Coastguard Worker }
1101*35238bceSAndroid Build Coastguard Worker };
1102*35238bceSAndroid Build Coastguard Worker
1103*35238bceSAndroid Build Coastguard Worker class BitsToFloatCase : public CommonFunctionCase
1104*35238bceSAndroid Build Coastguard Worker {
1105*35238bceSAndroid Build Coastguard Worker public:
BitsToFloatCase(Context & context,glu::DataType baseType,glu::ShaderType shaderType)1106*35238bceSAndroid Build Coastguard Worker BitsToFloatCase(Context &context, glu::DataType baseType, glu::ShaderType shaderType)
1107*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, glu::PRECISION_HIGHP, shaderType).c_str(),
1108*35238bceSAndroid Build Coastguard Worker glu::isDataTypeIntOrIVec(baseType) ? "intBitsToFloat" : "uintBitsToFloat", shaderType)
1109*35238bceSAndroid Build Coastguard Worker {
1110*35238bceSAndroid Build Coastguard Worker const bool inIsSigned = glu::isDataTypeIntOrIVec(baseType);
1111*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
1112*35238bceSAndroid Build Coastguard Worker const glu::DataType floatType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
1113*35238bceSAndroid Build Coastguard Worker
1114*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
1115*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(floatType, glu::PRECISION_HIGHP)));
1116*35238bceSAndroid Build Coastguard Worker m_spec.source = inIsSigned ? "out0 = intBitsToFloat(in0);" : "out0 = uintBitsToFloat(in0);";
1117*35238bceSAndroid Build Coastguard Worker }
1118*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1119*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1120*35238bceSAndroid Build Coastguard Worker {
1121*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xbbb225u);
1122*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1123*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1124*35238bceSAndroid Build Coastguard Worker const Vec2 range(-1e8f, +1e8f);
1125*35238bceSAndroid Build Coastguard Worker
1126*35238bceSAndroid Build Coastguard Worker // \note Filled as floats.
1127*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, range.x(), range.y(), values[0], numValues * scalarSize);
1128*35238bceSAndroid Build Coastguard Worker }
1129*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1130*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1131*35238bceSAndroid Build Coastguard Worker {
1132*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1133*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1134*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = 0;
1135*35238bceSAndroid Build Coastguard Worker
1136*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1137*35238bceSAndroid Build Coastguard Worker {
1138*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1139*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1140*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiff(in0, out0);
1141*35238bceSAndroid Build Coastguard Worker
1142*35238bceSAndroid Build Coastguard Worker if (ulpDiff > maxUlpDiff)
1143*35238bceSAndroid Build Coastguard Worker {
1144*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(tcu::Float32(in0).bits())
1145*35238bceSAndroid Build Coastguard Worker << " with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got ULP diff "
1146*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1147*35238bceSAndroid Build Coastguard Worker return false;
1148*35238bceSAndroid Build Coastguard Worker }
1149*35238bceSAndroid Build Coastguard Worker }
1150*35238bceSAndroid Build Coastguard Worker
1151*35238bceSAndroid Build Coastguard Worker return true;
1152*35238bceSAndroid Build Coastguard Worker }
1153*35238bceSAndroid Build Coastguard Worker };
1154*35238bceSAndroid Build Coastguard Worker
1155*35238bceSAndroid Build Coastguard Worker class FloorCase : public CommonFunctionCase
1156*35238bceSAndroid Build Coastguard Worker {
1157*35238bceSAndroid Build Coastguard Worker public:
FloorCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1158*35238bceSAndroid Build Coastguard Worker FloorCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1159*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "floor",
1160*35238bceSAndroid Build Coastguard Worker shaderType)
1161*35238bceSAndroid Build Coastguard Worker {
1162*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1163*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1164*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = floor(in0);";
1165*35238bceSAndroid Build Coastguard Worker }
1166*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1167*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1168*35238bceSAndroid Build Coastguard Worker {
1169*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1170*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1171*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1172*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1173*35238bceSAndroid Build Coastguard Worker };
1174*35238bceSAndroid Build Coastguard Worker
1175*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1176*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1177*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1178*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1179*35238bceSAndroid Build Coastguard Worker // Random cases.
1180*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float *)values[0],
1181*35238bceSAndroid Build Coastguard Worker numValues * scalarSize);
1182*35238bceSAndroid Build Coastguard Worker
1183*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1184*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1185*35238bceSAndroid Build Coastguard Worker {
1186*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1187*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1188*35238bceSAndroid Build Coastguard Worker }
1189*35238bceSAndroid Build Coastguard Worker }
1190*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1191*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1192*35238bceSAndroid Build Coastguard Worker {
1193*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1194*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1195*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1196*35238bceSAndroid Build Coastguard Worker
1197*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1198*35238bceSAndroid Build Coastguard Worker {
1199*35238bceSAndroid Build Coastguard Worker // Require exact result.
1200*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1201*35238bceSAndroid Build Coastguard Worker {
1202*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1203*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1204*35238bceSAndroid Build Coastguard Worker const float ref = deFloatFloor(in0);
1205*35238bceSAndroid Build Coastguard Worker
1206*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiff(out0, ref);
1207*35238bceSAndroid Build Coastguard Worker
1208*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1209*35238bceSAndroid Build Coastguard Worker {
1210*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1211*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1212*35238bceSAndroid Build Coastguard Worker return false;
1213*35238bceSAndroid Build Coastguard Worker }
1214*35238bceSAndroid Build Coastguard Worker }
1215*35238bceSAndroid Build Coastguard Worker }
1216*35238bceSAndroid Build Coastguard Worker else
1217*35238bceSAndroid Build Coastguard Worker {
1218*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1219*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
1220*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1221*35238bceSAndroid Build Coastguard Worker
1222*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1223*35238bceSAndroid Build Coastguard Worker {
1224*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1225*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1226*35238bceSAndroid Build Coastguard Worker const int minRes = int(deFloatFloor(in0 - eps));
1227*35238bceSAndroid Build Coastguard Worker const int maxRes = int(deFloatFloor(in0 + eps));
1228*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
1229*35238bceSAndroid Build Coastguard Worker
1230*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
1231*35238bceSAndroid Build Coastguard Worker {
1232*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiff(out0, float(roundedVal));
1233*35238bceSAndroid Build Coastguard Worker
1234*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
1235*35238bceSAndroid Build Coastguard Worker {
1236*35238bceSAndroid Build Coastguard Worker anyOk = true;
1237*35238bceSAndroid Build Coastguard Worker break;
1238*35238bceSAndroid Build Coastguard Worker }
1239*35238bceSAndroid Build Coastguard Worker }
1240*35238bceSAndroid Build Coastguard Worker
1241*35238bceSAndroid Build Coastguard Worker if (!anyOk)
1242*35238bceSAndroid Build Coastguard Worker {
1243*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
1244*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
1245*35238bceSAndroid Build Coastguard Worker return false;
1246*35238bceSAndroid Build Coastguard Worker }
1247*35238bceSAndroid Build Coastguard Worker }
1248*35238bceSAndroid Build Coastguard Worker }
1249*35238bceSAndroid Build Coastguard Worker
1250*35238bceSAndroid Build Coastguard Worker return true;
1251*35238bceSAndroid Build Coastguard Worker }
1252*35238bceSAndroid Build Coastguard Worker };
1253*35238bceSAndroid Build Coastguard Worker
1254*35238bceSAndroid Build Coastguard Worker class TruncCase : public CommonFunctionCase
1255*35238bceSAndroid Build Coastguard Worker {
1256*35238bceSAndroid Build Coastguard Worker public:
TruncCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1257*35238bceSAndroid Build Coastguard Worker TruncCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1258*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "trunc",
1259*35238bceSAndroid Build Coastguard Worker shaderType)
1260*35238bceSAndroid Build Coastguard Worker {
1261*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1262*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1263*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = trunc(in0);";
1264*35238bceSAndroid Build Coastguard Worker }
1265*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1266*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1267*35238bceSAndroid Build Coastguard Worker {
1268*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1269*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1270*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1271*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1272*35238bceSAndroid Build Coastguard Worker };
1273*35238bceSAndroid Build Coastguard Worker
1274*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1275*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1276*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1277*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1278*35238bceSAndroid Build Coastguard Worker const float specialCases[] = {0.0f, -0.0f, -0.9f, 0.9f, 1.0f, -1.0f};
1279*35238bceSAndroid Build Coastguard Worker const int numSpecialCases = DE_LENGTH_OF_ARRAY(specialCases);
1280*35238bceSAndroid Build Coastguard Worker
1281*35238bceSAndroid Build Coastguard Worker // Special cases
1282*35238bceSAndroid Build Coastguard Worker for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
1283*35238bceSAndroid Build Coastguard Worker {
1284*35238bceSAndroid Build Coastguard Worker for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
1285*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[caseNdx * scalarSize + scalarNdx] = specialCases[caseNdx];
1286*35238bceSAndroid Build Coastguard Worker }
1287*35238bceSAndroid Build Coastguard Worker
1288*35238bceSAndroid Build Coastguard Worker // Random cases.
1289*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(),
1290*35238bceSAndroid Build Coastguard Worker (float *)values[0] + scalarSize * numSpecialCases,
1291*35238bceSAndroid Build Coastguard Worker (numValues - numSpecialCases) * scalarSize);
1292*35238bceSAndroid Build Coastguard Worker
1293*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1294*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1295*35238bceSAndroid Build Coastguard Worker {
1296*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1297*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1298*35238bceSAndroid Build Coastguard Worker }
1299*35238bceSAndroid Build Coastguard Worker }
1300*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1301*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1302*35238bceSAndroid Build Coastguard Worker {
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
1307*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1308*35238bceSAndroid Build Coastguard Worker {
1309*35238bceSAndroid Build Coastguard Worker // Require exact result.
1310*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1311*35238bceSAndroid Build Coastguard Worker {
1312*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1313*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1314*35238bceSAndroid Build Coastguard Worker const bool isNeg = tcu::Float32(in0).sign() < 0;
1315*35238bceSAndroid Build Coastguard Worker const float ref = isNeg ? (-float(int(-in0))) : float(int(in0));
1316*35238bceSAndroid Build Coastguard Worker
1317*35238bceSAndroid Build Coastguard Worker // \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero.
1318*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, ref);
1319*35238bceSAndroid Build Coastguard Worker
1320*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1321*35238bceSAndroid Build Coastguard Worker {
1322*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1323*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1324*35238bceSAndroid Build Coastguard Worker return false;
1325*35238bceSAndroid Build Coastguard Worker }
1326*35238bceSAndroid Build Coastguard Worker }
1327*35238bceSAndroid Build Coastguard Worker }
1328*35238bceSAndroid Build Coastguard Worker else
1329*35238bceSAndroid Build Coastguard Worker {
1330*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1331*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
1332*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1333*35238bceSAndroid Build Coastguard Worker
1334*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1335*35238bceSAndroid Build Coastguard Worker {
1336*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1337*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1338*35238bceSAndroid Build Coastguard Worker const int minRes = int(in0 - eps);
1339*35238bceSAndroid Build Coastguard Worker const int maxRes = int(in0 + eps);
1340*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
1341*35238bceSAndroid Build Coastguard Worker
1342*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
1343*35238bceSAndroid Build Coastguard Worker {
1344*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
1345*35238bceSAndroid Build Coastguard Worker
1346*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
1347*35238bceSAndroid Build Coastguard Worker {
1348*35238bceSAndroid Build Coastguard Worker anyOk = true;
1349*35238bceSAndroid Build Coastguard Worker break;
1350*35238bceSAndroid Build Coastguard Worker }
1351*35238bceSAndroid Build Coastguard Worker }
1352*35238bceSAndroid Build Coastguard Worker
1353*35238bceSAndroid Build Coastguard Worker if (!anyOk)
1354*35238bceSAndroid Build Coastguard Worker {
1355*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
1356*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
1357*35238bceSAndroid Build Coastguard Worker return false;
1358*35238bceSAndroid Build Coastguard Worker }
1359*35238bceSAndroid Build Coastguard Worker }
1360*35238bceSAndroid Build Coastguard Worker }
1361*35238bceSAndroid Build Coastguard Worker
1362*35238bceSAndroid Build Coastguard Worker return true;
1363*35238bceSAndroid Build Coastguard Worker }
1364*35238bceSAndroid Build Coastguard Worker };
1365*35238bceSAndroid Build Coastguard Worker
1366*35238bceSAndroid Build Coastguard Worker class RoundCase : public CommonFunctionCase
1367*35238bceSAndroid Build Coastguard Worker {
1368*35238bceSAndroid Build Coastguard Worker public:
RoundCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1369*35238bceSAndroid Build Coastguard Worker RoundCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1370*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "round",
1371*35238bceSAndroid Build Coastguard Worker shaderType)
1372*35238bceSAndroid Build Coastguard Worker {
1373*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1374*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1375*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = round(in0);";
1376*35238bceSAndroid Build Coastguard Worker }
1377*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1378*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1379*35238bceSAndroid Build Coastguard Worker {
1380*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1381*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1382*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1383*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1384*35238bceSAndroid Build Coastguard Worker };
1385*35238bceSAndroid Build Coastguard Worker
1386*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1387*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1388*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1389*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1390*35238bceSAndroid Build Coastguard Worker int numSpecialCases = 0;
1391*35238bceSAndroid Build Coastguard Worker
1392*35238bceSAndroid Build Coastguard Worker // Special cases.
1393*35238bceSAndroid Build Coastguard Worker if (precision != glu::PRECISION_LOWP)
1394*35238bceSAndroid Build Coastguard Worker {
1395*35238bceSAndroid Build Coastguard Worker DE_ASSERT(numValues >= 10);
1396*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < 10; ndx++)
1397*35238bceSAndroid Build Coastguard Worker {
1398*35238bceSAndroid Build Coastguard Worker const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
1399*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0], (float *)values[0] + scalarSize, v);
1400*35238bceSAndroid Build Coastguard Worker numSpecialCases += 1;
1401*35238bceSAndroid Build Coastguard Worker }
1402*35238bceSAndroid Build Coastguard Worker }
1403*35238bceSAndroid Build Coastguard Worker
1404*35238bceSAndroid Build Coastguard Worker // Random cases.
1405*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(),
1406*35238bceSAndroid Build Coastguard Worker (float *)values[0] + numSpecialCases * scalarSize,
1407*35238bceSAndroid Build Coastguard Worker (numValues - numSpecialCases) * scalarSize);
1408*35238bceSAndroid Build Coastguard Worker
1409*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1410*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1411*35238bceSAndroid Build Coastguard Worker {
1412*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1413*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1414*35238bceSAndroid Build Coastguard Worker }
1415*35238bceSAndroid Build Coastguard Worker }
1416*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1417*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1418*35238bceSAndroid Build Coastguard Worker {
1419*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1420*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1421*35238bceSAndroid Build Coastguard Worker const bool hasZeroSign = supportsSignedZero(precision);
1422*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1423*35238bceSAndroid Build Coastguard Worker
1424*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1425*35238bceSAndroid Build Coastguard Worker {
1426*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1427*35238bceSAndroid Build Coastguard Worker {
1428*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1429*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1430*35238bceSAndroid Build Coastguard Worker
1431*35238bceSAndroid Build Coastguard Worker if (deFloatFrac(in0) == 0.5f)
1432*35238bceSAndroid Build Coastguard Worker {
1433*35238bceSAndroid Build Coastguard Worker // Allow both ceil(in) and floor(in)
1434*35238bceSAndroid Build Coastguard Worker const float ref0 = deFloatFloor(in0);
1435*35238bceSAndroid Build Coastguard Worker const float ref1 = deFloatCeil(in0);
1436*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff0 =
1437*35238bceSAndroid Build Coastguard Worker hasZeroSign ? getUlpDiff(out0, ref0) : getUlpDiffIgnoreZeroSign(out0, ref0);
1438*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff1 =
1439*35238bceSAndroid Build Coastguard Worker hasZeroSign ? getUlpDiff(out0, ref1) : getUlpDiffIgnoreZeroSign(out0, ref1);
1440*35238bceSAndroid Build Coastguard Worker
1441*35238bceSAndroid Build Coastguard Worker if (ulpDiff0 > 0 && ulpDiff1 > 0)
1442*35238bceSAndroid Build Coastguard Worker {
1443*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " or " << HexFloat(ref1)
1444*35238bceSAndroid Build Coastguard Worker << ", got ULP diff " << tcu::toHex(de::min(ulpDiff0, ulpDiff1));
1445*35238bceSAndroid Build Coastguard Worker return false;
1446*35238bceSAndroid Build Coastguard Worker }
1447*35238bceSAndroid Build Coastguard Worker }
1448*35238bceSAndroid Build Coastguard Worker else
1449*35238bceSAndroid Build Coastguard Worker {
1450*35238bceSAndroid Build Coastguard Worker // Require exact result
1451*35238bceSAndroid Build Coastguard Worker const float ref = roundEven(in0);
1452*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
1453*35238bceSAndroid Build Coastguard Worker
1454*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1455*35238bceSAndroid Build Coastguard Worker {
1456*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1457*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1458*35238bceSAndroid Build Coastguard Worker return false;
1459*35238bceSAndroid Build Coastguard Worker }
1460*35238bceSAndroid Build Coastguard Worker }
1461*35238bceSAndroid Build Coastguard Worker }
1462*35238bceSAndroid Build Coastguard Worker }
1463*35238bceSAndroid Build Coastguard Worker else
1464*35238bceSAndroid Build Coastguard Worker {
1465*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1466*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
1467*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1468*35238bceSAndroid Build Coastguard Worker
1469*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1470*35238bceSAndroid Build Coastguard Worker {
1471*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1472*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1473*35238bceSAndroid Build Coastguard Worker const int minRes = int(roundEven(in0 - eps));
1474*35238bceSAndroid Build Coastguard Worker const int maxRes = int(roundEven(in0 + eps));
1475*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
1476*35238bceSAndroid Build Coastguard Worker
1477*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
1478*35238bceSAndroid Build Coastguard Worker {
1479*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
1480*35238bceSAndroid Build Coastguard Worker
1481*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
1482*35238bceSAndroid Build Coastguard Worker {
1483*35238bceSAndroid Build Coastguard Worker anyOk = true;
1484*35238bceSAndroid Build Coastguard Worker break;
1485*35238bceSAndroid Build Coastguard Worker }
1486*35238bceSAndroid Build Coastguard Worker }
1487*35238bceSAndroid Build Coastguard Worker
1488*35238bceSAndroid Build Coastguard Worker if (!anyOk)
1489*35238bceSAndroid Build Coastguard Worker {
1490*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
1491*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
1492*35238bceSAndroid Build Coastguard Worker return false;
1493*35238bceSAndroid Build Coastguard Worker }
1494*35238bceSAndroid Build Coastguard Worker }
1495*35238bceSAndroid Build Coastguard Worker }
1496*35238bceSAndroid Build Coastguard Worker
1497*35238bceSAndroid Build Coastguard Worker return true;
1498*35238bceSAndroid Build Coastguard Worker }
1499*35238bceSAndroid Build Coastguard Worker };
1500*35238bceSAndroid Build Coastguard Worker
1501*35238bceSAndroid Build Coastguard Worker class CeilCase : public CommonFunctionCase
1502*35238bceSAndroid Build Coastguard Worker {
1503*35238bceSAndroid Build Coastguard Worker public:
CeilCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1504*35238bceSAndroid Build Coastguard Worker CeilCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1505*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ceil",
1506*35238bceSAndroid Build Coastguard Worker shaderType)
1507*35238bceSAndroid Build Coastguard Worker {
1508*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1509*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1510*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = ceil(in0);";
1511*35238bceSAndroid Build Coastguard Worker }
1512*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1513*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1514*35238bceSAndroid Build Coastguard Worker {
1515*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1516*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1517*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1518*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1519*35238bceSAndroid Build Coastguard Worker };
1520*35238bceSAndroid Build Coastguard Worker
1521*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1522*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1523*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1524*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1525*35238bceSAndroid Build Coastguard Worker
1526*35238bceSAndroid Build Coastguard Worker // Random cases.
1527*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float *)values[0],
1528*35238bceSAndroid Build Coastguard Worker numValues * scalarSize);
1529*35238bceSAndroid Build Coastguard Worker
1530*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1531*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1532*35238bceSAndroid Build Coastguard Worker {
1533*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1534*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1535*35238bceSAndroid Build Coastguard Worker }
1536*35238bceSAndroid Build Coastguard Worker }
1537*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1538*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1539*35238bceSAndroid Build Coastguard Worker {
1540*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1541*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1542*35238bceSAndroid Build Coastguard Worker const bool hasZeroSign = supportsSignedZero(precision);
1543*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1544*35238bceSAndroid Build Coastguard Worker
1545*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1546*35238bceSAndroid Build Coastguard Worker {
1547*35238bceSAndroid Build Coastguard Worker // Require exact result.
1548*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1549*35238bceSAndroid Build Coastguard Worker {
1550*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1551*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1552*35238bceSAndroid Build Coastguard Worker const float ref = deFloatCeil(in0);
1553*35238bceSAndroid Build Coastguard Worker
1554*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
1555*35238bceSAndroid Build Coastguard Worker
1556*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1557*35238bceSAndroid Build Coastguard Worker {
1558*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1559*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1560*35238bceSAndroid Build Coastguard Worker return false;
1561*35238bceSAndroid Build Coastguard Worker }
1562*35238bceSAndroid Build Coastguard Worker }
1563*35238bceSAndroid Build Coastguard Worker }
1564*35238bceSAndroid Build Coastguard Worker else
1565*35238bceSAndroid Build Coastguard Worker {
1566*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1567*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
1568*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1569*35238bceSAndroid Build Coastguard Worker
1570*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1571*35238bceSAndroid Build Coastguard Worker {
1572*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1573*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1574*35238bceSAndroid Build Coastguard Worker const int minRes = int(deFloatCeil(in0 - eps));
1575*35238bceSAndroid Build Coastguard Worker const int maxRes = int(deFloatCeil(in0 + eps));
1576*35238bceSAndroid Build Coastguard Worker bool anyOk = false;
1577*35238bceSAndroid Build Coastguard Worker
1578*35238bceSAndroid Build Coastguard Worker for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++)
1579*35238bceSAndroid Build Coastguard Worker {
1580*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal));
1581*35238bceSAndroid Build Coastguard Worker
1582*35238bceSAndroid Build Coastguard Worker if (ulpDiff <= maxUlpDiff)
1583*35238bceSAndroid Build Coastguard Worker {
1584*35238bceSAndroid Build Coastguard Worker anyOk = true;
1585*35238bceSAndroid Build Coastguard Worker break;
1586*35238bceSAndroid Build Coastguard Worker }
1587*35238bceSAndroid Build Coastguard Worker }
1588*35238bceSAndroid Build Coastguard Worker
1589*35238bceSAndroid Build Coastguard Worker if (!anyOk && de::inRange(0, minRes, maxRes))
1590*35238bceSAndroid Build Coastguard Worker {
1591*35238bceSAndroid Build Coastguard Worker // Allow -0 as well.
1592*35238bceSAndroid Build Coastguard Worker const int ulpDiff = de::abs((int)tcu::Float32(out0).bits() - (int)0x80000000u);
1593*35238bceSAndroid Build Coastguard Worker anyOk = ((uint32_t)ulpDiff <= maxUlpDiff);
1594*35238bceSAndroid Build Coastguard Worker }
1595*35238bceSAndroid Build Coastguard Worker
1596*35238bceSAndroid Build Coastguard Worker if (!anyOk)
1597*35238bceSAndroid Build Coastguard Worker {
1598*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes
1599*35238bceSAndroid Build Coastguard Worker << "] with ULP threshold " << tcu::toHex(maxUlpDiff);
1600*35238bceSAndroid Build Coastguard Worker return false;
1601*35238bceSAndroid Build Coastguard Worker }
1602*35238bceSAndroid Build Coastguard Worker }
1603*35238bceSAndroid Build Coastguard Worker }
1604*35238bceSAndroid Build Coastguard Worker
1605*35238bceSAndroid Build Coastguard Worker return true;
1606*35238bceSAndroid Build Coastguard Worker }
1607*35238bceSAndroid Build Coastguard Worker };
1608*35238bceSAndroid Build Coastguard Worker
1609*35238bceSAndroid Build Coastguard Worker class FractCase : public CommonFunctionCase
1610*35238bceSAndroid Build Coastguard Worker {
1611*35238bceSAndroid Build Coastguard Worker public:
FractCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1612*35238bceSAndroid Build Coastguard Worker FractCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1613*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fract",
1614*35238bceSAndroid Build Coastguard Worker shaderType)
1615*35238bceSAndroid Build Coastguard Worker {
1616*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1617*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision)));
1618*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = fract(in0);";
1619*35238bceSAndroid Build Coastguard Worker }
1620*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1621*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1622*35238bceSAndroid Build Coastguard Worker {
1623*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1624*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1625*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1626*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1627*35238bceSAndroid Build Coastguard Worker };
1628*35238bceSAndroid Build Coastguard Worker
1629*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
1630*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1631*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1632*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1633*35238bceSAndroid Build Coastguard Worker int numSpecialCases = 0;
1634*35238bceSAndroid Build Coastguard Worker
1635*35238bceSAndroid Build Coastguard Worker // Special cases.
1636*35238bceSAndroid Build Coastguard Worker if (precision != glu::PRECISION_LOWP)
1637*35238bceSAndroid Build Coastguard Worker {
1638*35238bceSAndroid Build Coastguard Worker DE_ASSERT(numValues >= 10);
1639*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < 10; ndx++)
1640*35238bceSAndroid Build Coastguard Worker {
1641*35238bceSAndroid Build Coastguard Worker const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y());
1642*35238bceSAndroid Build Coastguard Worker std::fill((float *)values[0], (float *)values[0] + scalarSize, v);
1643*35238bceSAndroid Build Coastguard Worker numSpecialCases += 1;
1644*35238bceSAndroid Build Coastguard Worker }
1645*35238bceSAndroid Build Coastguard Worker }
1646*35238bceSAndroid Build Coastguard Worker
1647*35238bceSAndroid Build Coastguard Worker // Random cases.
1648*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(),
1649*35238bceSAndroid Build Coastguard Worker (float *)values[0] + numSpecialCases * scalarSize,
1650*35238bceSAndroid Build Coastguard Worker (numValues - numSpecialCases) * scalarSize);
1651*35238bceSAndroid Build Coastguard Worker
1652*35238bceSAndroid Build Coastguard Worker // If precision is mediump, make sure values can be represented in fp16 exactly
1653*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_MEDIUMP)
1654*35238bceSAndroid Build Coastguard Worker {
1655*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < numValues * scalarSize; ndx++)
1656*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[ndx] = tcu::Float16(((float *)values[0])[ndx]).asFloat();
1657*35238bceSAndroid Build Coastguard Worker }
1658*35238bceSAndroid Build Coastguard Worker }
1659*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1660*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1661*35238bceSAndroid Build Coastguard Worker {
1662*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1663*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1664*35238bceSAndroid Build Coastguard Worker const bool hasZeroSign = supportsSignedZero(precision);
1665*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1666*35238bceSAndroid Build Coastguard Worker
1667*35238bceSAndroid Build Coastguard Worker if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP)
1668*35238bceSAndroid Build Coastguard Worker {
1669*35238bceSAndroid Build Coastguard Worker // Require exact result.
1670*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1671*35238bceSAndroid Build Coastguard Worker {
1672*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1673*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1674*35238bceSAndroid Build Coastguard Worker const float ref = deFloatFrac(in0);
1675*35238bceSAndroid Build Coastguard Worker
1676*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref);
1677*35238bceSAndroid Build Coastguard Worker
1678*35238bceSAndroid Build Coastguard Worker if (ulpDiff > 0)
1679*35238bceSAndroid Build Coastguard Worker {
1680*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff "
1681*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1682*35238bceSAndroid Build Coastguard Worker return false;
1683*35238bceSAndroid Build Coastguard Worker }
1684*35238bceSAndroid Build Coastguard Worker }
1685*35238bceSAndroid Build Coastguard Worker }
1686*35238bceSAndroid Build Coastguard Worker else
1687*35238bceSAndroid Build Coastguard Worker {
1688*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1689*35238bceSAndroid Build Coastguard Worker const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds
1690*35238bceSAndroid Build Coastguard Worker
1691*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1692*35238bceSAndroid Build Coastguard Worker {
1693*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1694*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1695*35238bceSAndroid Build Coastguard Worker
1696*35238bceSAndroid Build Coastguard Worker if (int(deFloatFloor(in0 - eps)) == int(deFloatFloor(in0 + eps)))
1697*35238bceSAndroid Build Coastguard Worker {
1698*35238bceSAndroid Build Coastguard Worker const float ref = deFloatFrac(in0);
1699*35238bceSAndroid Build Coastguard Worker const int bitsLost = numBitsLostInOp(in0, ref);
1700*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(
1701*35238bceSAndroid Build Coastguard Worker de::max(0, mantissaBits - bitsLost)); // ULP diff for rounded integer value.
1702*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, ref);
1703*35238bceSAndroid Build Coastguard Worker
1704*35238bceSAndroid Build Coastguard Worker if (ulpDiff > maxUlpDiff)
1705*35238bceSAndroid Build Coastguard Worker {
1706*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold "
1707*35238bceSAndroid Build Coastguard Worker << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff);
1708*35238bceSAndroid Build Coastguard Worker return false;
1709*35238bceSAndroid Build Coastguard Worker }
1710*35238bceSAndroid Build Coastguard Worker }
1711*35238bceSAndroid Build Coastguard Worker else
1712*35238bceSAndroid Build Coastguard Worker {
1713*35238bceSAndroid Build Coastguard Worker if (out0 >= 1.0f)
1714*35238bceSAndroid Build Coastguard Worker {
1715*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] < 1.0";
1716*35238bceSAndroid Build Coastguard Worker return false;
1717*35238bceSAndroid Build Coastguard Worker }
1718*35238bceSAndroid Build Coastguard Worker }
1719*35238bceSAndroid Build Coastguard Worker }
1720*35238bceSAndroid Build Coastguard Worker }
1721*35238bceSAndroid Build Coastguard Worker
1722*35238bceSAndroid Build Coastguard Worker return true;
1723*35238bceSAndroid Build Coastguard Worker }
1724*35238bceSAndroid Build Coastguard Worker };
1725*35238bceSAndroid Build Coastguard Worker
frexp(float in,float * significand,int * exponent)1726*35238bceSAndroid Build Coastguard Worker static inline void frexp(float in, float *significand, int *exponent)
1727*35238bceSAndroid Build Coastguard Worker {
1728*35238bceSAndroid Build Coastguard Worker const tcu::Float32 fpValue(in);
1729*35238bceSAndroid Build Coastguard Worker
1730*35238bceSAndroid Build Coastguard Worker if (!fpValue.isZero())
1731*35238bceSAndroid Build Coastguard Worker {
1732*35238bceSAndroid Build Coastguard Worker // Construct float that has exactly the mantissa, and exponent of -1.
1733*35238bceSAndroid Build Coastguard Worker *significand = tcu::Float32::construct(fpValue.sign(), -1, fpValue.mantissa()).asFloat();
1734*35238bceSAndroid Build Coastguard Worker *exponent = fpValue.exponent() + 1;
1735*35238bceSAndroid Build Coastguard Worker }
1736*35238bceSAndroid Build Coastguard Worker else
1737*35238bceSAndroid Build Coastguard Worker {
1738*35238bceSAndroid Build Coastguard Worker *significand = fpValue.sign() < 0 ? -0.0f : 0.0f;
1739*35238bceSAndroid Build Coastguard Worker *exponent = 0;
1740*35238bceSAndroid Build Coastguard Worker }
1741*35238bceSAndroid Build Coastguard Worker }
1742*35238bceSAndroid Build Coastguard Worker
ldexp(float significand,int exponent)1743*35238bceSAndroid Build Coastguard Worker static inline float ldexp(float significand, int exponent)
1744*35238bceSAndroid Build Coastguard Worker {
1745*35238bceSAndroid Build Coastguard Worker const tcu::Float32 mant(significand);
1746*35238bceSAndroid Build Coastguard Worker
1747*35238bceSAndroid Build Coastguard Worker if (exponent == 0 && mant.isZero())
1748*35238bceSAndroid Build Coastguard Worker {
1749*35238bceSAndroid Build Coastguard Worker return mant.sign() < 0 ? -0.0f : 0.0f;
1750*35238bceSAndroid Build Coastguard Worker }
1751*35238bceSAndroid Build Coastguard Worker else
1752*35238bceSAndroid Build Coastguard Worker {
1753*35238bceSAndroid Build Coastguard Worker return tcu::Float32::construct(mant.sign(), exponent + mant.exponent(), mant.mantissa()).asFloat();
1754*35238bceSAndroid Build Coastguard Worker }
1755*35238bceSAndroid Build Coastguard Worker }
1756*35238bceSAndroid Build Coastguard Worker
1757*35238bceSAndroid Build Coastguard Worker class FrexpCase : public CommonFunctionCase
1758*35238bceSAndroid Build Coastguard Worker {
1759*35238bceSAndroid Build Coastguard Worker public:
FrexpCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1760*35238bceSAndroid Build Coastguard Worker FrexpCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1761*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "frexp",
1762*35238bceSAndroid Build Coastguard Worker shaderType)
1763*35238bceSAndroid Build Coastguard Worker {
1764*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
1765*35238bceSAndroid Build Coastguard Worker const glu::DataType intType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
1766*35238bceSAndroid Build Coastguard Worker
1767*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1768*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
1769*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out1", glu::VarType(intType, glu::PRECISION_HIGHP)));
1770*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = frexp(in0, out1);";
1771*35238bceSAndroid Build Coastguard Worker }
1772*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1773*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1774*35238bceSAndroid Build Coastguard Worker {
1775*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1776*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1777*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1778*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1779*35238bceSAndroid Build Coastguard Worker };
1780*35238bceSAndroid Build Coastguard Worker
1781*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0x2790au);
1782*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1783*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1784*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1785*35238bceSAndroid Build Coastguard Worker
1786*35238bceSAndroid Build Coastguard Worker // Special cases
1787*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1788*35238bceSAndroid Build Coastguard Worker {
1789*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[scalarSize * 0 + compNdx] = 0.0f;
1790*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[scalarSize * 1 + compNdx] = -0.0f;
1791*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[scalarSize * 2 + compNdx] = 0.5f;
1792*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[scalarSize * 3 + compNdx] = -0.5f;
1793*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[scalarSize * 4 + compNdx] = 1.0f;
1794*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[scalarSize * 5 + compNdx] = -1.0f;
1795*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[scalarSize * 6 + compNdx] = 2.0f;
1796*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[scalarSize * 7 + compNdx] = -2.0f;
1797*35238bceSAndroid Build Coastguard Worker }
1798*35238bceSAndroid Build Coastguard Worker
1799*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float *)values[0] + 8 * scalarSize,
1800*35238bceSAndroid Build Coastguard Worker (numValues - 8) * scalarSize);
1801*35238bceSAndroid Build Coastguard Worker
1802*35238bceSAndroid Build Coastguard Worker // Make sure the values are representable in the target format
1803*35238bceSAndroid Build Coastguard Worker for (int caseNdx = 0; caseNdx < numValues; ++caseNdx)
1804*35238bceSAndroid Build Coastguard Worker {
1805*35238bceSAndroid Build Coastguard Worker for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
1806*35238bceSAndroid Build Coastguard Worker {
1807*35238bceSAndroid Build Coastguard Worker float *const valuePtr = &((float *)values[0])[caseNdx * scalarSize + scalarNdx];
1808*35238bceSAndroid Build Coastguard Worker
1809*35238bceSAndroid Build Coastguard Worker *valuePtr = makeFloatRepresentable(*valuePtr, precision);
1810*35238bceSAndroid Build Coastguard Worker }
1811*35238bceSAndroid Build Coastguard Worker }
1812*35238bceSAndroid Build Coastguard Worker }
1813*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1814*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1815*35238bceSAndroid Build Coastguard Worker {
1816*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1817*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1818*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1819*35238bceSAndroid Build Coastguard Worker const bool signedZero = false;
1820*35238bceSAndroid Build Coastguard Worker
1821*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1822*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits);
1823*35238bceSAndroid Build Coastguard Worker
1824*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1825*35238bceSAndroid Build Coastguard Worker {
1826*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1827*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1828*35238bceSAndroid Build Coastguard Worker const int out1 = ((const int *)outputs[1])[compNdx];
1829*35238bceSAndroid Build Coastguard Worker
1830*35238bceSAndroid Build Coastguard Worker float refOut0;
1831*35238bceSAndroid Build Coastguard Worker int refOut1;
1832*35238bceSAndroid Build Coastguard Worker
1833*35238bceSAndroid Build Coastguard Worker frexp(in0, &refOut0, &refOut1);
1834*35238bceSAndroid Build Coastguard Worker
1835*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff0 = signedZero ? getUlpDiff(out0, refOut0) : getUlpDiffIgnoreZeroSign(out0, refOut0);
1836*35238bceSAndroid Build Coastguard Worker
1837*35238bceSAndroid Build Coastguard Worker if (ulpDiff0 > maxUlpDiff || out1 != refOut1)
1838*35238bceSAndroid Build Coastguard Worker {
1839*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(refOut0) << ", " << refOut1
1840*35238bceSAndroid Build Coastguard Worker << " with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got ULP diff "
1841*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff0);
1842*35238bceSAndroid Build Coastguard Worker return false;
1843*35238bceSAndroid Build Coastguard Worker }
1844*35238bceSAndroid Build Coastguard Worker }
1845*35238bceSAndroid Build Coastguard Worker
1846*35238bceSAndroid Build Coastguard Worker return true;
1847*35238bceSAndroid Build Coastguard Worker }
1848*35238bceSAndroid Build Coastguard Worker };
1849*35238bceSAndroid Build Coastguard Worker
1850*35238bceSAndroid Build Coastguard Worker class LdexpCase : public CommonFunctionCase
1851*35238bceSAndroid Build Coastguard Worker {
1852*35238bceSAndroid Build Coastguard Worker public:
LdexpCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1853*35238bceSAndroid Build Coastguard Worker LdexpCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1854*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ldexp",
1855*35238bceSAndroid Build Coastguard Worker shaderType)
1856*35238bceSAndroid Build Coastguard Worker {
1857*35238bceSAndroid Build Coastguard Worker const int vecSize = glu::getDataTypeScalarSize(baseType);
1858*35238bceSAndroid Build Coastguard Worker const glu::DataType intType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
1859*35238bceSAndroid Build Coastguard Worker
1860*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision)));
1861*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("in1", glu::VarType(intType, glu::PRECISION_HIGHP)));
1862*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, glu::PRECISION_HIGHP)));
1863*35238bceSAndroid Build Coastguard Worker m_spec.source = "out0 = ldexp(in0, in1);";
1864*35238bceSAndroid Build Coastguard Worker }
1865*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const1866*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
1867*35238bceSAndroid Build Coastguard Worker {
1868*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
1869*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
1870*35238bceSAndroid Build Coastguard Worker Vec2(-1e3f, 1e3f), // mediump
1871*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
1872*35238bceSAndroid Build Coastguard Worker };
1873*35238bceSAndroid Build Coastguard Worker
1874*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0x2790au);
1875*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1876*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1877*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1878*35238bceSAndroid Build Coastguard Worker int valueNdx = 0;
1879*35238bceSAndroid Build Coastguard Worker
1880*35238bceSAndroid Build Coastguard Worker {
1881*35238bceSAndroid Build Coastguard Worker const float easySpecialCases[] = {0.0f, -0.0f, 0.5f, -0.5f, 1.0f, -1.0f, 2.0f, -2.0f};
1882*35238bceSAndroid Build Coastguard Worker
1883*35238bceSAndroid Build Coastguard Worker DE_ASSERT(valueNdx + DE_LENGTH_OF_ARRAY(easySpecialCases) <= numValues);
1884*35238bceSAndroid Build Coastguard Worker for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(easySpecialCases); caseNdx++)
1885*35238bceSAndroid Build Coastguard Worker {
1886*35238bceSAndroid Build Coastguard Worker float in0;
1887*35238bceSAndroid Build Coastguard Worker int in1;
1888*35238bceSAndroid Build Coastguard Worker
1889*35238bceSAndroid Build Coastguard Worker frexp(easySpecialCases[caseNdx], &in0, &in1);
1890*35238bceSAndroid Build Coastguard Worker
1891*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1892*35238bceSAndroid Build Coastguard Worker {
1893*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[valueNdx * scalarSize + compNdx] = in0;
1894*35238bceSAndroid Build Coastguard Worker ((int *)values[1])[valueNdx * scalarSize + compNdx] = in1;
1895*35238bceSAndroid Build Coastguard Worker }
1896*35238bceSAndroid Build Coastguard Worker
1897*35238bceSAndroid Build Coastguard Worker valueNdx += 1;
1898*35238bceSAndroid Build Coastguard Worker }
1899*35238bceSAndroid Build Coastguard Worker }
1900*35238bceSAndroid Build Coastguard Worker
1901*35238bceSAndroid Build Coastguard Worker {
1902*35238bceSAndroid Build Coastguard Worker // \note lowp and mediump can not necessarily fit the values in hard cases, so we'll use only easy ones.
1903*35238bceSAndroid Build Coastguard Worker const int numEasyRandomCases = precision == glu::PRECISION_HIGHP ? 50 : (numValues - valueNdx);
1904*35238bceSAndroid Build Coastguard Worker
1905*35238bceSAndroid Build Coastguard Worker DE_ASSERT(valueNdx + numEasyRandomCases <= numValues);
1906*35238bceSAndroid Build Coastguard Worker for (int caseNdx = 0; caseNdx < numEasyRandomCases; caseNdx++)
1907*35238bceSAndroid Build Coastguard Worker {
1908*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1909*35238bceSAndroid Build Coastguard Worker {
1910*35238bceSAndroid Build Coastguard Worker const float in = rnd.getFloat(ranges[precision].x(), ranges[precision].y());
1911*35238bceSAndroid Build Coastguard Worker float in0;
1912*35238bceSAndroid Build Coastguard Worker int in1;
1913*35238bceSAndroid Build Coastguard Worker
1914*35238bceSAndroid Build Coastguard Worker frexp(in, &in0, &in1);
1915*35238bceSAndroid Build Coastguard Worker
1916*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[valueNdx * scalarSize + compNdx] = in0;
1917*35238bceSAndroid Build Coastguard Worker ((int *)values[1])[valueNdx * scalarSize + compNdx] = in1;
1918*35238bceSAndroid Build Coastguard Worker }
1919*35238bceSAndroid Build Coastguard Worker
1920*35238bceSAndroid Build Coastguard Worker valueNdx += 1;
1921*35238bceSAndroid Build Coastguard Worker }
1922*35238bceSAndroid Build Coastguard Worker }
1923*35238bceSAndroid Build Coastguard Worker
1924*35238bceSAndroid Build Coastguard Worker {
1925*35238bceSAndroid Build Coastguard Worker const int numHardRandomCases = numValues - valueNdx;
1926*35238bceSAndroid Build Coastguard Worker DE_ASSERT(numHardRandomCases >= 0 && valueNdx + numHardRandomCases <= numValues);
1927*35238bceSAndroid Build Coastguard Worker
1928*35238bceSAndroid Build Coastguard Worker for (int caseNdx = 0; caseNdx < numHardRandomCases; caseNdx++)
1929*35238bceSAndroid Build Coastguard Worker {
1930*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1931*35238bceSAndroid Build Coastguard Worker {
1932*35238bceSAndroid Build Coastguard Worker const int fpExp = rnd.getInt(-126, 127);
1933*35238bceSAndroid Build Coastguard Worker const int sign = rnd.getBool() ? -1 : +1;
1934*35238bceSAndroid Build Coastguard Worker const uint32_t mantissa = (1u << 23) | (rnd.getUint32() & ((1u << 23) - 1));
1935*35238bceSAndroid Build Coastguard Worker const int in1 = rnd.getInt(de::max(-126, -126 - fpExp), de::min(127, 127 - fpExp));
1936*35238bceSAndroid Build Coastguard Worker const float in0 = tcu::Float32::construct(sign, fpExp, mantissa).asFloat();
1937*35238bceSAndroid Build Coastguard Worker
1938*35238bceSAndroid Build Coastguard Worker DE_ASSERT(de::inRange(in1, -126, 127)); // See Khronos bug 11180
1939*35238bceSAndroid Build Coastguard Worker DE_ASSERT(de::inRange(in1 + fpExp, -126, 127));
1940*35238bceSAndroid Build Coastguard Worker
1941*35238bceSAndroid Build Coastguard Worker const float out = ldexp(in0, in1);
1942*35238bceSAndroid Build Coastguard Worker
1943*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!tcu::Float32(out).isInf() && !tcu::Float32(out).isDenorm());
1944*35238bceSAndroid Build Coastguard Worker DE_UNREF(out);
1945*35238bceSAndroid Build Coastguard Worker
1946*35238bceSAndroid Build Coastguard Worker ((float *)values[0])[valueNdx * scalarSize + compNdx] = in0;
1947*35238bceSAndroid Build Coastguard Worker ((int *)values[1])[valueNdx * scalarSize + compNdx] = in1;
1948*35238bceSAndroid Build Coastguard Worker }
1949*35238bceSAndroid Build Coastguard Worker
1950*35238bceSAndroid Build Coastguard Worker valueNdx += 1;
1951*35238bceSAndroid Build Coastguard Worker }
1952*35238bceSAndroid Build Coastguard Worker }
1953*35238bceSAndroid Build Coastguard Worker }
1954*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)1955*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
1956*35238bceSAndroid Build Coastguard Worker {
1957*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
1958*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
1959*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
1960*35238bceSAndroid Build Coastguard Worker
1961*35238bceSAndroid Build Coastguard Worker const int mantissaBits = getMinMantissaBits(precision);
1962*35238bceSAndroid Build Coastguard Worker const uint32_t maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits);
1963*35238bceSAndroid Build Coastguard Worker
1964*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
1965*35238bceSAndroid Build Coastguard Worker {
1966*35238bceSAndroid Build Coastguard Worker const float in0 = ((const float *)inputs[0])[compNdx];
1967*35238bceSAndroid Build Coastguard Worker const int in1 = ((const int *)inputs[1])[compNdx];
1968*35238bceSAndroid Build Coastguard Worker const float out0 = ((const float *)outputs[0])[compNdx];
1969*35238bceSAndroid Build Coastguard Worker const float refOut0 = ldexp(in0, in1);
1970*35238bceSAndroid Build Coastguard Worker const uint32_t ulpDiff = getUlpDiffIgnoreZeroSign(out0, refOut0);
1971*35238bceSAndroid Build Coastguard Worker
1972*35238bceSAndroid Build Coastguard Worker const int inExp = tcu::Float32(in0).exponent();
1973*35238bceSAndroid Build Coastguard Worker
1974*35238bceSAndroid Build Coastguard Worker if (ulpDiff > maxUlpDiff)
1975*35238bceSAndroid Build Coastguard Worker {
1976*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(refOut0) << ", (exp = " << inExp
1977*35238bceSAndroid Build Coastguard Worker << ") with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got ULP diff "
1978*35238bceSAndroid Build Coastguard Worker << tcu::toHex(ulpDiff);
1979*35238bceSAndroid Build Coastguard Worker return false;
1980*35238bceSAndroid Build Coastguard Worker }
1981*35238bceSAndroid Build Coastguard Worker }
1982*35238bceSAndroid Build Coastguard Worker
1983*35238bceSAndroid Build Coastguard Worker return true;
1984*35238bceSAndroid Build Coastguard Worker }
1985*35238bceSAndroid Build Coastguard Worker };
1986*35238bceSAndroid Build Coastguard Worker
1987*35238bceSAndroid Build Coastguard Worker class FmaCase : public CommonFunctionCase
1988*35238bceSAndroid Build Coastguard Worker {
1989*35238bceSAndroid Build Coastguard Worker public:
FmaCase(Context & context,glu::DataType baseType,glu::Precision precision,glu::ShaderType shaderType)1990*35238bceSAndroid Build Coastguard Worker FmaCase(Context &context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType)
1991*35238bceSAndroid Build Coastguard Worker : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fma", shaderType)
1992*35238bceSAndroid Build Coastguard Worker {
1993*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("a", glu::VarType(baseType, precision)));
1994*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("b", glu::VarType(baseType, precision)));
1995*35238bceSAndroid Build Coastguard Worker m_spec.inputs.push_back(Symbol("c", glu::VarType(baseType, precision)));
1996*35238bceSAndroid Build Coastguard Worker m_spec.outputs.push_back(Symbol("res", glu::VarType(baseType, precision)));
1997*35238bceSAndroid Build Coastguard Worker m_spec.source = "res = fma(a, b, c);";
1998*35238bceSAndroid Build Coastguard Worker
1999*35238bceSAndroid Build Coastguard Worker if (!glu::contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2)) &&
2000*35238bceSAndroid Build Coastguard Worker !glu::contextSupports(context.getRenderContext().getType(), glu::ApiType::core(4, 5)))
2001*35238bceSAndroid Build Coastguard Worker m_spec.globalDeclarations = "#extension GL_EXT_gpu_shader5 : require\n";
2002*35238bceSAndroid Build Coastguard Worker }
2003*35238bceSAndroid Build Coastguard Worker
init(void)2004*35238bceSAndroid Build Coastguard Worker void init(void)
2005*35238bceSAndroid Build Coastguard Worker {
2006*35238bceSAndroid Build Coastguard Worker if (!glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) &&
2007*35238bceSAndroid Build Coastguard Worker !m_context.getContextInfo().isExtensionSupported("GL_EXT_gpu_shader5") &&
2008*35238bceSAndroid Build Coastguard Worker !glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)))
2009*35238bceSAndroid Build Coastguard Worker throw tcu::NotSupportedError("OpenGL ES 3.2, GL_EXT_gpu_shader5 not supported and OpenGL 4.5");
2010*35238bceSAndroid Build Coastguard Worker
2011*35238bceSAndroid Build Coastguard Worker CommonFunctionCase::init();
2012*35238bceSAndroid Build Coastguard Worker }
2013*35238bceSAndroid Build Coastguard Worker
getInputValues(int numValues,void * const * values) const2014*35238bceSAndroid Build Coastguard Worker void getInputValues(int numValues, void *const *values) const
2015*35238bceSAndroid Build Coastguard Worker {
2016*35238bceSAndroid Build Coastguard Worker const Vec2 ranges[] = {
2017*35238bceSAndroid Build Coastguard Worker Vec2(-2.0f, 2.0f), // lowp
2018*35238bceSAndroid Build Coastguard Worker Vec2(-127.f, 127.f), // mediump
2019*35238bceSAndroid Build Coastguard Worker Vec2(-1e7f, 1e7f) // highp
2020*35238bceSAndroid Build Coastguard Worker };
2021*35238bceSAndroid Build Coastguard Worker
2022*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()) ^ 0xac23fu);
2023*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
2024*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
2025*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
2026*35238bceSAndroid Build Coastguard Worker const float specialCases[][3] = {
2027*35238bceSAndroid Build Coastguard Worker // a b c
2028*35238bceSAndroid Build Coastguard Worker {0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f},
2029*35238bceSAndroid Build Coastguard Worker {-1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}, {-0.0f, 1.0f, 0.0f}, {1.0f, -0.0f, 0.0f}};
2030*35238bceSAndroid Build Coastguard Worker const int numSpecialCases = DE_LENGTH_OF_ARRAY(specialCases);
2031*35238bceSAndroid Build Coastguard Worker
2032*35238bceSAndroid Build Coastguard Worker // Special cases
2033*35238bceSAndroid Build Coastguard Worker for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++)
2034*35238bceSAndroid Build Coastguard Worker {
2035*35238bceSAndroid Build Coastguard Worker for (int inputNdx = 0; inputNdx < 3; inputNdx++)
2036*35238bceSAndroid Build Coastguard Worker {
2037*35238bceSAndroid Build Coastguard Worker for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
2038*35238bceSAndroid Build Coastguard Worker ((float *)values[inputNdx])[caseNdx * scalarSize + scalarNdx] = specialCases[caseNdx][inputNdx];
2039*35238bceSAndroid Build Coastguard Worker }
2040*35238bceSAndroid Build Coastguard Worker }
2041*35238bceSAndroid Build Coastguard Worker
2042*35238bceSAndroid Build Coastguard Worker // Random cases.
2043*35238bceSAndroid Build Coastguard Worker {
2044*35238bceSAndroid Build Coastguard Worker const int numScalars = (numValues - numSpecialCases) * scalarSize;
2045*35238bceSAndroid Build Coastguard Worker const int offs = scalarSize * numSpecialCases;
2046*35238bceSAndroid Build Coastguard Worker
2047*35238bceSAndroid Build Coastguard Worker for (int inputNdx = 0; inputNdx < 3; inputNdx++)
2048*35238bceSAndroid Build Coastguard Worker fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float *)values[inputNdx] + offs,
2049*35238bceSAndroid Build Coastguard Worker numScalars);
2050*35238bceSAndroid Build Coastguard Worker }
2051*35238bceSAndroid Build Coastguard Worker
2052*35238bceSAndroid Build Coastguard Worker // Make sure the values are representable in the target format
2053*35238bceSAndroid Build Coastguard Worker for (int inputNdx = 0; inputNdx < 3; inputNdx++)
2054*35238bceSAndroid Build Coastguard Worker {
2055*35238bceSAndroid Build Coastguard Worker for (int caseNdx = 0; caseNdx < numValues; ++caseNdx)
2056*35238bceSAndroid Build Coastguard Worker {
2057*35238bceSAndroid Build Coastguard Worker for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
2058*35238bceSAndroid Build Coastguard Worker {
2059*35238bceSAndroid Build Coastguard Worker float *const valuePtr = &((float *)values[inputNdx])[caseNdx * scalarSize + scalarNdx];
2060*35238bceSAndroid Build Coastguard Worker
2061*35238bceSAndroid Build Coastguard Worker *valuePtr = makeFloatRepresentable(*valuePtr, precision);
2062*35238bceSAndroid Build Coastguard Worker }
2063*35238bceSAndroid Build Coastguard Worker }
2064*35238bceSAndroid Build Coastguard Worker }
2065*35238bceSAndroid Build Coastguard Worker }
2066*35238bceSAndroid Build Coastguard Worker
fma(glu::Precision precision,float a,float b,float c)2067*35238bceSAndroid Build Coastguard Worker static tcu::Interval fma(glu::Precision precision, float a, float b, float c)
2068*35238bceSAndroid Build Coastguard Worker {
2069*35238bceSAndroid Build Coastguard Worker const tcu::FloatFormat formats[] = {
2070*35238bceSAndroid Build Coastguard Worker // minExp maxExp mantissa exact, subnormals infinities NaN
2071*35238bceSAndroid Build Coastguard Worker tcu::FloatFormat(0, 0, 7, false, tcu::YES, tcu::MAYBE, tcu::MAYBE),
2072*35238bceSAndroid Build Coastguard Worker tcu::FloatFormat(-13, 13, 9, false, tcu::MAYBE, tcu::MAYBE, tcu::MAYBE),
2073*35238bceSAndroid Build Coastguard Worker tcu::FloatFormat(-126, 127, 23, true, tcu::MAYBE, tcu::YES, tcu::MAYBE)};
2074*35238bceSAndroid Build Coastguard Worker const tcu::FloatFormat &format = de::getSizedArrayElement<glu::PRECISION_LAST>(formats, precision);
2075*35238bceSAndroid Build Coastguard Worker const tcu::Interval ia = format.convert(a);
2076*35238bceSAndroid Build Coastguard Worker const tcu::Interval ib = format.convert(b);
2077*35238bceSAndroid Build Coastguard Worker const tcu::Interval ic = format.convert(c);
2078*35238bceSAndroid Build Coastguard Worker tcu::Interval prod0;
2079*35238bceSAndroid Build Coastguard Worker tcu::Interval prod1;
2080*35238bceSAndroid Build Coastguard Worker tcu::Interval prod2;
2081*35238bceSAndroid Build Coastguard Worker tcu::Interval prod3;
2082*35238bceSAndroid Build Coastguard Worker tcu::Interval prod;
2083*35238bceSAndroid Build Coastguard Worker tcu::Interval res;
2084*35238bceSAndroid Build Coastguard Worker
2085*35238bceSAndroid Build Coastguard Worker TCU_SET_INTERVAL(prod0, tmp, tmp = ia.lo() * ib.lo());
2086*35238bceSAndroid Build Coastguard Worker TCU_SET_INTERVAL(prod1, tmp, tmp = ia.lo() * ib.hi());
2087*35238bceSAndroid Build Coastguard Worker TCU_SET_INTERVAL(prod2, tmp, tmp = ia.hi() * ib.lo());
2088*35238bceSAndroid Build Coastguard Worker TCU_SET_INTERVAL(prod3, tmp, tmp = ia.hi() * ib.hi());
2089*35238bceSAndroid Build Coastguard Worker
2090*35238bceSAndroid Build Coastguard Worker prod = format.convert(format.roundOut(prod0 | prod1 | prod2 | prod3,
2091*35238bceSAndroid Build Coastguard Worker ia.isFinite(format.getMaxValue()) && ib.isFinite(format.getMaxValue())));
2092*35238bceSAndroid Build Coastguard Worker
2093*35238bceSAndroid Build Coastguard Worker TCU_SET_INTERVAL_BOUNDS(res, tmp, tmp = prod.lo() + ic.lo(), tmp = prod.hi() + ic.hi());
2094*35238bceSAndroid Build Coastguard Worker
2095*35238bceSAndroid Build Coastguard Worker return format.convert(
2096*35238bceSAndroid Build Coastguard Worker format.roundOut(res, prod.isFinite(format.getMaxValue()) && ic.isFinite(format.getMaxValue())));
2097*35238bceSAndroid Build Coastguard Worker }
2098*35238bceSAndroid Build Coastguard Worker
compare(const void * const * inputs,const void * const * outputs)2099*35238bceSAndroid Build Coastguard Worker bool compare(const void *const *inputs, const void *const *outputs)
2100*35238bceSAndroid Build Coastguard Worker {
2101*35238bceSAndroid Build Coastguard Worker const glu::DataType type = m_spec.inputs[0].varType.getBasicType();
2102*35238bceSAndroid Build Coastguard Worker const glu::Precision precision = m_spec.inputs[0].varType.getPrecision();
2103*35238bceSAndroid Build Coastguard Worker const int scalarSize = glu::getDataTypeScalarSize(type);
2104*35238bceSAndroid Build Coastguard Worker
2105*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < scalarSize; compNdx++)
2106*35238bceSAndroid Build Coastguard Worker {
2107*35238bceSAndroid Build Coastguard Worker const float a = ((const float *)inputs[0])[compNdx];
2108*35238bceSAndroid Build Coastguard Worker const float b = ((const float *)inputs[1])[compNdx];
2109*35238bceSAndroid Build Coastguard Worker const float c = ((const float *)inputs[2])[compNdx];
2110*35238bceSAndroid Build Coastguard Worker const float res = ((const float *)outputs[0])[compNdx];
2111*35238bceSAndroid Build Coastguard Worker const tcu::Interval ref = fma(precision, a, b, c);
2112*35238bceSAndroid Build Coastguard Worker
2113*35238bceSAndroid Build Coastguard Worker if (!ref.contains(res))
2114*35238bceSAndroid Build Coastguard Worker {
2115*35238bceSAndroid Build Coastguard Worker m_failMsg << "Expected [" << compNdx << "] = " << ref;
2116*35238bceSAndroid Build Coastguard Worker return false;
2117*35238bceSAndroid Build Coastguard Worker }
2118*35238bceSAndroid Build Coastguard Worker }
2119*35238bceSAndroid Build Coastguard Worker
2120*35238bceSAndroid Build Coastguard Worker return true;
2121*35238bceSAndroid Build Coastguard Worker }
2122*35238bceSAndroid Build Coastguard Worker };
2123*35238bceSAndroid Build Coastguard Worker
ShaderCommonFunctionTests(Context & context)2124*35238bceSAndroid Build Coastguard Worker ShaderCommonFunctionTests::ShaderCommonFunctionTests(Context &context)
2125*35238bceSAndroid Build Coastguard Worker : TestCaseGroup(context, "common", "Common function tests")
2126*35238bceSAndroid Build Coastguard Worker {
2127*35238bceSAndroid Build Coastguard Worker }
2128*35238bceSAndroid Build Coastguard Worker
~ShaderCommonFunctionTests(void)2129*35238bceSAndroid Build Coastguard Worker ShaderCommonFunctionTests::~ShaderCommonFunctionTests(void)
2130*35238bceSAndroid Build Coastguard Worker {
2131*35238bceSAndroid Build Coastguard Worker }
2132*35238bceSAndroid Build Coastguard Worker
2133*35238bceSAndroid Build Coastguard Worker template <class TestClass>
addFunctionCases(TestCaseGroup * parent,const char * functionName,bool floatTypes,bool intTypes,bool uintTypes,uint32_t shaderBits)2134*35238bceSAndroid Build Coastguard Worker static void addFunctionCases(TestCaseGroup *parent, const char *functionName, bool floatTypes, bool intTypes,
2135*35238bceSAndroid Build Coastguard Worker bool uintTypes, uint32_t shaderBits)
2136*35238bceSAndroid Build Coastguard Worker {
2137*35238bceSAndroid Build Coastguard Worker tcu::TestCaseGroup *group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName);
2138*35238bceSAndroid Build Coastguard Worker parent->addChild(group);
2139*35238bceSAndroid Build Coastguard Worker
2140*35238bceSAndroid Build Coastguard Worker const glu::DataType scalarTypes[] = {glu::TYPE_FLOAT, glu::TYPE_INT, glu::TYPE_UINT};
2141*35238bceSAndroid Build Coastguard Worker
2142*35238bceSAndroid Build Coastguard Worker for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++)
2143*35238bceSAndroid Build Coastguard Worker {
2144*35238bceSAndroid Build Coastguard Worker const glu::DataType scalarType = scalarTypes[scalarTypeNdx];
2145*35238bceSAndroid Build Coastguard Worker
2146*35238bceSAndroid Build Coastguard Worker if ((!floatTypes && scalarType == glu::TYPE_FLOAT) || (!intTypes && scalarType == glu::TYPE_INT) ||
2147*35238bceSAndroid Build Coastguard Worker (!uintTypes && scalarType == glu::TYPE_UINT))
2148*35238bceSAndroid Build Coastguard Worker continue;
2149*35238bceSAndroid Build Coastguard Worker
2150*35238bceSAndroid Build Coastguard Worker for (int vecSize = 1; vecSize <= 4; vecSize++)
2151*35238bceSAndroid Build Coastguard Worker {
2152*35238bceSAndroid Build Coastguard Worker for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++)
2153*35238bceSAndroid Build Coastguard Worker {
2154*35238bceSAndroid Build Coastguard Worker for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++)
2155*35238bceSAndroid Build Coastguard Worker {
2156*35238bceSAndroid Build Coastguard Worker if (shaderBits & (1 << shaderTypeNdx))
2157*35238bceSAndroid Build Coastguard Worker group->addChild(new TestClass(parent->getContext(), glu::DataType(scalarType + vecSize - 1),
2158*35238bceSAndroid Build Coastguard Worker glu::Precision(prec), glu::ShaderType(shaderTypeNdx)));
2159*35238bceSAndroid Build Coastguard Worker }
2160*35238bceSAndroid Build Coastguard Worker }
2161*35238bceSAndroid Build Coastguard Worker }
2162*35238bceSAndroid Build Coastguard Worker }
2163*35238bceSAndroid Build Coastguard Worker }
2164*35238bceSAndroid Build Coastguard Worker
init(void)2165*35238bceSAndroid Build Coastguard Worker void ShaderCommonFunctionTests::init(void)
2166*35238bceSAndroid Build Coastguard Worker {
2167*35238bceSAndroid Build Coastguard Worker enum
2168*35238bceSAndroid Build Coastguard Worker {
2169*35238bceSAndroid Build Coastguard Worker VS = (1 << glu::SHADERTYPE_VERTEX),
2170*35238bceSAndroid Build Coastguard Worker TC = (1 << glu::SHADERTYPE_TESSELLATION_CONTROL),
2171*35238bceSAndroid Build Coastguard Worker TE = (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION),
2172*35238bceSAndroid Build Coastguard Worker GS = (1 << glu::SHADERTYPE_GEOMETRY),
2173*35238bceSAndroid Build Coastguard Worker FS = (1 << glu::SHADERTYPE_FRAGMENT),
2174*35238bceSAndroid Build Coastguard Worker CS = (1 << glu::SHADERTYPE_COMPUTE),
2175*35238bceSAndroid Build Coastguard Worker
2176*35238bceSAndroid Build Coastguard Worker ALL_SHADERS = VS | TC | TE | GS | FS | CS,
2177*35238bceSAndroid Build Coastguard Worker NEW_SHADERS = TC | TE | GS | CS,
2178*35238bceSAndroid Build Coastguard Worker };
2179*35238bceSAndroid Build Coastguard Worker
2180*35238bceSAndroid Build Coastguard Worker // Float? Int? Uint? Shaders
2181*35238bceSAndroid Build Coastguard Worker addFunctionCases<AbsCase>(this, "abs", true, true, false, NEW_SHADERS);
2182*35238bceSAndroid Build Coastguard Worker addFunctionCases<SignCase>(this, "sign", true, true, false, NEW_SHADERS);
2183*35238bceSAndroid Build Coastguard Worker addFunctionCases<FloorCase>(this, "floor", true, false, false, NEW_SHADERS);
2184*35238bceSAndroid Build Coastguard Worker addFunctionCases<TruncCase>(this, "trunc", true, false, false, NEW_SHADERS);
2185*35238bceSAndroid Build Coastguard Worker addFunctionCases<RoundCase>(this, "round", true, false, false, NEW_SHADERS);
2186*35238bceSAndroid Build Coastguard Worker addFunctionCases<RoundEvenCase>(this, "roundeven", true, false, false, NEW_SHADERS);
2187*35238bceSAndroid Build Coastguard Worker addFunctionCases<CeilCase>(this, "ceil", true, false, false, NEW_SHADERS);
2188*35238bceSAndroid Build Coastguard Worker addFunctionCases<FractCase>(this, "fract", true, false, false, NEW_SHADERS);
2189*35238bceSAndroid Build Coastguard Worker // mod
2190*35238bceSAndroid Build Coastguard Worker addFunctionCases<ModfCase>(this, "modf", true, false, false, NEW_SHADERS);
2191*35238bceSAndroid Build Coastguard Worker // min
2192*35238bceSAndroid Build Coastguard Worker // max
2193*35238bceSAndroid Build Coastguard Worker // clamp
2194*35238bceSAndroid Build Coastguard Worker // mix
2195*35238bceSAndroid Build Coastguard Worker // step
2196*35238bceSAndroid Build Coastguard Worker // smoothstep
2197*35238bceSAndroid Build Coastguard Worker addFunctionCases<IsnanCase>(this, "isnan", true, false, false, NEW_SHADERS);
2198*35238bceSAndroid Build Coastguard Worker addFunctionCases<IsinfCase>(this, "isinf", true, false, false, NEW_SHADERS);
2199*35238bceSAndroid Build Coastguard Worker addFunctionCases<FloatBitsToIntCase>(this, "floatbitstoint", true, false, false, NEW_SHADERS);
2200*35238bceSAndroid Build Coastguard Worker addFunctionCases<FloatBitsToUintCase>(this, "floatbitstouint", true, false, false, NEW_SHADERS);
2201*35238bceSAndroid Build Coastguard Worker
2202*35238bceSAndroid Build Coastguard Worker addFunctionCases<FrexpCase>(this, "frexp", true, false, false, ALL_SHADERS);
2203*35238bceSAndroid Build Coastguard Worker addFunctionCases<LdexpCase>(this, "ldexp", true, false, false, ALL_SHADERS);
2204*35238bceSAndroid Build Coastguard Worker addFunctionCases<FmaCase>(this, "fma", true, false, false, ALL_SHADERS);
2205*35238bceSAndroid Build Coastguard Worker
2206*35238bceSAndroid Build Coastguard Worker // (u)intBitsToFloat()
2207*35238bceSAndroid Build Coastguard Worker {
2208*35238bceSAndroid Build Coastguard Worker const uint32_t shaderBits = NEW_SHADERS;
2209*35238bceSAndroid Build Coastguard Worker tcu::TestCaseGroup *intGroup = new tcu::TestCaseGroup(m_testCtx, "intbitstofloat", "intBitsToFloat() Tests");
2210*35238bceSAndroid Build Coastguard Worker tcu::TestCaseGroup *uintGroup = new tcu::TestCaseGroup(m_testCtx, "uintbitstofloat", "uintBitsToFloat() Tests");
2211*35238bceSAndroid Build Coastguard Worker
2212*35238bceSAndroid Build Coastguard Worker addChild(intGroup);
2213*35238bceSAndroid Build Coastguard Worker addChild(uintGroup);
2214*35238bceSAndroid Build Coastguard Worker
2215*35238bceSAndroid Build Coastguard Worker for (int vecSize = 1; vecSize < 4; vecSize++)
2216*35238bceSAndroid Build Coastguard Worker {
2217*35238bceSAndroid Build Coastguard Worker const glu::DataType intType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
2218*35238bceSAndroid Build Coastguard Worker const glu::DataType uintType = vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
2219*35238bceSAndroid Build Coastguard Worker
2220*35238bceSAndroid Build Coastguard Worker for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
2221*35238bceSAndroid Build Coastguard Worker {
2222*35238bceSAndroid Build Coastguard Worker if (shaderBits & (1 << shaderType))
2223*35238bceSAndroid Build Coastguard Worker {
2224*35238bceSAndroid Build Coastguard Worker intGroup->addChild(new BitsToFloatCase(m_context, intType, glu::ShaderType(shaderType)));
2225*35238bceSAndroid Build Coastguard Worker uintGroup->addChild(new BitsToFloatCase(m_context, uintType, glu::ShaderType(shaderType)));
2226*35238bceSAndroid Build Coastguard Worker }
2227*35238bceSAndroid Build Coastguard Worker }
2228*35238bceSAndroid Build Coastguard Worker }
2229*35238bceSAndroid Build Coastguard Worker }
2230*35238bceSAndroid Build Coastguard Worker }
2231*35238bceSAndroid Build Coastguard Worker
2232*35238bceSAndroid Build Coastguard Worker } // namespace Functional
2233*35238bceSAndroid Build Coastguard Worker } // namespace gles31
2234*35238bceSAndroid Build Coastguard Worker } // namespace deqp
2235