es31fShaderCommonFunctionTests.cpp revision 3c827367444ee418f129b2c238299f49d3264554
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 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 "es31fShaderCommonFunctionTests.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluContextInfo.hpp" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderExecUtil.hpp" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFormatUtil.hpp" 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp" 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp" 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h" 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h" 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector; 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string; 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog; 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace gls::ShaderExecUtil; 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2; 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec3; 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec4; 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2; 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec3; 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec4; 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Utilities 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size> 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VecArrayAccess 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VecArrayAccess (const void* ptr) : m_array((tcu::Vector<T, Size>*)ptr) {} 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~VecArrayAccess (void) {} 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Vector<T, Size>& operator[] (size_t offset) const { return m_array[offset]; } 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<T, Size>& operator[] (size_t offset) { return m_array[offset]; } 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<T, Size>* m_array; 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T> T randomScalar (de::Random& rnd, T minValue, T maxValue); 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline float randomScalar (de::Random& rnd, float minValue, float maxValue) { return rnd.getFloat(minValue, maxValue); } 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline deInt32 randomScalar (de::Random& rnd, deInt32 minValue, deInt32 maxValue) { return rnd.getInt(minValue, maxValue); } 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<> inline deUint32 randomScalar (de::Random& rnd, deUint32 minValue, deUint32 maxValue) { return minValue + rnd.getUint32() % (maxValue - minValue + 1); } 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size> 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::Vector<T, Size> randomVector (de::Random& rnd, const tcu::Vector<T, Size>& minValue, const tcu::Vector<T, Size>& maxValue) 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::Vector<T, Size> res; 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < Size; ndx++) 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry res[ndx] = randomScalar<T>(rnd, minValue[ndx], maxValue[ndx]); 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return res; 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T, int Size> 843c827367444ee418f129b2c238299f49d3264554Jarkko 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) 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VecArrayAccess<T, Size> access(dst); 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues; ndx++) 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry access[offset + ndx] = randomVector<T, Size>(rnd, minValue, maxValue); 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename T> 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0) 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry T* typedPtr = (T*)dst; 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues; ndx++) 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue); 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline int numBitsLostInOp (float input, float output) 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int inExp = tcu::Float32(input).exponent(); 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int outExp = tcu::Float32(output).exponent(); 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return de::max(0, inExp-outExp); // Lost due to mantissa shift. 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getUlpDiff (float a, float b) 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 aBits = tcu::Float32(a).bits(); 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 bBits = tcu::Float32(b).bits(); 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return aBits > bBits ? aBits - bBits : bBits - aBits; 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getUlpDiffIgnoreZeroSign (float a, float b) 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (tcu::Float32(a).isZero()) 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getUlpDiff(tcu::Float32::construct(tcu::Float32(b).sign(), 0, 0).asFloat(), b); 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (tcu::Float32(b).isZero()) 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getUlpDiff(a, tcu::Float32::construct(tcu::Float32(a).sign(), 0, 0).asFloat()); 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getUlpDiff(a, b); 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline bool supportsSignedZero (glu::Precision precision) 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note GLSL ES 3.1 doesn't really require support for -0, but we require it for highp 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // as it is very widely supported. 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return precision == glu::PRECISION_HIGHP; 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float getEpsFromMaxUlpDiff (float value, deUint32 ulpDiff) 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int exp = tcu::Float32(value).exponent(); 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::Float32::construct(+1, exp, (1u<<23) | ulpDiff).asFloat() - tcu::Float32::construct(+1, exp, 1u<<23).asFloat(); 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline deUint32 getMaxUlpDiffFromBits (int numAccurateBits) 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numGarbageBits = 23-numAccurateBits; 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mask = (1u<<numGarbageBits)-1u; 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return mask; 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float getEpsFromBits (float value, int numAccurateBits) 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return getEpsFromMaxUlpDiff(value, getMaxUlpDiffFromBits(numAccurateBits)); 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getMinMantissaBits (glu::Precision precision) 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int bits[] = 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7, // lowp 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10, // mediump 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 23 // highp 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(bits) == glu::PRECISION_LAST); 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(bits))); 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return bits[precision]; 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CommonFunctionCase 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CommonFunctionCase : public TestCase 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommonFunctionCase (Context& context, const char* name, const char* description, glu::ShaderType shaderType); 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ~CommonFunctionCase (void); 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void); 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void deinit (void); 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IterateResult iterate (void); 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommonFunctionCase (const CommonFunctionCase& other); 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommonFunctionCase& operator= (const CommonFunctionCase& other); 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry virtual void getInputValues (int numValues, void* const* values) const = 0; 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry virtual bool compare (const void* const* inputs, const void* const* outputs) = 0; 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::ShaderType m_shaderType; 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderSpec m_spec; 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int m_numValues; 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream m_failMsg; //!< Comparison failure help message. 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ShaderExecutor* m_executor; 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::CommonFunctionCase (Context& context, const char* name, const char* description, glu::ShaderType shaderType) 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCase (context, name, description) 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_shaderType (shaderType) 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_numValues (100) 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_executor (DE_NULL) 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.version = glu::GLSL_VERSION_310_ES; 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2013c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::~CommonFunctionCase (void) 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommonFunctionCase::deinit(); 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonFunctionCase::init (void) 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!m_executor); 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_executor = createExecutor(m_context.getRenderContext(), m_shaderType, m_spec); 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << m_executor; 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_executor->isOk()) 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::TestError("Compile failed"); 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommonFunctionCase::deinit (void) 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete m_executor; 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_executor = DE_NULL; 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<int> getScalarSizes (const vector<Symbol>& symbols) 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<int> sizes(symbols.size()); 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < (int)symbols.size(); ++ndx) 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry sizes[ndx] = symbols[ndx].varType.getScalarSize(); 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return sizes; 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int computeTotalScalarSize (const vector<Symbol>& symbols) 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int totalSize = 0; 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (vector<Symbol>::const_iterator sym = symbols.begin(); sym != symbols.end(); ++sym) 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry totalSize += sym->varType.getScalarSize(); 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return totalSize; 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic vector<void*> getInputOutputPointers (const vector<Symbol>& symbols, vector<deUint32>& data, const int numValues) 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<void*> pointers (symbols.size()); 2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int curScalarOffset = 0; 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int varNdx = 0; varNdx < (int)symbols.size(); ++varNdx) 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Symbol& var = symbols[varNdx]; 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = var.varType.getScalarSize(); 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Uses planar layout as input/output specs do not support strides. 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry pointers[varNdx] = &data[curScalarOffset]; 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curScalarOffset += scalarSize*numValues; 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(curScalarOffset == (int)data.size()); 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return pointers; 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \todo [2013-08-08 pyry] Make generic utility and move to glu? 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct HexFloat 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float value; 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry HexFloat (const float value_) : value(value_) {} 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const HexFloat& v) 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return str << v.value << " / " << tcu::toHex(tcu::Float32(v.value).bits()); 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct HexBool 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 value; 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry HexBool (const deUint32 value_) : value(value_) {} 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const HexBool& v) 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return str << (v.value ? "true" : "false") << " / " << tcu::toHex(v.value); 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VarValue 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::VarType& type; 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const void* value; 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VarValue (const glu::VarType& type_, const void* value_) : type(type_), value(value_) {} 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const VarValue& varValue) 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(varValue.type.isBasicType()); 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType basicType = varValue.type.getBasicType(); 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType scalarType = glu::getDataTypeScalarType(basicType); 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numComponents = glu::getDataTypeScalarSize(basicType); 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (numComponents > 1) 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry str << glu::getDataTypeName(basicType) << "("; 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < numComponents; compNdx++) 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (compNdx != 0) 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry str << ", "; 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (scalarType) 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_FLOAT: str << HexFloat(((const float*)varValue.value)[compNdx]); break; 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_INT: str << ((const deInt32*)varValue.value)[compNdx]; break; 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_UINT: str << tcu::toHex(((const deUint32*)varValue.value)[compNdx]); break; 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case glu::TYPE_BOOL: str << HexBool(((const deUint32*)varValue.value)[compNdx]); break; 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(false); 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (numComponents > 1) 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry str << ")"; 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return str; 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3253c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommonFunctionCase::IterateResult CommonFunctionCase::iterate (void) 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numInputScalars = computeTotalScalarSize(m_spec.inputs); 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numOutputScalars = computeTotalScalarSize(m_spec.outputs); 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<deUint32> inputData (numInputScalars * m_numValues); 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<deUint32> outputData (numOutputScalars * m_numValues); 3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const vector<void*> inputPointers = getInputOutputPointers(m_spec.inputs, inputData, m_numValues); 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const vector<void*> outputPointers = getInputOutputPointers(m_spec.outputs, outputData, m_numValues); 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Initialize input data. 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry getInputValues(m_numValues, &inputPointers[0]); 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Execute shader. 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_executor->useProgram(); 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_executor->execute(m_numValues, &inputPointers[0], &outputPointers[0]); 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Compare results. 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const vector<int> inScalarSizes = getScalarSizes(m_spec.inputs); 3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const vector<int> outScalarSizes = getScalarSizes(m_spec.outputs); 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<void*> curInputPtr (inputPointers.size()); 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry vector<void*> curOutputPtr (outputPointers.size()); 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numFailed = 0; 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < m_numValues; valNdx++) 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Set up pointers for comparison. 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int inNdx = 0; inNdx < (int)curInputPtr.size(); ++inNdx) 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curInputPtr[inNdx] = (deUint32*)inputPointers[inNdx] + inScalarSizes[inNdx]*valNdx; 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); ++outNdx) 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry curOutputPtr[outNdx] = (deUint32*)outputPointers[outNdx] + outScalarSizes[outNdx]*valNdx; 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!compare(&curInputPtr[0], &curOutputPtr[0])) 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \todo [2013-08-08 pyry] We probably want to log reference value as well? 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed for value " << valNdx << ":\n " << m_failMsg.str() << TestLog::EndMessage; 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << " inputs:" << TestLog::EndMessage; 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int inNdx = 0; inNdx < (int)curInputPtr.size(); inNdx++) 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << " " << m_spec.inputs[inNdx].name << " = " 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << VarValue(m_spec.inputs[inNdx].varType, curInputPtr[inNdx]) 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << " outputs:" << TestLog::EndMessage; 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int outNdx = 0; outNdx < (int)curOutputPtr.size(); outNdx++) 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << " " << m_spec.outputs[outNdx].name << " = " 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << VarValue(m_spec.outputs[outNdx].varType, curOutputPtr[outNdx]) 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << TestLog::EndMessage; 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg.str(""); 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg.clear(); 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numFailed += 1; 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.getLog() << TestLog::Message << (m_numValues - numFailed) << " / " << m_numValues << " values passed" << TestLog::EndMessage; 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numFailed == 0 ? "Pass" : "Result comparison failed"); 3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return STOP; 3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getPrecisionPostfix (glu::Precision precision) 3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const char* s_postfix[] = 3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_lowp", 3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_mediump", 3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_highp" 3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_postfix) == glu::PRECISION_LAST); 4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inBounds<int>(precision, 0, DE_LENGTH_OF_ARRAY(s_postfix))); 4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return s_postfix[precision]; 4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getShaderTypePostfix (glu::ShaderType shaderType) 4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static const char* s_postfix[] = 4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_vertex", 4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_fragment", 4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_geometry", 4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_tess_control", 4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_tess_eval", 4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "_compute" 4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_postfix))); 4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return s_postfix[shaderType]; 4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string getCommonFuncCaseName (glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return string(glu::getDataTypeName(baseType)) + getPrecisionPostfix(precision) + getShaderTypePostfix(shaderType); 4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AbsCase : public CommonFunctionCase 4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry AbsCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "abs", shaderType) 4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = abs(in0);"; 4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 floatRanges[] = 4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 intRanges[] = 4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(-(1<<7)+1, (1<<7)-1), 4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(-(1<<15)+1, (1<<15)-1), 4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(0x80000001, 0x7fffffff) 4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0x235facu); 4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(type)) 4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), values[0], numValues*scalarSize); 4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), values[0], numValues*scalarSize); 4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(type)) 4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = (1u<<(23-mantissaBits))-1u; 4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref0 = de::abs(in0); 4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff0 = getUlpDiff(out0, ref0); 4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff0 > maxUlpDiff) 4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0; 4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int in0 = ((const int*)inputs[0])[compNdx]; 4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int out0 = ((const int*)outputs[0])[compNdx]; 4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ref0 = de::abs(in0); 4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != ref0) 4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << ref0; 4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SignCase : public CommonFunctionCase 5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SignCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "sign", shaderType) 5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = sign(in0);"; 5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 floatRanges[] = 5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e4f, 1e4f), // mediump - note: may end up as inf 5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e8f, 1e8f) // highp - note: may end up as inf 5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const IVec2 intRanges[] = 5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(-(1<<7), (1<<7)-1), 5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(-(1<<15), (1<<15)-1), 5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IVec2(0x80000000, 0x7fffffff) 5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0x324u); 5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(type)) 5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases. 5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((float*)values[0], (float*)values[0] + scalarSize, +1.0f); 5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((float*)values[0], (float*)values[0] + scalarSize, -1.0f); 5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((float*)values[0], (float*)values[0] + scalarSize, 0.0f); 5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, floatRanges[precision].x(), floatRanges[precision].y(), (float*)values[0] + scalarSize*3, (numValues-3)*scalarSize); 5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((int*)values[0], (int*)values[0] + scalarSize, +1); 5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((int*)values[0], (int*)values[0] + scalarSize, -1); 5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((int*)values[0], (int*)values[0] + scalarSize, 0); 5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, intRanges[precision].x(), intRanges[precision].y(), (int*)values[0] + scalarSize*3, (numValues-3)*scalarSize); 5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (glu::isDataTypeFloatOrVec(type)) 5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Both highp and mediump should be able to represent -1, 0, and +1 exactly 5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = precision == glu::PRECISION_LOWP ? getMaxUlpDiffFromBits(getMinMantissaBits(precision)) : 0; 5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref0 = in0 < 0.0f ? -1.0f : 5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry in0 > 0.0f ? +1.0f : 0.0f; 5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff0 = getUlpDiff(out0, ref0); 5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff0 > maxUlpDiff) 5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " with ULP threshold " << maxUlpDiff << ", got ULP diff " << ulpDiff0; 5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int in0 = ((const int*)inputs[0])[compNdx]; 5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int out0 = ((const int*)outputs[0])[compNdx]; 5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ref0 = in0 < 0 ? -1 : 5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry in0 > 0 ? +1 : 0; 5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != ref0) 5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << ref0; 5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float roundEven (float v) 6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float q = deFloatFrac(v); 6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int truncated = int(v-q); 6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int rounded = (q > 0.5f) ? (truncated + 1) : // Rounded up 6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (q == 0.5f && (truncated % 2 != 0)) ? (truncated + 1) : // Round to nearest even at 0.5 6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry truncated; // Rounded down 6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return float(rounded); 6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RoundEvenCase : public CommonFunctionCase 6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry RoundEvenCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "roundEven", shaderType) 6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = roundEven(in0);"; 6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numSpecialCases = 0; 6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases. 6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision != glu::PRECISION_LOWP) 6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(numValues >= 20); 6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 20; ndx++) 6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float v = de::clamp(float(ndx) - 10.5f, ranges[precision].x(), ranges[precision].y()); 6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((float*)values[0], (float*)values[0] + scalarSize, v); 6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numSpecialCases += 1; 6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize); 6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasSignedZero = supportsSignedZero(precision); 6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact rounding result. 6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = roundEven(in0); 6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref); 6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(roundEven(in0-eps)); 6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(roundEven(in0+eps)); 6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal)); 7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ModfCase : public CommonFunctionCase 7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ModfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "modf", shaderType) 7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out1", glu::VarType(baseType, precision))); 7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = modf(in0, out1);"; 7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize); 7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasZeroSign = supportsSignedZero(precision); 7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out1 = ((const float*)outputs[1])[compNdx]; 7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float refOut1 = float(int(in0)); 7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float refOut0 = in0 - refOut1; 7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int bitsLost = precision != glu::PRECISION_HIGHP ? numBitsLostInOp(in0, refOut0) : 0; 7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(de::max(mantissaBits - bitsLost, 0)); 7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float resSum = out0 + out1; 7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasZeroSign ? getUlpDiff(resSum, in0) : getUlpDiffIgnoreZeroSign(resSum, in0); 7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = (" << HexFloat(refOut0) << ") + (" << HexFloat(refOut1) << ") = " << HexFloat(in0) << " with ULP threshold " 7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff); 7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsnanCase : public CommonFunctionCase 7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IsnanCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isnan", shaderType) 7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(glu::isDataTypeFloatOrVec(baseType)); 7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType boolType = vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL; 7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST))); 8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = isnan(in0);"; 8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xc2a39fu); 8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mantissaMask = ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u); 8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++) 8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isNan = rnd.getFloat() > 0.3f; 8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isInf = !isNan && rnd.getFloat() > 0.4f; 8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mantissa = !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0; 8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 exp = !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu; 8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 sign = rnd.getUint32() & 0x1u; 8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 value = (sign << 31) | (exp << 23) | mantissa; 8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan); 8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((deUint32*)values[0])[valNdx] = value; 8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP) 8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Only highp is required to support inf/nan 8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 out0 = ((const deUint32*)outputs[0])[compNdx]; 8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ref = tcu::Float32(in0).isNaN() ? 1u : 0u; 8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != ref) 8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref); 8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Value can be either 0 or 1 8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int out0 = ((const int*)outputs[0])[compNdx]; 8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != 0 && out0 != 1) 8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = 0 / 1"; 8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IsinfCase : public CommonFunctionCase 8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry IsinfCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "isinf", shaderType) 8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(glu::isDataTypeFloatOrVec(baseType)); 8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType boolType = vecSize > 1 ? glu::getDataTypeBoolVec(vecSize) : glu::TYPE_BOOL; 8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(boolType, glu::PRECISION_LAST))); 8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = isinf(in0);"; 8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xc2a39fu); 8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mantissaMask = ~getMaxUlpDiffFromBits(mantissaBits) & ((1u<<23)-1u); 8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int valNdx = 0; valNdx < numValues*scalarSize; valNdx++) 8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isInf = rnd.getFloat() > 0.3f; 8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isNan = !isInf && rnd.getFloat() > 0.4f; 8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mantissa = !isInf ? ((1u<<22) | (rnd.getUint32() & mantissaMask)) : 0; 9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 exp = !isNan && !isInf ? (rnd.getUint32() & 0x7fu) : 0xffu; 9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 sign = rnd.getUint32() & 0x1u; 9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 value = (sign << 31) | (exp << 23) | mantissa; 9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(tcu::Float32(value).isInf() == isInf && tcu::Float32(value).isNaN() == isNan); 9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((deUint32*)values[0])[valNdx] = value; 9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP) 9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Only highp is required to support inf/nan 9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 out0 = ((const deUint32*)outputs[0])[compNdx]; 9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ref = tcu::Float32(in0).isInf() ? 1u : 0u; 9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != ref) 9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexBool(ref); 9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Value can be either 0 or 1 9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int out0 = ((const int*)outputs[0])[compNdx]; 9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 != 0 && out0 != 1) 9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = 0 / 1"; 9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToUintIntCase : public CommonFunctionCase 9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FloatBitsToUintIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType, bool outIsSigned) 9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), outIsSigned ? "floatBitsToInt" : "floatBitsToUint", shaderType) 9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intType = outIsSigned ? (vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT) 9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : (vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT); 9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(intType, glu::PRECISION_HIGHP))); 9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = outIsSigned ? "out0 = floatBitsToInt(in0);" : "out0 = floatBitsToUint(in0);"; 9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0x2790au); 9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), values[0], numValues*scalarSize); 9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); 9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 out0 = ((const deUint32*)outputs[0])[compNdx]; 9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 refOut0 = tcu::Float32(in0).bits(); 9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ulpDiff = de::abs((int)out0 - (int)refOut0); 9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(refOut0) << " with threshold " 10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff); 10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToIntCase : public FloatBitsToUintIntCase 10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FloatBitsToIntCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : FloatBitsToUintIntCase(context, baseType, precision, shaderType, true) 10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloatBitsToUintCase : public FloatBitsToUintIntCase 10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FloatBitsToUintCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : FloatBitsToUintIntCase(context, baseType, precision, shaderType, false) 10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass BitsToFloatCase : public CommonFunctionCase 10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BitsToFloatCase (Context& context, glu::DataType baseType, glu::ShaderType shaderType) 10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, glu::PRECISION_HIGHP, shaderType).c_str(), glu::isDataTypeIntOrIVec(baseType) ? "intBitsToFloat" : "uintBitsToFloat", shaderType) 10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool inIsSigned = glu::isDataTypeIntOrIVec(baseType); 10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType floatType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT; 10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, glu::PRECISION_HIGHP))); 10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(floatType, glu::PRECISION_HIGHP))); 10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = inIsSigned ? "out0 = intBitsToFloat(in0);" : "out0 = uintBitsToFloat(in0);"; 10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xbbb225u); 10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 range (-1e8f, +1e8f); 10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Filled as floats. 10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, range.x(), range.y(), values[0], numValues*scalarSize); 10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxUlpDiff = 0; 10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ulpDiff = de::abs((int)in0 - (int)out0); 10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << tcu::toHex(in0) << " with ULP threshold " 10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff); 10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FloorCase : public CommonFunctionCase 10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FloorCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "floor", shaderType) 10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = floor(in0);"; 10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize); 11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result. 11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = deFloatFloor(in0); 11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiff(out0, ref); 11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(deFloatFloor(in0-eps)); 11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(deFloatFloor(in0+eps)); 11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiff(out0, float(roundedVal)); 11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TruncCase : public CommonFunctionCase 11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TruncCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "trunc", shaderType) 11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = trunc(in0);"; 11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float specialCases[] = { 0.0f, -0.0f, -0.9f, 0.9f, 1.0f, -1.0f }; 12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSpecialCases = DE_LENGTH_OF_ARRAY(specialCases); 12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases 12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++) 12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) 12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[caseNdx*scalarSize + scalarNdx] = specialCases[caseNdx]; 12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + scalarSize*numSpecialCases, (numValues-numSpecialCases)*scalarSize); 12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasSignedZero = supportsSignedZero(precision); 12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result. 12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isNeg = tcu::Float32(in0).sign() < 0; 12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = isNeg ? (-float(int(-in0))) : float(int(in0)); 12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasSignedZero ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref); 12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(in0-eps); 12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(in0+eps); 12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal)); 12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass RoundCase : public CommonFunctionCase 12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry RoundCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "round", shaderType) 12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = round(in0);"; 12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numSpecialCases = 0; 13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases. 13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision != glu::PRECISION_LOWP) 13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(numValues >= 10); 13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 10; ndx++) 13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y()); 13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((float*)values[0], (float*)values[0] + scalarSize, v); 13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numSpecialCases += 1; 13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize); 13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasZeroSign = supportsSignedZero(precision); 13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (deFloatFrac(in0) == 0.5f) 13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Allow both ceil(in) and floor(in) 13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref0 = deFloatFloor(in0); 13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref1 = deFloatCeil(in0); 13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff0 = hasZeroSign ? getUlpDiff(out0, ref0) : getUlpDiffIgnoreZeroSign(out0, ref0); 13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff1 = hasZeroSign ? getUlpDiff(out0, ref1) : getUlpDiffIgnoreZeroSign(out0, ref1); 13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff0 > 0 && ulpDiff1 > 0) 13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref0) << " or " << HexFloat(ref1) << ", got ULP diff " << tcu::toHex(de::min(ulpDiff0, ulpDiff1)); 13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result 13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = roundEven(in0); 13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref); 13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(roundEven(in0-eps)); 13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(roundEven(in0+eps)); 13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal)); 13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CeilCase : public CommonFunctionCase 14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CeilCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ceil", shaderType) 14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = ceil(in0);"; 14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0], numValues*scalarSize); 14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasZeroSign = supportsSignedZero(precision); 14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result. 14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = deFloatCeil(in0); 14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref); 14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value. 14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int minRes = int(deFloatCeil(in0-eps)); 14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int maxRes = int(deFloatCeil(in0+eps)); 14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool anyOk = false; 14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int roundedVal = minRes; roundedVal <= maxRes; roundedVal++) 14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, float(roundedVal)); 14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff <= maxUlpDiff) 14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = true; 14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk && de::inRange(0, minRes, maxRes)) 14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Allow -0 as well. 15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int ulpDiff = de::abs((int)tcu::Float32(out0).bits() - (int)0x80000000u); 15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry anyOk = ((deUint32)ulpDiff <= maxUlpDiff); 15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!anyOk) 15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = [" << minRes << ", " << maxRes << "] with ULP threshold " << tcu::toHex(maxUlpDiff); 15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FractCase : public CommonFunctionCase 15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FractCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fract", shaderType) 15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, precision))); 15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = fract(in0);"; 15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int numSpecialCases = 0; 15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases. 15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision != glu::PRECISION_LOWP) 15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(numValues >= 10); 15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < 10; ndx++) 15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float v = de::clamp(float(ndx) - 5.5f, ranges[precision].x(), ranges[precision].y()); 15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::fill((float*)values[0], (float*)values[0] + scalarSize, v); 15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numSpecialCases += 1; 15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + numSpecialCases*scalarSize, (numValues-numSpecialCases)*scalarSize); 15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If precision is mediump, make sure values can be represented in fp16 exactly 15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_MEDIUMP) 15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int ndx = 0; ndx < numValues*scalarSize; ndx++) 15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[ndx] = tcu::Float16(((float*)values[0])[ndx]).asFloat(); 15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool hasZeroSign = supportsSignedZero(precision); 15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (precision == glu::PRECISION_HIGHP || precision == glu::PRECISION_MEDIUMP) 15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Require exact result. 15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = deFloatFrac(in0); 15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = hasZeroSign ? getUlpDiff(out0, ref) : getUlpDiffIgnoreZeroSign(out0, ref); 15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > 0) 15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << ", got ULP diff " << tcu::toHex(ulpDiff); 15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float eps = getEpsFromBits(1.0f, mantissaBits); // epsilon for rounding bounds 15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (int(deFloatFloor(in0-eps)) == int(deFloatFloor(in0+eps))) 16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = deFloatFrac(in0); 16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int bitsLost = numBitsLostInOp(in0, ref); 16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(de::max(0, mantissaBits-bitsLost)); // ULP diff for rounded integer value. 16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = getUlpDiffIgnoreZeroSign(out0, ref); 16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold " << tcu::toHex(maxUlpDiff) << ", got diff " << tcu::toHex(ulpDiff); 16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (out0 >= 1.0f) 16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] < 1.0"; 16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void frexp (float in, float* significand, int* exponent) 16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Float32 fpValue(in); 16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!fpValue.isZero()) 16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Construct float that has exactly the mantissa, and exponent of -1. 16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *significand = tcu::Float32::construct(fpValue.sign(), -1, fpValue.mantissa()).asFloat(); 16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *exponent = fpValue.exponent()+1; 16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *significand = fpValue.sign() < 0 ? -0.0f : 0.0f; 16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *exponent = 0; 16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float ldexp (float significand, int exponent) 16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const tcu::Float32 mant(significand); 16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (exponent == 0 && mant.isZero()) 16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return mant.sign() < 0 ? -0.0f : 0.0f; 16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return tcu::Float32::construct(mant.sign(), exponent+mant.exponent(), mant.mantissa()).asFloat(); 16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FrexpCase : public CommonFunctionCase 16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FrexpCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "frexp", shaderType) 16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, glu::PRECISION_HIGHP))); 16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out1", glu::VarType(intType, glu::PRECISION_HIGHP))); 16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = frexp(in0, out1);"; 16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0x2790au); 16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases 16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[scalarSize*0 + compNdx] = 0.0f; 16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[scalarSize*1 + compNdx] = -0.0f; 16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[scalarSize*2 + compNdx] = 0.5f; 16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[scalarSize*3 + compNdx] = -0.5f; 16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[scalarSize*4 + compNdx] = 1.0f; 16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[scalarSize*5 + compNdx] = -1.0f; 16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[scalarSize*6 + compNdx] = 2.0f; 16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[scalarSize*7 + compNdx] = -2.0f; 16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[0] + 8*scalarSize, (numValues-8)*scalarSize); 17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool signedZero = supportsSignedZero(precision); 17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); 17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int out1 = ((const int*)outputs[1])[compNdx]; 17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float refOut0; 17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int refOut1; 17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry frexp(in0, &refOut0, &refOut1); 17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff0 = signedZero ? getUlpDiff(out0, refOut0) : getUlpDiffIgnoreZeroSign(out0, refOut0); 17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff0 > maxUlpDiff || out1 != refOut1) 17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(refOut0) << ", " << refOut1 << " with ULP threshold " 17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff0); 17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LdexpCase : public CommonFunctionCase 17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LdexpCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "ldexp", shaderType) 17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int vecSize = glu::getDataTypeScalarSize(baseType); 17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in0", glu::VarType(baseType, precision))); 17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("in1", glu::VarType(intType, glu::PRECISION_HIGHP))); 17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("out0", glu::VarType(baseType, glu::PRECISION_HIGHP))); 17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "out0 = ldexp(in0, in1);"; 17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0x2790au); 17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int valueNdx = 0; 17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float easySpecialCases[] = { 0.0f, -0.0f, 0.5f, -0.5f, 1.0f, -1.0f, 2.0f, -2.0f }; 17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(valueNdx + DE_LENGTH_OF_ARRAY(easySpecialCases) <= numValues); 17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(easySpecialCases); caseNdx++) 17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float in0; 17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int in1; 17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry frexp(easySpecialCases[caseNdx], &in0, &in1); 17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[valueNdx*scalarSize + compNdx] = in0; 17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((int*)values[1])[valueNdx*scalarSize + compNdx] = in1; 17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry valueNdx += 1; 17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note lowp and mediump can not necessarily fit the values in hard cases, so we'll use only easy ones. 17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numEasyRandomCases = precision == glu::PRECISION_HIGHP ? 50 : (numValues-valueNdx); 17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(valueNdx + numEasyRandomCases <= numValues); 17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int caseNdx = 0; caseNdx < numEasyRandomCases; caseNdx++) 17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in = rnd.getFloat(ranges[precision].x(), ranges[precision].y()); 18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float in0; 18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int in1; 18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry frexp(in, &in0, &in1); 18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[valueNdx*scalarSize + compNdx] = in0; 18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((int*)values[1])[valueNdx*scalarSize + compNdx] = in1; 18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry valueNdx += 1; 18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numHardRandomCases = numValues-valueNdx; 18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(numHardRandomCases >= 0 && valueNdx + numHardRandomCases <= numValues); 18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int caseNdx = 0; caseNdx < numHardRandomCases; caseNdx++) 18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int fpExp = rnd.getInt(-126, 127); 18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int sign = rnd.getBool() ? -1 : +1; 18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 mantissa = (1u<<23) | (rnd.getUint32() & ((1u<<23)-1)); 18243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int in1 = rnd.getInt(de::max(-126, -126-fpExp), de::min(127, 127-fpExp)); 18253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = tcu::Float32::construct(sign, fpExp, mantissa).asFloat(); 18263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inRange(in1, -126, 127)); // See Khronos bug 11180 18283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inRange(in1+fpExp, -126, 127)); 18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out = ldexp(in0, in1); 18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!tcu::Float32(out).isInf() && !tcu::Float32(out).isDenorm()); 18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(out); 18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[0])[valueNdx*scalarSize + compNdx] = in0; 18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((int*)values[1])[valueNdx*scalarSize + compNdx] = in1; 18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry valueNdx += 1; 18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 18453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 18473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool signedZero = supportsSignedZero(precision); 18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(mantissaBits); 18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float in0 = ((const float*)inputs[0])[compNdx]; 18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int in1 = ((const int*)inputs[1])[compNdx]; 18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float out0 = ((const float*)outputs[0])[compNdx]; 18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float refOut0 = ldexp(in0, in1); 18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = signedZero ? getUlpDiff(out0, refOut0) : getUlpDiffIgnoreZeroSign(out0, refOut0); 18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int inExp = tcu::Float32(in0).exponent(); 18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(refOut0) << ", (exp = " << inExp << ") with ULP threshold " 18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff); 18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FmaCase : public CommonFunctionCase 18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FmaCase (Context& context, glu::DataType baseType, glu::Precision precision, glu::ShaderType shaderType) 18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : CommonFunctionCase(context, getCommonFuncCaseName(baseType, precision, shaderType).c_str(), "fma", shaderType) 18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("a", glu::VarType(baseType, precision))); 18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("b", glu::VarType(baseType, precision))); 18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.inputs.push_back(Symbol("c", glu::VarType(baseType, precision))); 18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.outputs.push_back(Symbol("res", glu::VarType(baseType, precision))); 18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.source = "res = fma(a, b, c);"; 18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_spec.globalDeclarations = "#extension GL_EXT_gpu_shader5 : require\n"; 18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void init (void) 18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_gpu_shader5")) 18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw tcu::NotSupportedError("GL_EXT_gpu_shader5 not supported"); 18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommonFunctionCase::init(); 18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void getInputValues (int numValues, void* const* values) const 18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Vec2 ranges[] = 19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-2.0f, 2.0f), // lowp 19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e3f, 1e3f), // mediump 19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Vec2(-1e7f, 1e7f) // highp 19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Random rnd (deStringHash(getName()) ^ 0xac23fu); 19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float specialCases[][3] = 19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // a b c 19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 0.0f, 0.0f, 0.0f }, 19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 0.0f, 1.0f, 0.0f }, 19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 0.0f, 0.0f, -1.0f }, 19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1.0f, 1.0f, 0.0f }, 19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1.0f, 1.0f, 1.0f }, 19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { -1.0f, 1.0f, 0.0f }, 19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1.0f, -1.0f, 0.0f }, 19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { -1.0f, -1.0f, 0.0f }, 19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { -0.0f, 1.0f, 0.0f }, 19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1.0f, -0.0f, 0.0f } 19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numSpecialCases = DE_LENGTH_OF_ARRAY(specialCases); 19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Special cases 19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int caseNdx = 0; caseNdx < numSpecialCases; caseNdx++) 19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int inputNdx = 0; inputNdx < 3; inputNdx++) 19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) 19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((float*)values[inputNdx])[caseNdx*scalarSize + scalarNdx] = specialCases[caseNdx][inputNdx]; 19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Random cases. 19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numScalars = (numValues-numSpecialCases)*scalarSize; 19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int offs = scalarSize*numSpecialCases; 19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int inputNdx = 0; inputNdx < 3; inputNdx++) 19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fillRandomScalars(rnd, ranges[precision].x(), ranges[precision].y(), (float*)values[inputNdx] + offs, numScalars); 19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool compare (const void* const* inputs, const void* const* outputs) 19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); 19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); 19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int scalarSize = glu::getDataTypeScalarSize(type); 19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool signedZero = supportsSignedZero(precision); 19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int mantissaBits = getMinMantissaBits(precision); 19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int compNdx = 0; compNdx < scalarSize; compNdx++) 19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float a = ((const float*)inputs[0])[compNdx]; 19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float b = ((const float*)inputs[1])[compNdx]; 19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float c = ((const float*)inputs[2])[compNdx]; 19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float res = ((const float*)outputs[0])[compNdx]; 19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const float ref = a*b + c; 19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numBitsLost = precision != glu::PRECISION_HIGHP 19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ? de::max(de::max(numBitsLostInOp(a, res), numBitsLostInOp(b, res)), numBitsLostInOp(c, res))+1 19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : 1; 19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(de::max(0, mantissaBits-numBitsLost)); 19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 ulpDiff = signedZero ? getUlpDiff(res, ref) : getUlpDiffIgnoreZeroSign(res, ref); 19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (ulpDiff > maxUlpDiff) 19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold " 19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff); 19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19833c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCommonFunctionTests::ShaderCommonFunctionTests (Context& context) 19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : TestCaseGroup(context, "common", "Common function tests") 19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19883c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderCommonFunctionTests::~ShaderCommonFunctionTests (void) 19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<class TestClass> 19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void addFunctionCases (TestCaseGroup* parent, const char* functionName, bool floatTypes, bool intTypes, bool uintTypes, deUint32 shaderBits) 19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), functionName, functionName); 19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry parent->addChild(group); 19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType scalarTypes[] = 19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::TYPE_FLOAT, 20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::TYPE_INT, 20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry glu::TYPE_UINT 20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int scalarTypeNdx = 0; scalarTypeNdx < DE_LENGTH_OF_ARRAY(scalarTypes); scalarTypeNdx++) 20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType scalarType = scalarTypes[scalarTypeNdx]; 20083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((!floatTypes && scalarType == glu::TYPE_FLOAT) || 20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (!intTypes && scalarType == glu::TYPE_INT) || 20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (!uintTypes && scalarType == glu::TYPE_UINT)) 20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int vecSize = 1; vecSize <= 4; vecSize++) 20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int prec = glu::PRECISION_LOWP; prec <= glu::PRECISION_HIGHP; prec++) 20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; shaderTypeNdx++) 20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (shaderBits & (1<<shaderTypeNdx)) 20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry group->addChild(new TestClass(parent->getContext(), glu::DataType(scalarType + vecSize - 1), glu::Precision(prec), glu::ShaderType(shaderTypeNdx))); 20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderCommonFunctionTests::init (void) 20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 20303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum 20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VS = (1<<glu::SHADERTYPE_VERTEX), 20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TC = (1<<glu::SHADERTYPE_TESSELLATION_CONTROL), 20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TE = (1<<glu::SHADERTYPE_TESSELLATION_EVALUATION), 20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry GS = (1<<glu::SHADERTYPE_GEOMETRY), 20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FS = (1<<glu::SHADERTYPE_FRAGMENT), 20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CS = (1<<glu::SHADERTYPE_COMPUTE), 20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ALL_SHADERS = VS|TC|TE|GS|FS|CS, 20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry NEW_SHADERS = TC|TE|GS|CS, 20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Float? Int? Uint? Shaders 20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<AbsCase> (this, "abs", true, true, false, NEW_SHADERS); 20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<SignCase> (this, "sign", true, true, false, NEW_SHADERS); 20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FloorCase> (this, "floor", true, false, false, NEW_SHADERS); 20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<TruncCase> (this, "trunc", true, false, false, NEW_SHADERS); 20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<RoundCase> (this, "round", true, false, false, NEW_SHADERS); 20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<RoundEvenCase> (this, "roundeven", true, false, false, NEW_SHADERS); 20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<CeilCase> (this, "ceil", true, false, false, NEW_SHADERS); 20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FractCase> (this, "fract", true, false, false, NEW_SHADERS); 20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // mod 20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<ModfCase> (this, "modf", true, false, false, NEW_SHADERS); 20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // min 20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // max 20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // clamp 20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // mix 20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // step 20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // smoothstep 20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<IsnanCase> (this, "isnan", true, false, false, NEW_SHADERS); 20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<IsinfCase> (this, "isinf", true, false, false, NEW_SHADERS); 20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FloatBitsToIntCase> (this, "floatbitstoint", true, false, false, NEW_SHADERS); 20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FloatBitsToUintCase> (this, "floatbitstouint", true, false, false, NEW_SHADERS); 20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FrexpCase> (this, "frexp", true, false, false, ALL_SHADERS); 20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<LdexpCase> (this, "ldexp", true, false, false, ALL_SHADERS); 20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addFunctionCases<FmaCase> (this, "fma", true, false, false, ALL_SHADERS); 20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // (u)intBitsToFloat() 20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32 shaderBits = NEW_SHADERS; 20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TestCaseGroup* intGroup = new tcu::TestCaseGroup(m_testCtx, "intbitstofloat", "intBitsToFloat() Tests"); 20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tcu::TestCaseGroup* uintGroup = new tcu::TestCaseGroup(m_testCtx, "uintbitstofloat", "uintBitsToFloat() Tests"); 20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(intGroup); 20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addChild(uintGroup); 20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int vecSize = 1; vecSize < 4; vecSize++) 20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType intType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const glu::DataType uintType = vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT; 20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++) 20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (shaderBits & (1<<shaderType)) 20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry intGroup->addChild(new BitsToFloatCase(m_context, intType, glu::ShaderType(shaderType))); 20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry uintGroup->addChild(new BitsToFloatCase(m_context, uintType, glu::ShaderType(shaderType))); 20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional 20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31 20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp 2098