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