13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.0 Module 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ------------------------------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Common built-in function tests. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es3fShaderCommonFunctionTests.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderExecUtil.hpp" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFormatUtil.hpp" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp" 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp" 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h" 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h" 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles3 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector; 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string; 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog; 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls::ShaderExecUtil; 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2; 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec3; 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4; 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2; 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec3; 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec4; 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Utilities 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size> 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VecArrayAccess 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VecArrayAccess (const void* ptr) : m_array((tcu::Vector<T, Size>*)ptr) {} 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~VecArrayAccess (void) {} 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<T, Size>& operator[] (size_t offset) const { return m_array[offset]; } 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<T, Size>& operator[] (size_t offset) { return m_array[offset]; } 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<T, Size>* m_array; 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T> T randomScalar (de::Random& rnd, T minValue, T maxValue); 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline float randomScalar (de::Random& rnd, float minValue, float maxValue) { return rnd.getFloat(minValue, maxValue); } 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline deInt32 randomScalar (de::Random& rnd, deInt32 minValue, deInt32 maxValue) { return rnd.getInt(minValue, maxValue); } 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline deUint32 randomScalar (de::Random& rnd, deUint32 minValue, deUint32 maxValue) { return minValue + rnd.getUint32() % (maxValue - minValue + 1); } 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size> 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::Vector<T, Size> randomVector (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue) 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<T, Size> res; 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < Size; ndx++) 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry res[ndx] = randomScalar<T>(rnd, minValue[ndx], maxValue[ndx]); 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return res; 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size> 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void fillRandomVectors (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue, void* dst, int numValues, int offset = 0) 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VecArrayAccess<T, Size> access(dst); 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues; ndx++) 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry access[offset + ndx] = randomVector<T, Size>(rnd, minValue, maxValue); 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T> 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0) 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry T* typedPtr = (T*)dst; 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues; ndx++) 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue); 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline int numBitsLostInOp (float input, float output) 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int inExp = tcu::Float32(input).exponent(); 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outExp = tcu::Float32(output).exponent(); 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return de::max(0, inExp-outExp); // Lost due to mantissa shift. 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getUlpDiff (float a, float b) 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 aBits = tcu::Float32(a).bits(); 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 bBits = tcu::Float32(b).bits(); 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return aBits > bBits ? aBits - bBits : bBits - aBits; 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getUlpDiffIgnoreZeroSign (float a, float b) 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (tcu::Float32(a).isZero()) 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getUlpDiff(tcu::Float32::construct(tcu::Float32(b).sign(), 0, 0).asFloat(), b); 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (tcu::Float32(b).isZero()) 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getUlpDiff(a, tcu::Float32::construct(tcu::Float32(a).sign(), 0, 0).asFloat()); 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getUlpDiff(a, b); 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline bool supportsSignedZero (glu::Precision precision) 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note GLSL ES 3.0 doesn't really require support for -0, but we require it for highp 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // as it is very widely supported. 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return precision == glu::PRECISION_HIGHP; 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float getEpsFromMaxUlpDiff (float value, deUint32 ulpDiff) 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int exp = tcu::Float32(value).exponent(); 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::Float32::construct(+1, exp, (1u<<23) | ulpDiff).asFloat() - tcu::Float32::construct(+1, exp, 1u<<23).asFloat(); 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getMaxUlpDiffFromBits (int numAccurateBits) 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numGarbageBits = 23-numAccurateBits; 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mask = (1u<<numGarbageBits)-1u; 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return mask; 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float getEpsFromBits (float value, int numAccurateBits) 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getEpsFromMaxUlpDiff(value, getMaxUlpDiffFromBits(numAccurateBits)); 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getMinMantissaBits (glu::Precision precision) 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int bits[] = 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7, // lowp 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10, // mediump 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23 // highp 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bits) == glu::PRECISION_LAST); 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(bits))); 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return bits[precision]; 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CommonFunctionCase 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CommonFunctionCase : public TestCase 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommonFunctionCase (Context& context, const char* name, const char* description, glu::ShaderType shaderType); 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~CommonFunctionCase (void); 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void); 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void deinit (void); 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommonFunctionCase (const CommonFunctionCase& other); 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommonFunctionCase& operator= (const CommonFunctionCase& other); 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry virtual void getInputValues (int numValues, void* const* values) const = 0; 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry virtual bool compare (const void* const* inputs, const void* const* outputs) = 0; 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ShaderType m_shaderType; 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderSpec m_spec; 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int m_numValues; 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream m_failMsg; //!< Comparison failure help message. 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderExecutor* m_executor; 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1913c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::CommonFunctionCase (Context& context, const char* name, const char* description, glu::ShaderType shaderType) 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_shaderType (shaderType) 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_numValues (100) 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_executor (DE_NULL) 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.version = glu::GLSL_VERSION_300_ES; 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2003c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::~CommonFunctionCase (void) 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommonFunctionCase::deinit(); 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonFunctionCase::init (void) 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!m_executor); 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec); 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << m_executor; 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_executor->isOk()) 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::TestError("Compile failed"); 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonFunctionCase::deinit (void) 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete m_executor; 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_executor = DE_NULL; 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<int> getScalarSizes (const vector<Symbol>& symbols) 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<int> sizes(symbols.size()); 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < (int)symbols.size(); ++ndx) 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry sizes[ndx] = symbols[ndx].varType.getScalarSize(); 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return sizes; 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int computeTotalScalarSize (const vector<Symbol>& symbols) 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int totalSize = 0; 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym) 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry totalSize += sym->varType.getScalarSize(); 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return totalSize; 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<void*> getInputOutputPointers (const vector<Symbol>& symbols, vector<deUint32>& data, const int numValues) 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<void*> pointers (symbols.size()); 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int curScalarOffset = 0; 2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx) 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Symbol& var = symbols[varNdx]; 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = var.varType.getScalarSize(); 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Uses planar layout as input/output specs do not support strides. 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pointers[varNdx] = &data[curScalarOffset]; 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curScalarOffset += scalarSize*numValues; 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(curScalarOffset == (int)data.size()); 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return pointers; 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \todo [2013-08-08 pyry] Make generic utility and move to glu? 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct HexFloat 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float value; 2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry HexFloat (const float value_) : value(value_) {} 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const HexFloat& v) 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits()); 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct HexBool 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 value; 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry HexBool (const deUint32 value_) : value(value_) {} 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const HexBool& v) 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return str << (v.value ? "true" : "false") << " / " << tcu::toHex(v.value); 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VarValue 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VarType& type; 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const void* value; 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VarValue (const glu::VarType& type_, const void* value_) : type(type_), value(value_) {} 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const VarValue& varValue) 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(varValue.type.isBasicType()); 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType basicType = varValue.type.getBasicType(); 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType scalarType = glu::getDataTypeScalarType(basicType); 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numComponents = glu::getDataTypeScalarSize(basicType); 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (numComponents > 1) 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry str << glu::getDataTypeName(basicType) << "("; 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < numComponents; compNdx++) 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (compNdx != 0) 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry str << ", "; 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (scalarType) 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_FLOAT: str << HexFloat(((const float*)varValue.value)[compNdx]); break; 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_INT: str << ((const deInt32*)varValue.value)[compNdx]; break; 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_UINT: str << tcu::toHex(((const deUint32*)varValue.value)[compNdx]); break; 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_BOOL: str << HexBool(((const deUint32*)varValue.value)[compNdx]); break; 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (numComponents > 1) 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry str << ")"; 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return str; 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::IterateResult CommonFunctionCase::iterate (void) 3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numInputScalars = computeTotalScalarSize(m_spec.inputs); 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numOutputScalars = computeTotalScalarSize(m_spec.outputs); 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<deUint32> inputData (numInputScalars * m_numValues); 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<deUint32> outputData (numOutputScalars * m_numValues); 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const vector<void*> inputPointers = getInputOutputPointers(m_spec.inputs, inputData, m_numValues); 3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const vector<void*> outputPointers = getInputOutputPointers(m_spec.outputs, outputData, m_numValues); 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Initialize input data. 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getInputValues(m_numValues, &inputPointers[0]); 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Execute shader. 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_executor->useProgram(); 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]); 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compare results. 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const vector<int> inScalarSizes = getScalarSizes(m_spec.inputs); 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const vector<int> outScalarSizes = getScalarSizes(m_spec.outputs); 3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<void*> curInputPtr (inputPointers.size()); 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<void*> curOutputPtr (outputPointers.size()); 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numFailed = 0; 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < m_numValues; valNdx++) 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Set up pointers for comparison. 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx) 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curInputPtr[inNdx] = (deUint32*)inputPointers[inNdx] + inScalarSizes[inNdx]*valNdx; 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx) 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curOutputPtr[outNdx] = (deUint32*)outputPointers[outNdx] + outScalarSizes[outNdx]*valNdx; 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!compare(&curInputPtr[0], &curOutputPtr[0])) 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \todo [2013-08-08 pyry] We probably want to log reference value as well? 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n " << m_failMsg.str() << TestLog::EndMessage; 3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << " inputs:" << TestLog::EndMessage; 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++) 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << " " << m_spec.inputs[inNdx].name << " = " 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx]) 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << " outputs:" << TestLog::EndMessage; 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++) 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << " " << m_spec.outputs[outNdx].name << " = " 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx]) 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg.str(""); 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg.clear(); 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numFailed += 1; 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed" << TestLog::EndMessage; 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numFailed == 0 ? "Pass" : "Result comparison failed"); 3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getPrecisionPostfix (glu::Precision precision) 3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const char* s_postfix[] = 3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_lowp", 3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_mediump", 3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_highp" 3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_postfix) == glu::PRECISION_LAST); 3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(s_postfix))); 4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return s_postfix[precision]; 4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getShaderTypePostfix (glu::ShaderType shaderType) 4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const char* s_postfix[] = 4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_vertex", 4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_fragment" 4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_postfix))); 4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return s_postfix[shaderType]; 4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string getCommonFuncCaseName (glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType); 4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AbsCase : public CommonFunctionCase 4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry AbsCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "abs", shaderType) 4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = abs(in0);"; 4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 floatRanges[] = 4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 intRanges[] = 4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(-(1<<7)+1, (1<<7)-1), 4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(-(1<<15)+1, (1<<15)-1), 4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(0x80000001, 0x7fffffff) 4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0x235facu); 4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(type)) 4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), values[0], numValues*scalarSize); 4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), values[0], numValues*scalarSize); 4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(type)) 4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = (1u<<(23-mantissaBits))-1u; 4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref0 = de::abs(in0); 4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff0 = getUlpDiff(out0, ref0); 4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff0 > maxUlpDiff) 4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0; 4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int in0 = ((const int*)inputs[0])[compNdx]; 4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int out0 = ((const int*)outputs[0])[compNdx]; 4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ref0 = de::abs(in0); 4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != ref0) 4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << ref0; 4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SignCase : public CommonFunctionCase 5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SignCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "sign", shaderType) 5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = sign(in0);"; 5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 floatRanges[] = 5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e4f, 1e4f), // mediump - note: may end up as inf 5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e8f, 1e8f) // highp - note: may end up as inf 5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 intRanges[] = 5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(-(1<<7), (1<<7)-1), 5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(-(1<<15), (1<<15)-1), 5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(0x80000000, 0x7fffffff) 5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0x324u); 5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(type)) 5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases. 535b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos std::fill((float*)values[0], (float*)values[0] + scalarSize, +1.0f); 536b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos std::fill((float*)values[0] + scalarSize*1, (float*)values[0] + scalarSize*2, -1.0f); 537b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos std::fill((float*)values[0] + scalarSize*2, (float*)values[0] + scalarSize*3, 0.0f); 5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), (float*)values[0] + scalarSize*3, (numValues-3)*scalarSize); 5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 542b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos std::fill((int*)values[0], (int*)values[0] + scalarSize, +1); 543b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos std::fill((int*)values[0] + scalarSize*1, (int*)values[0] + scalarSize*2, -1); 544b55a172c47932197abc5e18950a70c938ef302c0Pyry Haulos std::fill((int*)values[0] + scalarSize*2, (int*)values[0] + scalarSize*3, 0); 5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), (int*)values[0] + scalarSize*3, (numValues-3)*scalarSize); 5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(type)) 5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Both highp and mediump should be able to represent -1, 0, and +1 exactly 5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = precision == glu::PRECISION_LOWP ? getMaxUlpDiffFromBits(getMinMantissaBits(precision)) : 0; 5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref0 = in0 < 0.0f ? -1.0f : 5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry in0 > 0.0f ? +1.0f : 0.0f; 5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff0 = getUlpDiff(out0, ref0); 5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff0 > maxUlpDiff) 5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0; 5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int in0 = ((const int*)inputs[0])[compNdx]; 5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int out0 = ((const int*)outputs[0])[compNdx]; 5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ref0 = in0 < 0 ? -1 : 5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry in0 > 0 ? +1 : 0; 5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != ref0) 5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << ref0; 5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float roundEven (float v) 5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float q = deFloatFrac(v); 5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int truncated = int(v-q); 6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int rounded = (q > 0.5f) ? (truncated + 1) : // Rounded up 6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (q == 0.5f && (truncated % 2 != 0)) ? (truncated + 1) : // Round to nearest even at 0.5 6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry truncated; // Rounded down 6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return float(rounded); 6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RoundEvenCase : public CommonFunctionCase 6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry RoundEvenCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "roundEven", shaderType) 6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = roundEven(in0);"; 6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numSpecialCases = 0; 6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases. 6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision != glu::PRECISION_LOWP) 6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(numValues >= 20); 6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 20; ndx++) 6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float v = de::clamp(float(ndx) - 10.5f, ranges[precision].x(), ranges[precision].y()); 6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((float*)values[0], (float*)values[0] + scalarSize, v); 6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numSpecialCases += 1; 6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize); 6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasSignedZero = supportsSignedZero(precision); 6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact rounding result. 6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = roundEven(in0); 6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref); 6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(roundEven(in0-eps)); 6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(roundEven(in0+eps)); 6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal)); 6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ModfCase : public CommonFunctionCase 7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ModfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "modf", shaderType) 7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out1", glu::VarType(baseType, precision))); 7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = modf(in0, out1);"; 7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize); 7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasZeroSign = supportsSignedZero(precision); 7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out1 = ((const float*)outputs[1])[compNdx]; 7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float refOut1 = float(int(in0)); 7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float refOut0 = in0 - refOut1; 7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int bitsLost = precision != glu::PRECISION_HIGHP ? numBitsLostInOp(in0, refOut0) : 0; 7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(de::max(mantissaBits - bitsLost, 0)); 7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float resSum = out0 + out1; 7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasZeroSign ? getUlpDiff(resSum, in0) : getUlpDiffIgnoreZeroSign(resSum, in0); 7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = (" << HexFloat(refOut0) << ") + (" << HexFloat(refOut1) << ") = " << HexFloat(in0) << " with ULP threshold " 7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff); 7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsnanCase : public CommonFunctionCase 7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IsnanCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isnan", shaderType) 7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(glu::isDataTypeFloatOrVec(baseType)); 7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType boolType = vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL; 7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST))); 7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = isnan(in0);"; 7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xc2a39fu); 8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mantissaMask = ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u); 8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++) 8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isNan = rnd.getFloat() > 0.3f; 8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isInf = !isNan && rnd.getFloat() > 0.4f; 8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mantissa = !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0; 8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 exp = !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu; 8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 sign = rnd.getUint32() & 0x1u; 8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 value = (sign << 31) | (exp << 23) | mantissa; 8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan); 8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((deUint32*)values[0])[valNdx] = value; 8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP) 8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Only highp is required to support inf/nan 8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 out0 = ((const deUint32*)outputs[0])[compNdx]; 8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ref = tcu::Float32(in0).isNaN() ? 1u : 0u; 8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != ref) 8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref); 8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Value can be either 0 or 1 8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int out0 = ((const int*)outputs[0])[compNdx]; 8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != 0 && out0 != 1) 8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = 0 / 1"; 8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsinfCase : public CommonFunctionCase 8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IsinfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isinf", shaderType) 8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(glu::isDataTypeFloatOrVec(baseType)); 8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType boolType = vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL; 8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST))); 8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = isinf(in0);"; 8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xc2a39fu); 8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mantissaMask = ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u); 8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++) 8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isInf = rnd.getFloat() > 0.3f; 8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isNan = !isInf && rnd.getFloat() > 0.4f; 8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mantissa = !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0; 8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 exp = !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu; 8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 sign = rnd.getUint32() & 0x1u; 8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 value = (sign << 31) | (exp << 23) | mantissa; 8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan); 9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((deUint32*)values[0])[valNdx] = value; 9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP) 9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Only highp is required to support inf/nan 9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 out0 = ((const deUint32*)outputs[0])[compNdx]; 9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ref = tcu::Float32(in0).isInf() ? 1u : 0u; 9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != ref) 9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref); 9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Value can be either 0 or 1 9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int out0 = ((const int*)outputs[0])[compNdx]; 9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != 0 && out0 != 1) 9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = 0 / 1"; 9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToUintIntCase : public CommonFunctionCase 9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FloatBitsToUintIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType, bool outIsSigned) 9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), outIsSigned ? "floatBitsToInt" : "floatBitsToUint", shaderType) 9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intType = outIsSigned ? (vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT) 9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : (vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT); 9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(intType, glu::PRECISION_HIGHP))); 9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = outIsSigned ? "out0 = floatBitsToInt(in0);" : "out0 = floatBitsToUint(in0);"; 9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0x2790au); 9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize); 9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); 9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 out0 = ((const deUint32*)outputs[0])[compNdx]; 9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 refOut0 = tcu::Float32(in0).bits(); 9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ulpDiff = de::abs((int)out0 - (int)refOut0); 9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(refOut0) << " with threshold " 9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff); 9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToIntCase : public FloatBitsToUintIntCase 10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FloatBitsToIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : FloatBitsToUintIntCase(context, baseType, precision, shaderType, true) 10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToUintCase : public FloatBitsToUintIntCase 10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FloatBitsToUintCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : FloatBitsToUintIntCase(context, baseType, precision, shaderType, false) 10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BitsToFloatCase : public CommonFunctionCase 10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BitsToFloatCase (Context& context, glu::DataType baseType, glu::ShaderType shaderType) 10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, glu::PRECISION_HIGHP, shaderType).c_str(), glu::isDataTypeIntOrIVec(baseType) ? "intBitsToFloat" : "uintBitsToFloat", shaderType) 10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool inIsSigned = glu::isDataTypeIntOrIVec(baseType); 10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType floatType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT; 10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, glu::PRECISION_HIGHP))); 10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(floatType, glu::PRECISION_HIGHP))); 10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = inIsSigned ? "out0 = intBitsToFloat(in0);" : "out0 = uintBitsToFloat(in0);"; 10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xbbb225u); 10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 range (-1e8f, +1e8f); 10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Filled as floats. 10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, range.x(), range.y(), values[0], numValues*scalarSize); 10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 10548a14bbb74876a4a318d6277a3afeb8d35d682aafPyry Haulos const deUint32 maxUlpDiff = 0; 10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 10608a14bbb74876a4a318d6277a3afeb8d35d682aafPyry Haulos const deUint32 ulpDiff = getUlpDiff(in0, out0); 10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10648a14bbb74876a4a318d6277a3afeb8d35d682aafPyry Haulos m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(tcu::Float32(in0).bits()) << " with ULP threshold " 10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff); 10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloorCase : public CommonFunctionCase 10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FloorCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "floor", shaderType) 10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = floor(in0);"; 10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize); 11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result. 11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = deFloatFloor(in0); 11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiff(out0, ref); 11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(deFloatFloor(in0-eps)); 11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(deFloatFloor(in0+eps)); 11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiff(out0, float(roundedVal)); 11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TruncCase : public CommonFunctionCase 11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TruncCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "trunc", shaderType) 11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = trunc(in0);"; 11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float specialCases[] = { 0.0f, -0.0f, -0.9f, 0.9f, 1.0f, -1.0f }; 11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSpecialCases = DE_LENGTH_OF_ARRAY(specialCases); 11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases 11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++) 11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) 12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[caseNdx*scalarSize + scalarNdx] = specialCases[caseNdx]; 12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + scalarSize*numSpecialCases, (numValues-numSpecialCases)*scalarSize); 12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result. 12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isNeg = tcu::Float32(in0).sign() < 0; 12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = isNeg ? (-float(int(-in0))) : float(int(in0)); 12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1231ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry // \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero. 1232ade588f3b2b1b6d007b9681e95434dc4a4bd46caJarkko Pöyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, ref); 12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(in0-eps); 12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(in0+eps); 12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal)); 12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RoundCase : public CommonFunctionCase 12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry RoundCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "round", shaderType) 12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = round(in0);"; 12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numSpecialCases = 0; 13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases. 13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision != glu::PRECISION_LOWP) 13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(numValues >= 10); 13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 10; ndx++) 13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y()); 13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((float*)values[0], (float*)values[0] + scalarSize, v); 13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numSpecialCases += 1; 13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize); 13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasZeroSign = supportsSignedZero(precision); 13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (deFloatFrac(in0) == 0.5f) 13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Allow both ceil(in) and floor(in) 13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref0 = deFloatFloor(in0); 13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref1 = deFloatCeil(in0); 13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff0 = hasZeroSign ? getUlpDiff(out0, ref0) : getUlpDiffIgnoreZeroSign(out0, ref0); 13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff1 = hasZeroSign ? getUlpDiff(out0, ref1) : getUlpDiffIgnoreZeroSign(out0, ref1); 13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff0 > 0 && ulpDiff1 > 0) 13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " or " << HexFloat(ref1) << ", got ULP diff " << tcu::toHex(de::min(ulpDiff0, ulpDiff1)); 13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result 13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = roundEven(in0); 13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref); 13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(roundEven(in0-eps)); 13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(roundEven(in0+eps)); 13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal)); 13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CeilCase : public CommonFunctionCase 14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CeilCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ceil", shaderType) 14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = ceil(in0);"; 14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize); 14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasZeroSign = supportsSignedZero(precision); 14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result. 14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = deFloatCeil(in0); 14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref); 14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(deFloatCeil(in0-eps)); 14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(deFloatCeil(in0+eps)); 14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal)); 14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk && de::inRange(0, minRes, maxRes)) 14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Allow -0 as well. 14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ulpDiff = de::abs((int)tcu::Float32(out0).bits() - (int)0x80000000u); 14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = ((deUint32)ulpDiff <= maxUlpDiff); 14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FractCase : public CommonFunctionCase 15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FractCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fract", shaderType) 15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = fract(in0);"; 15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numSpecialCases = 0; 15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases. 15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision != glu::PRECISION_LOWP) 15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(numValues >= 10); 15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 10; ndx++) 15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y()); 15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((float*)values[0], (float*)values[0] + scalarSize, v); 15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numSpecialCases += 1; 15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize); 15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasZeroSign = supportsSignedZero(precision); 15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result. 15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = deFloatFrac(in0); 15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref); 15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (int(deFloatFloor(in0-eps)) == int(deFloatFloor(in0+eps))) 15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = deFloatFrac(in0); 15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int bitsLost = numBitsLostInOp(in0, ref); 15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(de::max(0, mantissaBits-bitsLost)); // ULP diff for rounded integer value. 16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, ref); 16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff); 16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 >= 1.0f) 16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] < 1.0"; 16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16233c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCommonFunctionTests::ShaderCommonFunctionTests (Context& context) 16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCaseGroup(context, "common", "Common function tests") 16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16283c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCommonFunctionTests::~ShaderCommonFunctionTests (void) 16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<class TestClass> 16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void addFunctionCases (TestCaseGroup* parent, const char* functionName, bool floatTypes, bool intTypes, bool uintTypes) 16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName); 16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry parent->addChild(group); 16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType scalarTypes[] = 16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::TYPE_FLOAT, 16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::TYPE_INT, 16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::TYPE_UINT 16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++) 16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType scalarType = scalarTypes[scalarTypeNdx]; 16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((!floatTypes && scalarType == glu::TYPE_FLOAT) || 16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (!intTypes && scalarType == glu::TYPE_INT) || 16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (!uintTypes && scalarType == glu::TYPE_UINT)) 16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int vecSize = 1; vecSize <= 4; vecSize++) 16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++) 16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int shaderType = glu::SHADERTYPE_VERTEX; shaderType <= glu::SHADERTYPE_FRAGMENT; shaderType++) 16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry group->addChild(new TestClass(parent->getContext(), glu::DataType(scalarType + vecSize - 1), glu::Precision(prec), glu::ShaderType(shaderType))); 16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCommonFunctionTests::init (void) 16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Float? Int? Uint? 16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<AbsCase> (this, "abs", true, true, false); 16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<SignCase> (this, "sign", true, true, false); 16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FloorCase> (this, "floor", true, false, false); 16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<TruncCase> (this, "trunc", true, false, false); 16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<RoundCase> (this, "round", true, false, false); 16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<RoundEvenCase> (this, "roundeven", true, false, false); 16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<CeilCase> (this, "ceil", true, false, false); 16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FractCase> (this, "fract", true, false, false); 16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // mod 16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<ModfCase> (this, "modf", true, false, false); 16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // min 16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // max 16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // clamp 16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // mix 16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // step 16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // smoothstep 16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<IsnanCase> (this, "isnan", true, false, false); 16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<IsinfCase> (this, "isinf", true, false, false); 16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FloatBitsToIntCase> (this, "floatbitstoint", true, false, false); 16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FloatBitsToUintCase> (this, "floatbitstouint", true, false, false); 16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // (u)intBitsToFloat() 16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TestCaseGroup* intGroup = new tcu::TestCaseGroup(m_testCtx, "intbitstofloat", "intBitsToFloat() Tests"); 16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TestCaseGroup* uintGroup = new tcu::TestCaseGroup(m_testCtx, "uintbitstofloat", "uintBitsToFloat() Tests"); 16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(intGroup); 16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(uintGroup); 16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int vecSize = 1; vecSize < 4; vecSize++) 16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType uintType = vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT; 17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int shaderType = glu::SHADERTYPE_VERTEX; shaderType <= glu::SHADERTYPE_FRAGMENT; shaderType++) 17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry intGroup->addChild(new BitsToFloatCase(m_context, intType, glu::ShaderType(shaderType))); 17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uintGroup->addChild(new BitsToFloatCase(m_context, uintType, glu::ShaderType(shaderType))); 17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional 17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles3 17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp 1714