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