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 Shader derivate function tests. 22e5c31af7Sopenharmony_ci * 23e5c31af7Sopenharmony_ci * \todo [2013-06-25 pyry] Missing features: 24e5c31af7Sopenharmony_ci * - lines and points 25e5c31af7Sopenharmony_ci * - projected coordinates 26e5c31af7Sopenharmony_ci * - continous non-trivial functions (sin, exp) 27e5c31af7Sopenharmony_ci * - non-continous functions (step) 28e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 29e5c31af7Sopenharmony_ci 30e5c31af7Sopenharmony_ci#include "es3fShaderDerivateTests.hpp" 31e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp" 32e5c31af7Sopenharmony_ci#include "gluRenderContext.hpp" 33e5c31af7Sopenharmony_ci#include "gluDrawUtil.hpp" 34e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp" 35e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp" 36e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp" 37e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp" 38e5c31af7Sopenharmony_ci#include "gluTexture.hpp" 39e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp" 40e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp" 41e5c31af7Sopenharmony_ci#include "tcuSurface.hpp" 42e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 43e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp" 44e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp" 45e5c31af7Sopenharmony_ci#include "tcuRGBA.hpp" 46e5c31af7Sopenharmony_ci#include "tcuFloat.hpp" 47e5c31af7Sopenharmony_ci#include "tcuInterval.hpp" 48e5c31af7Sopenharmony_ci#include "deRandom.hpp" 49e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp" 50e5c31af7Sopenharmony_ci#include "deString.h" 51e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 52e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 53e5c31af7Sopenharmony_ci#include "glsShaderRenderCase.hpp" // gls::setupDefaultUniforms() 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_ci#include <sstream> 56e5c31af7Sopenharmony_ci 57e5c31af7Sopenharmony_cinamespace deqp 58e5c31af7Sopenharmony_ci{ 59e5c31af7Sopenharmony_cinamespace gles3 60e5c31af7Sopenharmony_ci{ 61e5c31af7Sopenharmony_cinamespace Functional 62e5c31af7Sopenharmony_ci{ 63e5c31af7Sopenharmony_ci 64e5c31af7Sopenharmony_ciusing std::vector; 65e5c31af7Sopenharmony_ciusing std::string; 66e5c31af7Sopenharmony_ciusing std::map; 67e5c31af7Sopenharmony_ciusing tcu::TestLog; 68e5c31af7Sopenharmony_ciusing std::ostringstream; 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_cienum 71e5c31af7Sopenharmony_ci{ 72e5c31af7Sopenharmony_ci VIEWPORT_WIDTH = 167, 73e5c31af7Sopenharmony_ci VIEWPORT_HEIGHT = 103, 74e5c31af7Sopenharmony_ci FBO_WIDTH = 99, 75e5c31af7Sopenharmony_ci FBO_HEIGHT = 133, 76e5c31af7Sopenharmony_ci MAX_FAILED_MESSAGES = 10 77e5c31af7Sopenharmony_ci}; 78e5c31af7Sopenharmony_ci 79e5c31af7Sopenharmony_cienum DerivateFunc 80e5c31af7Sopenharmony_ci{ 81e5c31af7Sopenharmony_ci DERIVATE_DFDX = 0, 82e5c31af7Sopenharmony_ci DERIVATE_DFDY, 83e5c31af7Sopenharmony_ci DERIVATE_FWIDTH, 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_ci DERIVATE_LAST 86e5c31af7Sopenharmony_ci}; 87e5c31af7Sopenharmony_ci 88e5c31af7Sopenharmony_cienum SurfaceType 89e5c31af7Sopenharmony_ci{ 90e5c31af7Sopenharmony_ci SURFACETYPE_DEFAULT_FRAMEBUFFER = 0, 91e5c31af7Sopenharmony_ci SURFACETYPE_UNORM_FBO, 92e5c31af7Sopenharmony_ci SURFACETYPE_FLOAT_FBO, // \note Uses RGBA32UI fbo actually, since FP rendertargets are not in core spec. 93e5c31af7Sopenharmony_ci 94e5c31af7Sopenharmony_ci SURFACETYPE_LAST 95e5c31af7Sopenharmony_ci}; 96e5c31af7Sopenharmony_ci 97e5c31af7Sopenharmony_ci// Utilities 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_cinamespace 100e5c31af7Sopenharmony_ci{ 101e5c31af7Sopenharmony_ci 102e5c31af7Sopenharmony_ciclass AutoFbo 103e5c31af7Sopenharmony_ci{ 104e5c31af7Sopenharmony_cipublic: 105e5c31af7Sopenharmony_ci AutoFbo (const glw::Functions& gl) 106e5c31af7Sopenharmony_ci : m_gl (gl) 107e5c31af7Sopenharmony_ci , m_fbo (0) 108e5c31af7Sopenharmony_ci { 109e5c31af7Sopenharmony_ci } 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci ~AutoFbo (void) 112e5c31af7Sopenharmony_ci { 113e5c31af7Sopenharmony_ci if (m_fbo) 114e5c31af7Sopenharmony_ci m_gl.deleteFramebuffers(1, &m_fbo); 115e5c31af7Sopenharmony_ci } 116e5c31af7Sopenharmony_ci 117e5c31af7Sopenharmony_ci void gen (void) 118e5c31af7Sopenharmony_ci { 119e5c31af7Sopenharmony_ci DE_ASSERT(!m_fbo); 120e5c31af7Sopenharmony_ci m_gl.genFramebuffers(1, &m_fbo); 121e5c31af7Sopenharmony_ci } 122e5c31af7Sopenharmony_ci 123e5c31af7Sopenharmony_ci deUint32 operator* (void) const { return m_fbo; } 124e5c31af7Sopenharmony_ci 125e5c31af7Sopenharmony_ciprivate: 126e5c31af7Sopenharmony_ci const glw::Functions& m_gl; 127e5c31af7Sopenharmony_ci deUint32 m_fbo; 128e5c31af7Sopenharmony_ci}; 129e5c31af7Sopenharmony_ci 130e5c31af7Sopenharmony_ciclass AutoRbo 131e5c31af7Sopenharmony_ci{ 132e5c31af7Sopenharmony_cipublic: 133e5c31af7Sopenharmony_ci AutoRbo (const glw::Functions& gl) 134e5c31af7Sopenharmony_ci : m_gl (gl) 135e5c31af7Sopenharmony_ci , m_rbo (0) 136e5c31af7Sopenharmony_ci { 137e5c31af7Sopenharmony_ci } 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci ~AutoRbo (void) 140e5c31af7Sopenharmony_ci { 141e5c31af7Sopenharmony_ci if (m_rbo) 142e5c31af7Sopenharmony_ci m_gl.deleteRenderbuffers(1, &m_rbo); 143e5c31af7Sopenharmony_ci } 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci void gen (void) 146e5c31af7Sopenharmony_ci { 147e5c31af7Sopenharmony_ci DE_ASSERT(!m_rbo); 148e5c31af7Sopenharmony_ci m_gl.genRenderbuffers(1, &m_rbo); 149e5c31af7Sopenharmony_ci } 150e5c31af7Sopenharmony_ci 151e5c31af7Sopenharmony_ci deUint32 operator* (void) const { return m_rbo; } 152e5c31af7Sopenharmony_ci 153e5c31af7Sopenharmony_ciprivate: 154e5c31af7Sopenharmony_ci const glw::Functions& m_gl; 155e5c31af7Sopenharmony_ci deUint32 m_rbo; 156e5c31af7Sopenharmony_ci}; 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ci} // anonymous 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_cistatic const char* getDerivateFuncName (DerivateFunc func) 161e5c31af7Sopenharmony_ci{ 162e5c31af7Sopenharmony_ci switch (func) 163e5c31af7Sopenharmony_ci { 164e5c31af7Sopenharmony_ci case DERIVATE_DFDX: return "dFdx"; 165e5c31af7Sopenharmony_ci case DERIVATE_DFDY: return "dFdy"; 166e5c31af7Sopenharmony_ci case DERIVATE_FWIDTH: return "fwidth"; 167e5c31af7Sopenharmony_ci default: 168e5c31af7Sopenharmony_ci DE_ASSERT(false); 169e5c31af7Sopenharmony_ci return DE_NULL; 170e5c31af7Sopenharmony_ci } 171e5c31af7Sopenharmony_ci} 172e5c31af7Sopenharmony_ci 173e5c31af7Sopenharmony_cistatic const char* getDerivateFuncCaseName (DerivateFunc func) 174e5c31af7Sopenharmony_ci{ 175e5c31af7Sopenharmony_ci switch (func) 176e5c31af7Sopenharmony_ci { 177e5c31af7Sopenharmony_ci case DERIVATE_DFDX: return "dfdx"; 178e5c31af7Sopenharmony_ci case DERIVATE_DFDY: return "dfdy"; 179e5c31af7Sopenharmony_ci case DERIVATE_FWIDTH: return "fwidth"; 180e5c31af7Sopenharmony_ci default: 181e5c31af7Sopenharmony_ci DE_ASSERT(false); 182e5c31af7Sopenharmony_ci return DE_NULL; 183e5c31af7Sopenharmony_ci } 184e5c31af7Sopenharmony_ci} 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_cistatic inline tcu::BVec4 getDerivateMask (glu::DataType type) 187e5c31af7Sopenharmony_ci{ 188e5c31af7Sopenharmony_ci switch (type) 189e5c31af7Sopenharmony_ci { 190e5c31af7Sopenharmony_ci case glu::TYPE_FLOAT: return tcu::BVec4(true, false, false, false); 191e5c31af7Sopenharmony_ci case glu::TYPE_FLOAT_VEC2: return tcu::BVec4(true, true, false, false); 192e5c31af7Sopenharmony_ci case glu::TYPE_FLOAT_VEC3: return tcu::BVec4(true, true, true, false); 193e5c31af7Sopenharmony_ci case glu::TYPE_FLOAT_VEC4: return tcu::BVec4(true, true, true, true); 194e5c31af7Sopenharmony_ci default: 195e5c31af7Sopenharmony_ci DE_ASSERT(false); 196e5c31af7Sopenharmony_ci return tcu::BVec4(true); 197e5c31af7Sopenharmony_ci } 198e5c31af7Sopenharmony_ci} 199e5c31af7Sopenharmony_ci 200e5c31af7Sopenharmony_cistatic inline tcu::Vec4 readDerivate (const tcu::ConstPixelBufferAccess& surface, const tcu::Vec4& derivScale, const tcu::Vec4& derivBias, int x, int y) 201e5c31af7Sopenharmony_ci{ 202e5c31af7Sopenharmony_ci return (surface.getPixel(x, y) - derivBias) / derivScale; 203e5c31af7Sopenharmony_ci} 204e5c31af7Sopenharmony_ci 205e5c31af7Sopenharmony_cistatic inline tcu::UVec4 getCompExpBits (const tcu::Vec4& v) 206e5c31af7Sopenharmony_ci{ 207e5c31af7Sopenharmony_ci return tcu::UVec4(tcu::Float32(v[0]).exponentBits(), 208e5c31af7Sopenharmony_ci tcu::Float32(v[1]).exponentBits(), 209e5c31af7Sopenharmony_ci tcu::Float32(v[2]).exponentBits(), 210e5c31af7Sopenharmony_ci tcu::Float32(v[3]).exponentBits()); 211e5c31af7Sopenharmony_ci} 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_cifloat computeFloatingPointError (const float value, const int numAccurateBits) 214e5c31af7Sopenharmony_ci{ 215e5c31af7Sopenharmony_ci const int numGarbageBits = 23-numAccurateBits; 216e5c31af7Sopenharmony_ci const deUint32 mask = (1u<<numGarbageBits)-1u; 217e5c31af7Sopenharmony_ci const int exp = (tcu::Float32(value).exponent() < -3) ? -3 : tcu::Float32(value).exponent(); 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_ci return tcu::Float32::construct(+1, exp, (1u<<23) | mask).asFloat() - tcu::Float32::construct(+1, exp, 1u<<23).asFloat(); 220e5c31af7Sopenharmony_ci} 221e5c31af7Sopenharmony_ci 222e5c31af7Sopenharmony_cistatic int getNumMantissaBits (const glu::Precision precision) 223e5c31af7Sopenharmony_ci{ 224e5c31af7Sopenharmony_ci switch (precision) 225e5c31af7Sopenharmony_ci { 226e5c31af7Sopenharmony_ci case glu::PRECISION_HIGHP: return 23; 227e5c31af7Sopenharmony_ci case glu::PRECISION_MEDIUMP: return 10; 228e5c31af7Sopenharmony_ci case glu::PRECISION_LOWP: return 6; 229e5c31af7Sopenharmony_ci default: 230e5c31af7Sopenharmony_ci DE_ASSERT(false); 231e5c31af7Sopenharmony_ci return 0; 232e5c31af7Sopenharmony_ci } 233e5c31af7Sopenharmony_ci} 234e5c31af7Sopenharmony_ci 235e5c31af7Sopenharmony_cistatic int getMinExponent (const glu::Precision precision) 236e5c31af7Sopenharmony_ci{ 237e5c31af7Sopenharmony_ci switch (precision) 238e5c31af7Sopenharmony_ci { 239e5c31af7Sopenharmony_ci case glu::PRECISION_HIGHP: return -126; 240e5c31af7Sopenharmony_ci case glu::PRECISION_MEDIUMP: return -14; 241e5c31af7Sopenharmony_ci case glu::PRECISION_LOWP: return -8; 242e5c31af7Sopenharmony_ci default: 243e5c31af7Sopenharmony_ci DE_ASSERT(false); 244e5c31af7Sopenharmony_ci return 0; 245e5c31af7Sopenharmony_ci } 246e5c31af7Sopenharmony_ci} 247e5c31af7Sopenharmony_ci 248e5c31af7Sopenharmony_cistatic float getSingleULPForExponent (int exp, int numMantissaBits) 249e5c31af7Sopenharmony_ci{ 250e5c31af7Sopenharmony_ci if (numMantissaBits > 0) 251e5c31af7Sopenharmony_ci { 252e5c31af7Sopenharmony_ci DE_ASSERT(numMantissaBits <= 23); 253e5c31af7Sopenharmony_ci 254e5c31af7Sopenharmony_ci const int ulpBitNdx = 23-numMantissaBits; 255e5c31af7Sopenharmony_ci return tcu::Float32::construct(+1, exp, (1<<23) | (1 << ulpBitNdx)).asFloat() - tcu::Float32::construct(+1, exp, (1<<23)).asFloat(); 256e5c31af7Sopenharmony_ci } 257e5c31af7Sopenharmony_ci else 258e5c31af7Sopenharmony_ci { 259e5c31af7Sopenharmony_ci DE_ASSERT(numMantissaBits == 0); 260e5c31af7Sopenharmony_ci return tcu::Float32::construct(+1, exp, (1<<23)).asFloat(); 261e5c31af7Sopenharmony_ci } 262e5c31af7Sopenharmony_ci} 263e5c31af7Sopenharmony_ci 264e5c31af7Sopenharmony_cistatic float getSingleULPForValue (float value, int numMantissaBits) 265e5c31af7Sopenharmony_ci{ 266e5c31af7Sopenharmony_ci const int exp = tcu::Float32(value).exponent(); 267e5c31af7Sopenharmony_ci return getSingleULPForExponent(exp, numMantissaBits); 268e5c31af7Sopenharmony_ci} 269e5c31af7Sopenharmony_ci 270e5c31af7Sopenharmony_cistatic float convertFloatFlushToZeroRtn (float value, int minExponent, int numAccurateBits) 271e5c31af7Sopenharmony_ci{ 272e5c31af7Sopenharmony_ci if (value == 0.0f) 273e5c31af7Sopenharmony_ci { 274e5c31af7Sopenharmony_ci return 0.0f; 275e5c31af7Sopenharmony_ci } 276e5c31af7Sopenharmony_ci else 277e5c31af7Sopenharmony_ci { 278e5c31af7Sopenharmony_ci const tcu::Float32 inputFloat = tcu::Float32(value); 279e5c31af7Sopenharmony_ci const int numTruncatedBits = 23-numAccurateBits; 280e5c31af7Sopenharmony_ci const deUint32 truncMask = (1u<<numTruncatedBits)-1u; 281e5c31af7Sopenharmony_ci 282e5c31af7Sopenharmony_ci if (value > 0.0f) 283e5c31af7Sopenharmony_ci { 284e5c31af7Sopenharmony_ci if (value > 0.0f && tcu::Float32(value).exponent() < minExponent) 285e5c31af7Sopenharmony_ci { 286e5c31af7Sopenharmony_ci // flush to zero if possible 287e5c31af7Sopenharmony_ci return 0.0f; 288e5c31af7Sopenharmony_ci } 289e5c31af7Sopenharmony_ci else 290e5c31af7Sopenharmony_ci { 291e5c31af7Sopenharmony_ci // just mask away non-representable bits 292e5c31af7Sopenharmony_ci return tcu::Float32::construct(+1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask).asFloat(); 293e5c31af7Sopenharmony_ci } 294e5c31af7Sopenharmony_ci } 295e5c31af7Sopenharmony_ci else 296e5c31af7Sopenharmony_ci { 297e5c31af7Sopenharmony_ci if (inputFloat.mantissa() & truncMask) 298e5c31af7Sopenharmony_ci { 299e5c31af7Sopenharmony_ci // decrement one ulp if truncated bits are non-zero (i.e. if value is not representable) 300e5c31af7Sopenharmony_ci return tcu::Float32::construct(-1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask).asFloat() - getSingleULPForExponent(inputFloat.exponent(), numAccurateBits); 301e5c31af7Sopenharmony_ci } 302e5c31af7Sopenharmony_ci else 303e5c31af7Sopenharmony_ci { 304e5c31af7Sopenharmony_ci // value is representable, no need to do anything 305e5c31af7Sopenharmony_ci return value; 306e5c31af7Sopenharmony_ci } 307e5c31af7Sopenharmony_ci } 308e5c31af7Sopenharmony_ci } 309e5c31af7Sopenharmony_ci} 310e5c31af7Sopenharmony_ci 311e5c31af7Sopenharmony_cistatic float convertFloatFlushToZeroRtp (float value, int minExponent, int numAccurateBits) 312e5c31af7Sopenharmony_ci{ 313e5c31af7Sopenharmony_ci return -convertFloatFlushToZeroRtn(-value, minExponent, numAccurateBits); 314e5c31af7Sopenharmony_ci} 315e5c31af7Sopenharmony_ci 316e5c31af7Sopenharmony_cistatic float addErrorUlp (float value, float numUlps, int numMantissaBits) 317e5c31af7Sopenharmony_ci{ 318e5c31af7Sopenharmony_ci return value + numUlps * getSingleULPForValue(value, numMantissaBits); 319e5c31af7Sopenharmony_ci} 320e5c31af7Sopenharmony_ci 321e5c31af7Sopenharmony_cienum 322e5c31af7Sopenharmony_ci{ 323e5c31af7Sopenharmony_ci INTERPOLATION_LOST_BITS = 3, // number mantissa of bits allowed to be lost in varying interpolation 324e5c31af7Sopenharmony_ci}; 325e5c31af7Sopenharmony_ci 326e5c31af7Sopenharmony_cistatic int getInterpolationLostBitsWarning (const glu::Precision precision) 327e5c31af7Sopenharmony_ci{ 328e5c31af7Sopenharmony_ci // number mantissa of bits allowed to be lost in varying interpolation 329e5c31af7Sopenharmony_ci switch (precision) 330e5c31af7Sopenharmony_ci { 331e5c31af7Sopenharmony_ci case glu::PRECISION_HIGHP: return 9; 332e5c31af7Sopenharmony_ci case glu::PRECISION_MEDIUMP: return 3; 333e5c31af7Sopenharmony_ci case glu::PRECISION_LOWP: return 3; 334e5c31af7Sopenharmony_ci default: 335e5c31af7Sopenharmony_ci DE_ASSERT(false); 336e5c31af7Sopenharmony_ci return 0; 337e5c31af7Sopenharmony_ci } 338e5c31af7Sopenharmony_ci} 339e5c31af7Sopenharmony_ci 340e5c31af7Sopenharmony_cistatic inline tcu::Vec4 getDerivateThreshold (const glu::Precision precision, const tcu::Vec4& valueMin, const tcu::Vec4& valueMax, const tcu::Vec4& expectedDerivate) 341e5c31af7Sopenharmony_ci{ 342e5c31af7Sopenharmony_ci const int baseBits = getNumMantissaBits(precision); 343e5c31af7Sopenharmony_ci const tcu::UVec4 derivExp = getCompExpBits(expectedDerivate); 344e5c31af7Sopenharmony_ci const tcu::UVec4 maxValueExp = max(getCompExpBits(valueMin), getCompExpBits(valueMax)); 345e5c31af7Sopenharmony_ci const tcu::UVec4 numBitsLost = maxValueExp - min(maxValueExp, derivExp); 346e5c31af7Sopenharmony_ci const tcu::IVec4 numAccurateBits = max(baseBits - numBitsLost.asInt() - (int)INTERPOLATION_LOST_BITS, tcu::IVec4(0)); 347e5c31af7Sopenharmony_ci 348e5c31af7Sopenharmony_ci return tcu::Vec4(computeFloatingPointError(expectedDerivate[0], numAccurateBits[0]), 349e5c31af7Sopenharmony_ci computeFloatingPointError(expectedDerivate[1], numAccurateBits[1]), 350e5c31af7Sopenharmony_ci computeFloatingPointError(expectedDerivate[2], numAccurateBits[2]), 351e5c31af7Sopenharmony_ci computeFloatingPointError(expectedDerivate[3], numAccurateBits[3])); 352e5c31af7Sopenharmony_ci} 353e5c31af7Sopenharmony_ci 354e5c31af7Sopenharmony_cistatic inline tcu::Vec4 getDerivateThresholdWarning (const glu::Precision precision, const tcu::Vec4& valueMin, const tcu::Vec4& valueMax, const tcu::Vec4& expectedDerivate) 355e5c31af7Sopenharmony_ci{ 356e5c31af7Sopenharmony_ci const int baseBits = getNumMantissaBits(precision); 357e5c31af7Sopenharmony_ci const tcu::UVec4 derivExp = getCompExpBits(expectedDerivate); 358e5c31af7Sopenharmony_ci const tcu::UVec4 maxValueExp = max(getCompExpBits(valueMin), getCompExpBits(valueMax)); 359e5c31af7Sopenharmony_ci const tcu::UVec4 numBitsLost = maxValueExp - min(maxValueExp, derivExp); 360e5c31af7Sopenharmony_ci const tcu::IVec4 numAccurateBits = max(baseBits - numBitsLost.asInt() - getInterpolationLostBitsWarning(precision), tcu::IVec4(0)); 361e5c31af7Sopenharmony_ci 362e5c31af7Sopenharmony_ci return tcu::Vec4(computeFloatingPointError(expectedDerivate[0], numAccurateBits[0]), 363e5c31af7Sopenharmony_ci computeFloatingPointError(expectedDerivate[1], numAccurateBits[1]), 364e5c31af7Sopenharmony_ci computeFloatingPointError(expectedDerivate[2], numAccurateBits[2]), 365e5c31af7Sopenharmony_ci computeFloatingPointError(expectedDerivate[3], numAccurateBits[3])); 366e5c31af7Sopenharmony_ci} 367e5c31af7Sopenharmony_ci 368e5c31af7Sopenharmony_ci 369e5c31af7Sopenharmony_cinamespace 370e5c31af7Sopenharmony_ci{ 371e5c31af7Sopenharmony_ci 372e5c31af7Sopenharmony_cistruct LogVecComps 373e5c31af7Sopenharmony_ci{ 374e5c31af7Sopenharmony_ci const tcu::Vec4& v; 375e5c31af7Sopenharmony_ci int numComps; 376e5c31af7Sopenharmony_ci 377e5c31af7Sopenharmony_ci LogVecComps (const tcu::Vec4& v_, int numComps_) 378e5c31af7Sopenharmony_ci : v (v_) 379e5c31af7Sopenharmony_ci , numComps (numComps_) 380e5c31af7Sopenharmony_ci { 381e5c31af7Sopenharmony_ci } 382e5c31af7Sopenharmony_ci}; 383e5c31af7Sopenharmony_ci 384e5c31af7Sopenharmony_cistd::ostream& operator<< (std::ostream& str, const LogVecComps& v) 385e5c31af7Sopenharmony_ci{ 386e5c31af7Sopenharmony_ci DE_ASSERT(de::inRange(v.numComps, 1, 4)); 387e5c31af7Sopenharmony_ci if (v.numComps == 1) return str << v.v[0]; 388e5c31af7Sopenharmony_ci else if (v.numComps == 2) return str << v.v.toWidth<2>(); 389e5c31af7Sopenharmony_ci else if (v.numComps == 3) return str << v.v.toWidth<3>(); 390e5c31af7Sopenharmony_ci else return str << v.v; 391e5c31af7Sopenharmony_ci} 392e5c31af7Sopenharmony_ci 393e5c31af7Sopenharmony_ci} // anonymous 394e5c31af7Sopenharmony_ci 395e5c31af7Sopenharmony_cienum VerificationLogging 396e5c31af7Sopenharmony_ci{ 397e5c31af7Sopenharmony_ci LOG_ALL = 0, 398e5c31af7Sopenharmony_ci LOG_NOTHING 399e5c31af7Sopenharmony_ci}; 400e5c31af7Sopenharmony_ci 401e5c31af7Sopenharmony_cistatic qpTestResult verifyConstantDerivate (tcu::TestLog& log, 402e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 403e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 404e5c31af7Sopenharmony_ci glu::DataType dataType, 405e5c31af7Sopenharmony_ci const tcu::Vec4& reference, 406e5c31af7Sopenharmony_ci const tcu::Vec4& threshold, 407e5c31af7Sopenharmony_ci const tcu::Vec4& scale, 408e5c31af7Sopenharmony_ci const tcu::Vec4& bias, 409e5c31af7Sopenharmony_ci VerificationLogging logPolicy = LOG_ALL) 410e5c31af7Sopenharmony_ci{ 411e5c31af7Sopenharmony_ci const int numComps = glu::getDataTypeFloatScalars(dataType); 412e5c31af7Sopenharmony_ci const tcu::BVec4 mask = tcu::logicalNot(getDerivateMask(dataType)); 413e5c31af7Sopenharmony_ci int numFailedPixels = 0; 414e5c31af7Sopenharmony_ci 415e5c31af7Sopenharmony_ci if (logPolicy == LOG_ALL) 416e5c31af7Sopenharmony_ci log << TestLog::Message << "Expecting " << LogVecComps(reference, numComps) << " with threshold " << LogVecComps(threshold, numComps) << TestLog::EndMessage; 417e5c31af7Sopenharmony_ci 418e5c31af7Sopenharmony_ci for (int y = 0; y < result.getHeight(); y++) 419e5c31af7Sopenharmony_ci { 420e5c31af7Sopenharmony_ci for (int x = 0; x < result.getWidth(); x++) 421e5c31af7Sopenharmony_ci { 422e5c31af7Sopenharmony_ci const tcu::Vec4 resDerivate = readDerivate(result, scale, bias, x, y); 423e5c31af7Sopenharmony_ci const bool isOk = tcu::allEqual(tcu::logicalOr(tcu::lessThanEqual(tcu::abs(reference - resDerivate), threshold), mask), tcu::BVec4(true)); 424e5c31af7Sopenharmony_ci 425e5c31af7Sopenharmony_ci if (!isOk) 426e5c31af7Sopenharmony_ci { 427e5c31af7Sopenharmony_ci if (numFailedPixels < MAX_FAILED_MESSAGES && logPolicy == LOG_ALL) 428e5c31af7Sopenharmony_ci log << TestLog::Message << "FAIL: got " << LogVecComps(resDerivate, numComps) 429e5c31af7Sopenharmony_ci << ", diff = " << LogVecComps(tcu::abs(reference - resDerivate), numComps) 430e5c31af7Sopenharmony_ci << ", at x = " << x << ", y = " << y 431e5c31af7Sopenharmony_ci << TestLog::EndMessage; 432e5c31af7Sopenharmony_ci numFailedPixels += 1; 433e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), x, y); 434e5c31af7Sopenharmony_ci } 435e5c31af7Sopenharmony_ci } 436e5c31af7Sopenharmony_ci } 437e5c31af7Sopenharmony_ci 438e5c31af7Sopenharmony_ci if (numFailedPixels >= MAX_FAILED_MESSAGES && logPolicy == LOG_ALL) 439e5c31af7Sopenharmony_ci log << TestLog::Message << "..." << TestLog::EndMessage; 440e5c31af7Sopenharmony_ci 441e5c31af7Sopenharmony_ci if (numFailedPixels > 0 && logPolicy == LOG_ALL) 442e5c31af7Sopenharmony_ci log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage; 443e5c31af7Sopenharmony_ci 444e5c31af7Sopenharmony_ci return (numFailedPixels == 0) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL; 445e5c31af7Sopenharmony_ci} 446e5c31af7Sopenharmony_ci 447e5c31af7Sopenharmony_cistruct Linear2DFunctionEvaluator 448e5c31af7Sopenharmony_ci{ 449e5c31af7Sopenharmony_ci tcu::Matrix<float, 4, 3> matrix; 450e5c31af7Sopenharmony_ci 451e5c31af7Sopenharmony_ci // .-----. 452e5c31af7Sopenharmony_ci // | s_x | 453e5c31af7Sopenharmony_ci // M x | s_y | 454e5c31af7Sopenharmony_ci // | 1.0 | 455e5c31af7Sopenharmony_ci // '-----' 456e5c31af7Sopenharmony_ci tcu::Vec4 evaluateAt (float screenX, float screenY) const; 457e5c31af7Sopenharmony_ci}; 458e5c31af7Sopenharmony_ci 459e5c31af7Sopenharmony_citcu::Vec4 Linear2DFunctionEvaluator::evaluateAt (float screenX, float screenY) const 460e5c31af7Sopenharmony_ci{ 461e5c31af7Sopenharmony_ci const tcu::Vec3 position(screenX, screenY, 1.0f); 462e5c31af7Sopenharmony_ci return matrix * position; 463e5c31af7Sopenharmony_ci} 464e5c31af7Sopenharmony_ci 465e5c31af7Sopenharmony_cistatic qpTestResult reverifyConstantDerivateWithFlushRelaxations (tcu::TestLog& log, 466e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 467e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 468e5c31af7Sopenharmony_ci glu::DataType dataType, 469e5c31af7Sopenharmony_ci glu::Precision precision, 470e5c31af7Sopenharmony_ci const tcu::Vec4& derivScale, 471e5c31af7Sopenharmony_ci const tcu::Vec4& derivBias, 472e5c31af7Sopenharmony_ci const tcu::Vec4& surfaceThreshold, 473e5c31af7Sopenharmony_ci DerivateFunc derivateFunc, 474e5c31af7Sopenharmony_ci const Linear2DFunctionEvaluator& function) 475e5c31af7Sopenharmony_ci{ 476e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth()); 477e5c31af7Sopenharmony_ci DE_ASSERT(result.getHeight() == errorMask.getHeight()); 478e5c31af7Sopenharmony_ci DE_ASSERT(derivateFunc == DERIVATE_DFDX || derivateFunc == DERIVATE_DFDY); 479e5c31af7Sopenharmony_ci 480e5c31af7Sopenharmony_ci const tcu::IVec4 red (255, 0, 0, 255); 481e5c31af7Sopenharmony_ci const tcu::IVec4 green (0, 255, 0, 255); 482e5c31af7Sopenharmony_ci const float divisionErrorUlps = 2.5f; 483e5c31af7Sopenharmony_ci 484e5c31af7Sopenharmony_ci const int numComponents = glu::getDataTypeFloatScalars(dataType); 485e5c31af7Sopenharmony_ci const int numBits = getNumMantissaBits(precision); 486e5c31af7Sopenharmony_ci const int minExponent = getMinExponent(precision); 487e5c31af7Sopenharmony_ci 488e5c31af7Sopenharmony_ci const int numVaryingSampleBits = numBits - INTERPOLATION_LOST_BITS; 489e5c31af7Sopenharmony_ci int numFailedPixels = 0; 490e5c31af7Sopenharmony_ci 491e5c31af7Sopenharmony_ci tcu::clear(errorMask, green); 492e5c31af7Sopenharmony_ci 493e5c31af7Sopenharmony_ci // search for failed pixels 494e5c31af7Sopenharmony_ci for (int y = 0; y < result.getHeight(); ++y) 495e5c31af7Sopenharmony_ci for (int x = 0; x < result.getWidth(); ++x) 496e5c31af7Sopenharmony_ci { 497e5c31af7Sopenharmony_ci // flushToZero?(f2z?(functionValueCurrent) - f2z?(functionValueBefore)) 498e5c31af7Sopenharmony_ci // flushToZero? ( ------------------------------------------------------------------------ +- 2.5 ULP ) 499e5c31af7Sopenharmony_ci // dx 500e5c31af7Sopenharmony_ci 501e5c31af7Sopenharmony_ci const tcu::Vec4 resultDerivative = readDerivate(result, derivScale, derivBias, x, y); 502e5c31af7Sopenharmony_ci 503e5c31af7Sopenharmony_ci // sample at the front of the back pixel and the back of the front pixel to cover the whole area of 504e5c31af7Sopenharmony_ci // legal sample positions. In general case this is NOT OK, but we know that the target function is 505e5c31af7Sopenharmony_ci // (mostly*) linear which allows us to take the sample points at arbitrary points. This gets us the 506e5c31af7Sopenharmony_ci // maximum difference possible in exponents which are used in error bound calculations. 507e5c31af7Sopenharmony_ci // * non-linearity may happen around zero or with very high function values due to subnorms not 508e5c31af7Sopenharmony_ci // behaving well. 509e5c31af7Sopenharmony_ci const tcu::Vec4 functionValueForward = (derivateFunc == DERIVATE_DFDX) 510e5c31af7Sopenharmony_ci ? (function.evaluateAt((float)x + 2.0f, (float)y + 0.5f)) 511e5c31af7Sopenharmony_ci : (function.evaluateAt((float)x + 0.5f, (float)y + 2.0f)); 512e5c31af7Sopenharmony_ci const tcu::Vec4 functionValueBackward = (derivateFunc == DERIVATE_DFDX) 513e5c31af7Sopenharmony_ci ? (function.evaluateAt((float)x - 1.0f, (float)y + 0.5f)) 514e5c31af7Sopenharmony_ci : (function.evaluateAt((float)x + 0.5f, (float)y - 1.0f)); 515e5c31af7Sopenharmony_ci 516e5c31af7Sopenharmony_ci bool anyComponentFailed = false; 517e5c31af7Sopenharmony_ci 518e5c31af7Sopenharmony_ci // check components separately 519e5c31af7Sopenharmony_ci for (int c = 0; c < numComponents; ++c) 520e5c31af7Sopenharmony_ci { 521e5c31af7Sopenharmony_ci // Simulate interpolation. Add allowed interpolation error and round to target precision. Allow one half ULP (i.e. correct rounding) 522e5c31af7Sopenharmony_ci const tcu::Interval forwardComponent (convertFloatFlushToZeroRtn(addErrorUlp((float)functionValueForward[c], -0.5f, numVaryingSampleBits), minExponent, numBits), 523e5c31af7Sopenharmony_ci convertFloatFlushToZeroRtp(addErrorUlp((float)functionValueForward[c], +0.5f, numVaryingSampleBits), minExponent, numBits)); 524e5c31af7Sopenharmony_ci const tcu::Interval backwardComponent (convertFloatFlushToZeroRtn(addErrorUlp((float)functionValueBackward[c], -0.5f, numVaryingSampleBits), minExponent, numBits), 525e5c31af7Sopenharmony_ci convertFloatFlushToZeroRtp(addErrorUlp((float)functionValueBackward[c], +0.5f, numVaryingSampleBits), minExponent, numBits)); 526e5c31af7Sopenharmony_ci const int maxValueExp = de::max(de::max(tcu::Float32(forwardComponent.lo()).exponent(), tcu::Float32(forwardComponent.hi()).exponent()), 527e5c31af7Sopenharmony_ci de::max(tcu::Float32(backwardComponent.lo()).exponent(), tcu::Float32(backwardComponent.hi()).exponent())); 528e5c31af7Sopenharmony_ci 529e5c31af7Sopenharmony_ci // subtraction in numerator will likely cause a cancellation of the most 530e5c31af7Sopenharmony_ci // significant bits. Apply error bounds. 531e5c31af7Sopenharmony_ci 532e5c31af7Sopenharmony_ci const tcu::Interval numerator (forwardComponent - backwardComponent); 533e5c31af7Sopenharmony_ci const int numeratorLoExp = tcu::Float32(numerator.lo()).exponent(); 534e5c31af7Sopenharmony_ci const int numeratorHiExp = tcu::Float32(numerator.hi()).exponent(); 535e5c31af7Sopenharmony_ci const int numeratorLoBitsLost = de::max(0, maxValueExp - numeratorLoExp); //!< must clamp to zero since if forward and backward components have different 536e5c31af7Sopenharmony_ci const int numeratorHiBitsLost = de::max(0, maxValueExp - numeratorHiExp); //!< sign, numerator might have larger exponent than its operands. 537e5c31af7Sopenharmony_ci const int numeratorLoBits = de::max(0, numBits - numeratorLoBitsLost); 538e5c31af7Sopenharmony_ci const int numeratorHiBits = de::max(0, numBits - numeratorHiBitsLost); 539e5c31af7Sopenharmony_ci 540e5c31af7Sopenharmony_ci const tcu::Interval numeratorRange (convertFloatFlushToZeroRtn((float)numerator.lo(), minExponent, numeratorLoBits), 541e5c31af7Sopenharmony_ci convertFloatFlushToZeroRtp((float)numerator.hi(), minExponent, numeratorHiBits)); 542e5c31af7Sopenharmony_ci 543e5c31af7Sopenharmony_ci const tcu::Interval divisionRange = numeratorRange / 3.0f; // legal sample area is anywhere within this and neighboring pixels (i.e. size = 3) 544e5c31af7Sopenharmony_ci const tcu::Interval divisionResultRange (convertFloatFlushToZeroRtn(addErrorUlp((float)divisionRange.lo(), -divisionErrorUlps, numBits), minExponent, numBits), 545e5c31af7Sopenharmony_ci convertFloatFlushToZeroRtp(addErrorUlp((float)divisionRange.hi(), +divisionErrorUlps, numBits), minExponent, numBits)); 546e5c31af7Sopenharmony_ci const tcu::Interval finalResultRange (divisionResultRange.lo() - surfaceThreshold[c], divisionResultRange.hi() + surfaceThreshold[c]); 547e5c31af7Sopenharmony_ci 548e5c31af7Sopenharmony_ci if (resultDerivative[c] >= finalResultRange.lo() && resultDerivative[c] <= finalResultRange.hi()) 549e5c31af7Sopenharmony_ci { 550e5c31af7Sopenharmony_ci // value ok 551e5c31af7Sopenharmony_ci } 552e5c31af7Sopenharmony_ci else 553e5c31af7Sopenharmony_ci { 554e5c31af7Sopenharmony_ci if (numFailedPixels < MAX_FAILED_MESSAGES) 555e5c31af7Sopenharmony_ci log << tcu::TestLog::Message 556e5c31af7Sopenharmony_ci << "Error in pixel at " << x << ", " << y << " with component " << c << " (channel " << ("rgba"[c]) << ")\n" 557e5c31af7Sopenharmony_ci << "\tGot pixel value " << result.getPixelInt(x, y) << "\n" 558e5c31af7Sopenharmony_ci << "\t\tdFd" << ((derivateFunc == DERIVATE_DFDX) ? ('x') : ('y')) << " ~= " << resultDerivative[c] << "\n" 559e5c31af7Sopenharmony_ci << "\t\tdifference to a valid range: " 560e5c31af7Sopenharmony_ci << ((resultDerivative[c] < finalResultRange.lo()) ? ("-") : ("+")) 561e5c31af7Sopenharmony_ci << ((resultDerivative[c] < finalResultRange.lo()) ? (finalResultRange.lo() - resultDerivative[c]) : (resultDerivative[c] - finalResultRange.hi())) 562e5c31af7Sopenharmony_ci << "\n" 563e5c31af7Sopenharmony_ci << "\tDerivative value range:\n" 564e5c31af7Sopenharmony_ci << "\t\tMin: " << finalResultRange.lo() << "\n" 565e5c31af7Sopenharmony_ci << "\t\tMax: " << finalResultRange.hi() << "\n" 566e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 567e5c31af7Sopenharmony_ci 568e5c31af7Sopenharmony_ci ++numFailedPixels; 569e5c31af7Sopenharmony_ci anyComponentFailed = true; 570e5c31af7Sopenharmony_ci } 571e5c31af7Sopenharmony_ci } 572e5c31af7Sopenharmony_ci 573e5c31af7Sopenharmony_ci if (anyComponentFailed) 574e5c31af7Sopenharmony_ci errorMask.setPixel(red, x, y); 575e5c31af7Sopenharmony_ci } 576e5c31af7Sopenharmony_ci 577e5c31af7Sopenharmony_ci if (numFailedPixels >= MAX_FAILED_MESSAGES) 578e5c31af7Sopenharmony_ci log << TestLog::Message << "..." << TestLog::EndMessage; 579e5c31af7Sopenharmony_ci 580e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 581e5c31af7Sopenharmony_ci log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage; 582e5c31af7Sopenharmony_ci 583e5c31af7Sopenharmony_ci return (numFailedPixels == 0) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL; 584e5c31af7Sopenharmony_ci} 585e5c31af7Sopenharmony_ci 586e5c31af7Sopenharmony_ci// TriangleDerivateCase 587e5c31af7Sopenharmony_ci 588e5c31af7Sopenharmony_ciclass TriangleDerivateCase : public TestCase 589e5c31af7Sopenharmony_ci{ 590e5c31af7Sopenharmony_cipublic: 591e5c31af7Sopenharmony_ci TriangleDerivateCase (Context& context, const char* name, const char* description); 592e5c31af7Sopenharmony_ci ~TriangleDerivateCase (void); 593e5c31af7Sopenharmony_ci 594e5c31af7Sopenharmony_ci IterateResult iterate (void); 595e5c31af7Sopenharmony_ci 596e5c31af7Sopenharmony_ciprotected: 597e5c31af7Sopenharmony_ci virtual void setupRenderState (deUint32 program) { DE_UNREF(program); } 598e5c31af7Sopenharmony_ci virtual qpTestResult verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) = DE_NULL; 599e5c31af7Sopenharmony_ci 600e5c31af7Sopenharmony_ci tcu::IVec2 getViewportSize (void) const; 601e5c31af7Sopenharmony_ci tcu::Vec4 getSurfaceThreshold (void) const; 602e5c31af7Sopenharmony_ci 603e5c31af7Sopenharmony_ci glu::DataType m_dataType; 604e5c31af7Sopenharmony_ci glu::Precision m_precision; 605e5c31af7Sopenharmony_ci 606e5c31af7Sopenharmony_ci glu::DataType m_coordDataType; 607e5c31af7Sopenharmony_ci glu::Precision m_coordPrecision; 608e5c31af7Sopenharmony_ci 609e5c31af7Sopenharmony_ci std::string m_fragmentSrc; 610e5c31af7Sopenharmony_ci 611e5c31af7Sopenharmony_ci tcu::Vec4 m_coordMin; 612e5c31af7Sopenharmony_ci tcu::Vec4 m_coordMax; 613e5c31af7Sopenharmony_ci tcu::Vec4 m_derivScale; 614e5c31af7Sopenharmony_ci tcu::Vec4 m_derivBias; 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci SurfaceType m_surfaceType; 617e5c31af7Sopenharmony_ci int m_numSamples; 618e5c31af7Sopenharmony_ci deUint32 m_hint; 619e5c31af7Sopenharmony_ci 620e5c31af7Sopenharmony_ci bool m_useAsymmetricCoords; 621e5c31af7Sopenharmony_ci}; 622e5c31af7Sopenharmony_ci 623e5c31af7Sopenharmony_ciTriangleDerivateCase::TriangleDerivateCase (Context& context, const char* name, const char* description) 624e5c31af7Sopenharmony_ci : TestCase (context, name, description) 625e5c31af7Sopenharmony_ci , m_dataType (glu::TYPE_LAST) 626e5c31af7Sopenharmony_ci , m_precision (glu::PRECISION_LAST) 627e5c31af7Sopenharmony_ci , m_coordDataType (glu::TYPE_LAST) 628e5c31af7Sopenharmony_ci , m_coordPrecision (glu::PRECISION_LAST) 629e5c31af7Sopenharmony_ci , m_surfaceType (SURFACETYPE_DEFAULT_FRAMEBUFFER) 630e5c31af7Sopenharmony_ci , m_numSamples (0) 631e5c31af7Sopenharmony_ci , m_hint (GL_DONT_CARE) 632e5c31af7Sopenharmony_ci , m_useAsymmetricCoords (false) 633e5c31af7Sopenharmony_ci{ 634e5c31af7Sopenharmony_ci DE_ASSERT(m_surfaceType != SURFACETYPE_DEFAULT_FRAMEBUFFER || m_numSamples == 0); 635e5c31af7Sopenharmony_ci} 636e5c31af7Sopenharmony_ci 637e5c31af7Sopenharmony_ciTriangleDerivateCase::~TriangleDerivateCase (void) 638e5c31af7Sopenharmony_ci{ 639e5c31af7Sopenharmony_ci TriangleDerivateCase::deinit(); 640e5c31af7Sopenharmony_ci} 641e5c31af7Sopenharmony_ci 642e5c31af7Sopenharmony_cistatic std::string genVertexSource (glu::DataType coordType, glu::Precision precision) 643e5c31af7Sopenharmony_ci{ 644e5c31af7Sopenharmony_ci DE_ASSERT(glu::isDataTypeFloatOrVec(coordType)); 645e5c31af7Sopenharmony_ci 646e5c31af7Sopenharmony_ci const char* vertexTmpl = 647e5c31af7Sopenharmony_ci "#version 300 es\n" 648e5c31af7Sopenharmony_ci "in highp vec4 a_position;\n" 649e5c31af7Sopenharmony_ci "in ${PRECISION} ${DATATYPE} a_coord;\n" 650e5c31af7Sopenharmony_ci "out ${PRECISION} ${DATATYPE} v_coord;\n" 651e5c31af7Sopenharmony_ci "void main (void)\n" 652e5c31af7Sopenharmony_ci "{\n" 653e5c31af7Sopenharmony_ci " gl_Position = a_position;\n" 654e5c31af7Sopenharmony_ci " v_coord = a_coord;\n" 655e5c31af7Sopenharmony_ci "}\n"; 656e5c31af7Sopenharmony_ci 657e5c31af7Sopenharmony_ci map<string, string> vertexParams; 658e5c31af7Sopenharmony_ci 659e5c31af7Sopenharmony_ci vertexParams["PRECISION"] = glu::getPrecisionName(precision); 660e5c31af7Sopenharmony_ci vertexParams["DATATYPE"] = glu::getDataTypeName(coordType); 661e5c31af7Sopenharmony_ci 662e5c31af7Sopenharmony_ci return tcu::StringTemplate(vertexTmpl).specialize(vertexParams); 663e5c31af7Sopenharmony_ci} 664e5c31af7Sopenharmony_ci 665e5c31af7Sopenharmony_ciinline tcu::IVec2 TriangleDerivateCase::getViewportSize (void) const 666e5c31af7Sopenharmony_ci{ 667e5c31af7Sopenharmony_ci if (m_surfaceType == SURFACETYPE_DEFAULT_FRAMEBUFFER) 668e5c31af7Sopenharmony_ci { 669e5c31af7Sopenharmony_ci const int width = de::min<int>(m_context.getRenderTarget().getWidth(), VIEWPORT_WIDTH); 670e5c31af7Sopenharmony_ci const int height = de::min<int>(m_context.getRenderTarget().getHeight(), VIEWPORT_HEIGHT); 671e5c31af7Sopenharmony_ci return tcu::IVec2(width, height); 672e5c31af7Sopenharmony_ci } 673e5c31af7Sopenharmony_ci else 674e5c31af7Sopenharmony_ci return tcu::IVec2(FBO_WIDTH, FBO_HEIGHT); 675e5c31af7Sopenharmony_ci} 676e5c31af7Sopenharmony_ci 677e5c31af7Sopenharmony_ciTriangleDerivateCase::IterateResult TriangleDerivateCase::iterate (void) 678e5c31af7Sopenharmony_ci{ 679e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 680e5c31af7Sopenharmony_ci const glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(genVertexSource(m_coordDataType, m_coordPrecision), m_fragmentSrc)); 681e5c31af7Sopenharmony_ci de::Random rnd (deStringHash(getName()) ^ 0xbbc24); 682e5c31af7Sopenharmony_ci const bool useFbo = m_surfaceType != SURFACETYPE_DEFAULT_FRAMEBUFFER; 683e5c31af7Sopenharmony_ci const deUint32 fboFormat = m_surfaceType == SURFACETYPE_FLOAT_FBO ? GL_RGBA32UI : GL_RGBA8; 684e5c31af7Sopenharmony_ci const tcu::IVec2 viewportSize = getViewportSize(); 685e5c31af7Sopenharmony_ci const int viewportX = useFbo ? 0 : rnd.getInt(0, m_context.getRenderTarget().getWidth() - viewportSize.x()); 686e5c31af7Sopenharmony_ci const int viewportY = useFbo ? 0 : rnd.getInt(0, m_context.getRenderTarget().getHeight() - viewportSize.y()); 687e5c31af7Sopenharmony_ci AutoFbo fbo (gl); 688e5c31af7Sopenharmony_ci AutoRbo rbo (gl); 689e5c31af7Sopenharmony_ci tcu::TextureLevel result; 690e5c31af7Sopenharmony_ci 691e5c31af7Sopenharmony_ci m_testCtx.getLog() << program; 692e5c31af7Sopenharmony_ci 693e5c31af7Sopenharmony_ci if (!program.isOk()) 694e5c31af7Sopenharmony_ci TCU_FAIL("Compile failed"); 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci if (useFbo) 697e5c31af7Sopenharmony_ci { 698e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message 699e5c31af7Sopenharmony_ci << "Rendering to FBO, format = " << glu::getTextureFormatStr(fboFormat) 700e5c31af7Sopenharmony_ci << ", samples = " << m_numSamples 701e5c31af7Sopenharmony_ci << TestLog::EndMessage; 702e5c31af7Sopenharmony_ci 703e5c31af7Sopenharmony_ci fbo.gen(); 704e5c31af7Sopenharmony_ci rbo.gen(); 705e5c31af7Sopenharmony_ci 706e5c31af7Sopenharmony_ci gl.bindRenderbuffer(GL_RENDERBUFFER, *rbo); 707e5c31af7Sopenharmony_ci gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_numSamples, fboFormat, viewportSize.x(), viewportSize.y()); 708e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo); 709e5c31af7Sopenharmony_ci gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *rbo); 710e5c31af7Sopenharmony_ci TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 711e5c31af7Sopenharmony_ci } 712e5c31af7Sopenharmony_ci else 713e5c31af7Sopenharmony_ci { 714e5c31af7Sopenharmony_ci const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 715e5c31af7Sopenharmony_ci 716e5c31af7Sopenharmony_ci m_testCtx.getLog() 717e5c31af7Sopenharmony_ci << TestLog::Message 718e5c31af7Sopenharmony_ci << "Rendering to default framebuffer\n" 719e5c31af7Sopenharmony_ci << "\tColor depth: R=" << pixelFormat.redBits << ", G=" << pixelFormat.greenBits << ", B=" << pixelFormat.blueBits << ", A=" << pixelFormat.alphaBits 720e5c31af7Sopenharmony_ci << TestLog::EndMessage; 721e5c31af7Sopenharmony_ci } 722e5c31af7Sopenharmony_ci 723e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Message << "in: " << m_coordMin << " -> " << m_coordMax << "\n" 724e5c31af7Sopenharmony_ci << (m_useAsymmetricCoords ? "v_coord.x = in.x * (x+y)/2\n" : "v_coord.x = in.x * x\n") 725e5c31af7Sopenharmony_ci << (m_useAsymmetricCoords ? "v_coord.y = in.y * (x+y)/2\n" : "v_coord.y = in.y * y\n") 726e5c31af7Sopenharmony_ci << "v_coord.z = in.z * (x+y)/2\n" 727e5c31af7Sopenharmony_ci << "v_coord.w = in.w * (1 - (x+y)/2)\n" 728e5c31af7Sopenharmony_ci << TestLog::EndMessage 729e5c31af7Sopenharmony_ci << TestLog::Message << "u_scale: " << m_derivScale << ", u_bias: " << m_derivBias << " (displayed values have scale/bias removed)" << TestLog::EndMessage 730e5c31af7Sopenharmony_ci << TestLog::Message << "Viewport: " << viewportSize.x() << "x" << viewportSize.y() << TestLog::EndMessage 731e5c31af7Sopenharmony_ci << TestLog::Message << "GL_FRAGMENT_SHADER_DERIVATE_HINT: " << glu::getHintModeStr(m_hint) << TestLog::EndMessage; 732e5c31af7Sopenharmony_ci 733e5c31af7Sopenharmony_ci // Draw 734e5c31af7Sopenharmony_ci { 735e5c31af7Sopenharmony_ci const float positions[] = 736e5c31af7Sopenharmony_ci { 737e5c31af7Sopenharmony_ci -1.0f, -1.0f, 0.0f, 1.0f, 738e5c31af7Sopenharmony_ci -1.0f, 1.0f, 0.0f, 1.0f, 739e5c31af7Sopenharmony_ci 1.0f, -1.0f, 0.0f, 1.0f, 740e5c31af7Sopenharmony_ci 1.0f, 1.0f, 0.0f, 1.0f 741e5c31af7Sopenharmony_ci }; 742e5c31af7Sopenharmony_ci float coords[] = 743e5c31af7Sopenharmony_ci { 744e5c31af7Sopenharmony_ci m_coordMin.x(), m_coordMin.y(), m_coordMin.z(), m_coordMax.w(), 745e5c31af7Sopenharmony_ci m_coordMin.x(), m_coordMax.y(), (m_coordMin.z()+m_coordMax.z())*0.5f, (m_coordMin.w()+m_coordMax.w())*0.5f, 746e5c31af7Sopenharmony_ci m_coordMax.x(), m_coordMin.y(), (m_coordMin.z()+m_coordMax.z())*0.5f, (m_coordMin.w()+m_coordMax.w())*0.5f, 747e5c31af7Sopenharmony_ci m_coordMax.x(), m_coordMax.y(), m_coordMax.z(), m_coordMin.w() 748e5c31af7Sopenharmony_ci }; 749e5c31af7Sopenharmony_ci 750e5c31af7Sopenharmony_ci // For linear tests we want varying data x and y to vary along both axes 751e5c31af7Sopenharmony_ci // to get nonzero x for dfdy and nonzero y for dfdx. To make the gradient 752e5c31af7Sopenharmony_ci // the same for both triangles we set vertices 2 and 3 to middle values. 753e5c31af7Sopenharmony_ci // This way the values go from min -> (max+min) / 2 or (max+min) / 2 -> max 754e5c31af7Sopenharmony_ci // depending on the triangle, but the derivative is the same for both. 755e5c31af7Sopenharmony_ci if (m_useAsymmetricCoords) 756e5c31af7Sopenharmony_ci { 757e5c31af7Sopenharmony_ci coords[4] = coords[8] = (m_coordMin.x() + m_coordMax.x())*0.5f; 758e5c31af7Sopenharmony_ci coords[5] = coords[9] = (m_coordMin.y() + m_coordMax.y())*0.5f; 759e5c31af7Sopenharmony_ci } 760e5c31af7Sopenharmony_ci 761e5c31af7Sopenharmony_ci const glu::VertexArrayBinding vertexArrays[] = 762e5c31af7Sopenharmony_ci { 763e5c31af7Sopenharmony_ci glu::va::Float("a_position", 4, 4, 0, &positions[0]), 764e5c31af7Sopenharmony_ci glu::va::Float("a_coord", 4, 4, 0, &coords[0]) 765e5c31af7Sopenharmony_ci }; 766e5c31af7Sopenharmony_ci const deUint16 indices[] = { 0, 2, 1, 2, 3, 1 }; 767e5c31af7Sopenharmony_ci 768e5c31af7Sopenharmony_ci gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f); 769e5c31af7Sopenharmony_ci gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 770e5c31af7Sopenharmony_ci gl.disable(GL_DITHER); 771e5c31af7Sopenharmony_ci 772e5c31af7Sopenharmony_ci gl.useProgram(program.getProgram()); 773e5c31af7Sopenharmony_ci 774e5c31af7Sopenharmony_ci { 775e5c31af7Sopenharmony_ci const int scaleLoc = gl.getUniformLocation(program.getProgram(), "u_scale"); 776e5c31af7Sopenharmony_ci const int biasLoc = gl.getUniformLocation(program.getProgram(), "u_bias"); 777e5c31af7Sopenharmony_ci 778e5c31af7Sopenharmony_ci switch (m_dataType) 779e5c31af7Sopenharmony_ci { 780e5c31af7Sopenharmony_ci case glu::TYPE_FLOAT: 781e5c31af7Sopenharmony_ci gl.uniform1f(scaleLoc, m_derivScale.x()); 782e5c31af7Sopenharmony_ci gl.uniform1f(biasLoc, m_derivBias.x()); 783e5c31af7Sopenharmony_ci break; 784e5c31af7Sopenharmony_ci 785e5c31af7Sopenharmony_ci case glu::TYPE_FLOAT_VEC2: 786e5c31af7Sopenharmony_ci gl.uniform2fv(scaleLoc, 1, m_derivScale.getPtr()); 787e5c31af7Sopenharmony_ci gl.uniform2fv(biasLoc, 1, m_derivBias.getPtr()); 788e5c31af7Sopenharmony_ci break; 789e5c31af7Sopenharmony_ci 790e5c31af7Sopenharmony_ci case glu::TYPE_FLOAT_VEC3: 791e5c31af7Sopenharmony_ci gl.uniform3fv(scaleLoc, 1, m_derivScale.getPtr()); 792e5c31af7Sopenharmony_ci gl.uniform3fv(biasLoc, 1, m_derivBias.getPtr()); 793e5c31af7Sopenharmony_ci break; 794e5c31af7Sopenharmony_ci 795e5c31af7Sopenharmony_ci case glu::TYPE_FLOAT_VEC4: 796e5c31af7Sopenharmony_ci gl.uniform4fv(scaleLoc, 1, m_derivScale.getPtr()); 797e5c31af7Sopenharmony_ci gl.uniform4fv(biasLoc, 1, m_derivBias.getPtr()); 798e5c31af7Sopenharmony_ci break; 799e5c31af7Sopenharmony_ci 800e5c31af7Sopenharmony_ci default: 801e5c31af7Sopenharmony_ci DE_ASSERT(false); 802e5c31af7Sopenharmony_ci } 803e5c31af7Sopenharmony_ci } 804e5c31af7Sopenharmony_ci 805e5c31af7Sopenharmony_ci gls::setupDefaultUniforms(m_context.getRenderContext(), program.getProgram()); 806e5c31af7Sopenharmony_ci setupRenderState(program.getProgram()); 807e5c31af7Sopenharmony_ci 808e5c31af7Sopenharmony_ci gl.hint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT, m_hint); 809e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Setup program state"); 810e5c31af7Sopenharmony_ci 811e5c31af7Sopenharmony_ci gl.viewport(viewportX, viewportY, viewportSize.x(), viewportSize.y()); 812e5c31af7Sopenharmony_ci glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], 813e5c31af7Sopenharmony_ci glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0])); 814e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Draw"); 815e5c31af7Sopenharmony_ci } 816e5c31af7Sopenharmony_ci 817e5c31af7Sopenharmony_ci // Read back results 818e5c31af7Sopenharmony_ci { 819e5c31af7Sopenharmony_ci const bool isMSAA = useFbo && m_numSamples > 0; 820e5c31af7Sopenharmony_ci AutoFbo resFbo (gl); 821e5c31af7Sopenharmony_ci AutoRbo resRbo (gl); 822e5c31af7Sopenharmony_ci 823e5c31af7Sopenharmony_ci // Resolve if necessary 824e5c31af7Sopenharmony_ci if (isMSAA) 825e5c31af7Sopenharmony_ci { 826e5c31af7Sopenharmony_ci resFbo.gen(); 827e5c31af7Sopenharmony_ci resRbo.gen(); 828e5c31af7Sopenharmony_ci 829e5c31af7Sopenharmony_ci gl.bindRenderbuffer(GL_RENDERBUFFER, *resRbo); 830e5c31af7Sopenharmony_ci gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 0, fboFormat, viewportSize.x(), viewportSize.y()); 831e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *resFbo); 832e5c31af7Sopenharmony_ci gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *resRbo); 833e5c31af7Sopenharmony_ci TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); 834e5c31af7Sopenharmony_ci 835e5c31af7Sopenharmony_ci gl.blitFramebuffer(0, 0, viewportSize.x(), viewportSize.y(), 0, 0, viewportSize.x(), viewportSize.y(), GL_COLOR_BUFFER_BIT, GL_NEAREST); 836e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Resolve blit"); 837e5c31af7Sopenharmony_ci 838e5c31af7Sopenharmony_ci gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *resFbo); 839e5c31af7Sopenharmony_ci } 840e5c31af7Sopenharmony_ci 841e5c31af7Sopenharmony_ci switch (m_surfaceType) 842e5c31af7Sopenharmony_ci { 843e5c31af7Sopenharmony_ci case SURFACETYPE_DEFAULT_FRAMEBUFFER: 844e5c31af7Sopenharmony_ci case SURFACETYPE_UNORM_FBO: 845e5c31af7Sopenharmony_ci result.setStorage(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), viewportSize.x(), viewportSize.y()); 846e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, result); 847e5c31af7Sopenharmony_ci break; 848e5c31af7Sopenharmony_ci 849e5c31af7Sopenharmony_ci case SURFACETYPE_FLOAT_FBO: 850e5c31af7Sopenharmony_ci { 851e5c31af7Sopenharmony_ci const tcu::TextureFormat dataFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT); 852e5c31af7Sopenharmony_ci const tcu::TextureFormat transferFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32); 853e5c31af7Sopenharmony_ci 854e5c31af7Sopenharmony_ci result.setStorage(dataFormat, viewportSize.x(), viewportSize.y()); 855e5c31af7Sopenharmony_ci glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, 856e5c31af7Sopenharmony_ci tcu::PixelBufferAccess(transferFormat, result.getWidth(), result.getHeight(), result.getDepth(), result.getAccess().getDataPtr())); 857e5c31af7Sopenharmony_ci break; 858e5c31af7Sopenharmony_ci } 859e5c31af7Sopenharmony_ci 860e5c31af7Sopenharmony_ci default: 861e5c31af7Sopenharmony_ci DE_ASSERT(false); 862e5c31af7Sopenharmony_ci } 863e5c31af7Sopenharmony_ci 864e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels"); 865e5c31af7Sopenharmony_ci } 866e5c31af7Sopenharmony_ci 867e5c31af7Sopenharmony_ci // Verify 868e5c31af7Sopenharmony_ci { 869e5c31af7Sopenharmony_ci tcu::Surface errorMask(result.getWidth(), result.getHeight()); 870e5c31af7Sopenharmony_ci tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec()); 871e5c31af7Sopenharmony_ci 872e5c31af7Sopenharmony_ci const qpTestResult testResult = verify(result.getAccess(), errorMask.getAccess()); 873e5c31af7Sopenharmony_ci const char* failStr = "Fail"; 874e5c31af7Sopenharmony_ci 875e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::ImageSet("Result", "Result images") 876e5c31af7Sopenharmony_ci << TestLog::Image("Rendered", "Rendered image", result); 877e5c31af7Sopenharmony_ci 878e5c31af7Sopenharmony_ci if (testResult != QP_TEST_RESULT_PASS) 879e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::Image("ErrorMask", "Error mask", errorMask); 880e5c31af7Sopenharmony_ci 881e5c31af7Sopenharmony_ci m_testCtx.getLog() << TestLog::EndImageSet; 882e5c31af7Sopenharmony_ci 883e5c31af7Sopenharmony_ci if (testResult == QP_TEST_RESULT_PASS) 884e5c31af7Sopenharmony_ci failStr = "Pass"; 885e5c31af7Sopenharmony_ci else if (testResult == QP_TEST_RESULT_QUALITY_WARNING) 886e5c31af7Sopenharmony_ci failStr = "QualityWarning"; 887e5c31af7Sopenharmony_ci 888e5c31af7Sopenharmony_ci m_testCtx.setTestResult(testResult, failStr); 889e5c31af7Sopenharmony_ci 890e5c31af7Sopenharmony_ci } 891e5c31af7Sopenharmony_ci 892e5c31af7Sopenharmony_ci return STOP; 893e5c31af7Sopenharmony_ci} 894e5c31af7Sopenharmony_ci 895e5c31af7Sopenharmony_citcu::Vec4 TriangleDerivateCase::getSurfaceThreshold (void) const 896e5c31af7Sopenharmony_ci{ 897e5c31af7Sopenharmony_ci switch (m_surfaceType) 898e5c31af7Sopenharmony_ci { 899e5c31af7Sopenharmony_ci case SURFACETYPE_DEFAULT_FRAMEBUFFER: 900e5c31af7Sopenharmony_ci { 901e5c31af7Sopenharmony_ci const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 902e5c31af7Sopenharmony_ci const tcu::IVec4 channelBits (pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits, pixelFormat.alphaBits); 903e5c31af7Sopenharmony_ci const tcu::IVec4 intThreshold = tcu::IVec4(1) << (8 - channelBits); 904e5c31af7Sopenharmony_ci const tcu::Vec4 normThreshold = intThreshold.asFloat() / 255.0f; 905e5c31af7Sopenharmony_ci 906e5c31af7Sopenharmony_ci return normThreshold; 907e5c31af7Sopenharmony_ci } 908e5c31af7Sopenharmony_ci 909e5c31af7Sopenharmony_ci case SURFACETYPE_UNORM_FBO: return tcu::IVec4(1).asFloat() / 255.0f; 910e5c31af7Sopenharmony_ci case SURFACETYPE_FLOAT_FBO: return tcu::Vec4(0.0f); 911e5c31af7Sopenharmony_ci default: 912e5c31af7Sopenharmony_ci DE_ASSERT(false); 913e5c31af7Sopenharmony_ci return tcu::Vec4(0.0f); 914e5c31af7Sopenharmony_ci } 915e5c31af7Sopenharmony_ci} 916e5c31af7Sopenharmony_ci 917e5c31af7Sopenharmony_ci// ConstantDerivateCase 918e5c31af7Sopenharmony_ci 919e5c31af7Sopenharmony_ciclass ConstantDerivateCase : public TriangleDerivateCase 920e5c31af7Sopenharmony_ci{ 921e5c31af7Sopenharmony_cipublic: 922e5c31af7Sopenharmony_ci ConstantDerivateCase (Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type); 923e5c31af7Sopenharmony_ci ~ConstantDerivateCase (void) {} 924e5c31af7Sopenharmony_ci 925e5c31af7Sopenharmony_ci void init (void); 926e5c31af7Sopenharmony_ci 927e5c31af7Sopenharmony_ciprotected: 928e5c31af7Sopenharmony_ci qpTestResult verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask); 929e5c31af7Sopenharmony_ci 930e5c31af7Sopenharmony_ciprivate: 931e5c31af7Sopenharmony_ci DerivateFunc m_func; 932e5c31af7Sopenharmony_ci}; 933e5c31af7Sopenharmony_ci 934e5c31af7Sopenharmony_ciConstantDerivateCase::ConstantDerivateCase (Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type) 935e5c31af7Sopenharmony_ci : TriangleDerivateCase (context, name, description) 936e5c31af7Sopenharmony_ci , m_func (func) 937e5c31af7Sopenharmony_ci{ 938e5c31af7Sopenharmony_ci m_dataType = type; 939e5c31af7Sopenharmony_ci m_precision = glu::PRECISION_HIGHP; 940e5c31af7Sopenharmony_ci m_coordDataType = m_dataType; 941e5c31af7Sopenharmony_ci m_coordPrecision = m_precision; 942e5c31af7Sopenharmony_ci} 943e5c31af7Sopenharmony_ci 944e5c31af7Sopenharmony_civoid ConstantDerivateCase::init (void) 945e5c31af7Sopenharmony_ci{ 946e5c31af7Sopenharmony_ci const char* fragmentTmpl = 947e5c31af7Sopenharmony_ci "#version 300 es\n" 948e5c31af7Sopenharmony_ci "layout(location = 0) out mediump vec4 o_color;\n" 949e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 950e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 951e5c31af7Sopenharmony_ci "void main (void)\n" 952e5c31af7Sopenharmony_ci "{\n" 953e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res = ${FUNC}(${VALUE}) * u_scale + u_bias;\n" 954e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 955e5c31af7Sopenharmony_ci "}\n"; 956e5c31af7Sopenharmony_ci map<string, string> fragmentParams; 957e5c31af7Sopenharmony_ci fragmentParams["PRECISION"] = glu::getPrecisionName(m_precision); 958e5c31af7Sopenharmony_ci fragmentParams["DATATYPE"] = glu::getDataTypeName(m_dataType); 959e5c31af7Sopenharmony_ci fragmentParams["FUNC"] = getDerivateFuncName(m_func); 960e5c31af7Sopenharmony_ci fragmentParams["VALUE"] = m_dataType == glu::TYPE_FLOAT_VEC4 ? "vec4(1.0, 7.2, -1e5, 0.0)" : 961e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec3(1e2, 8.0, 0.01)" : 962e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec2(-0.0, 2.7)" : 963e5c31af7Sopenharmony_ci /* TYPE_FLOAT */ "7.7"; 964e5c31af7Sopenharmony_ci fragmentParams["CAST_TO_OUTPUT"] = m_dataType == glu::TYPE_FLOAT_VEC4 ? "res" : 965e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec4(res, 1.0)" : 966e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec4(res, 0.0, 1.0)" : 967e5c31af7Sopenharmony_ci /* TYPE_FLOAT */ "vec4(res, 0.0, 0.0, 1.0)"; 968e5c31af7Sopenharmony_ci 969e5c31af7Sopenharmony_ci m_fragmentSrc = tcu::StringTemplate(fragmentTmpl).specialize(fragmentParams); 970e5c31af7Sopenharmony_ci 971e5c31af7Sopenharmony_ci m_derivScale = tcu::Vec4(1e3f, 1e3f, 1e3f, 1e3f); 972e5c31af7Sopenharmony_ci m_derivBias = tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f); 973e5c31af7Sopenharmony_ci} 974e5c31af7Sopenharmony_ci 975e5c31af7Sopenharmony_ciqpTestResult ConstantDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) 976e5c31af7Sopenharmony_ci{ 977e5c31af7Sopenharmony_ci const tcu::Vec4 reference (0.0f); // Derivate of constant argument should always be 0 978e5c31af7Sopenharmony_ci const tcu::Vec4 threshold = getSurfaceThreshold() / abs(m_derivScale); 979e5c31af7Sopenharmony_ci 980e5c31af7Sopenharmony_ci return verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, 981e5c31af7Sopenharmony_ci reference, threshold, m_derivScale, m_derivBias); 982e5c31af7Sopenharmony_ci} 983e5c31af7Sopenharmony_ci 984e5c31af7Sopenharmony_ci// LinearDerivateCase 985e5c31af7Sopenharmony_ci 986e5c31af7Sopenharmony_ciclass LinearDerivateCase : public TriangleDerivateCase 987e5c31af7Sopenharmony_ci{ 988e5c31af7Sopenharmony_cipublic: 989e5c31af7Sopenharmony_ci LinearDerivateCase (Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type, glu::Precision precision, deUint32 hint, SurfaceType surfaceType, int numSamples, const char* fragmentSrcTmpl); 990e5c31af7Sopenharmony_ci ~LinearDerivateCase (void) {} 991e5c31af7Sopenharmony_ci 992e5c31af7Sopenharmony_ci void init (void); 993e5c31af7Sopenharmony_ci 994e5c31af7Sopenharmony_ciprotected: 995e5c31af7Sopenharmony_ci qpTestResult verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask); 996e5c31af7Sopenharmony_ci 997e5c31af7Sopenharmony_ciprivate: 998e5c31af7Sopenharmony_ci DerivateFunc m_func; 999e5c31af7Sopenharmony_ci std::string m_fragmentTmpl; 1000e5c31af7Sopenharmony_ci}; 1001e5c31af7Sopenharmony_ci 1002e5c31af7Sopenharmony_ciLinearDerivateCase::LinearDerivateCase (Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type, glu::Precision precision, deUint32 hint, SurfaceType surfaceType, int numSamples, const char* fragmentSrcTmpl) 1003e5c31af7Sopenharmony_ci : TriangleDerivateCase (context, name, description) 1004e5c31af7Sopenharmony_ci , m_func (func) 1005e5c31af7Sopenharmony_ci , m_fragmentTmpl (fragmentSrcTmpl) 1006e5c31af7Sopenharmony_ci{ 1007e5c31af7Sopenharmony_ci m_dataType = type; 1008e5c31af7Sopenharmony_ci m_precision = precision; 1009e5c31af7Sopenharmony_ci m_coordDataType = m_dataType; 1010e5c31af7Sopenharmony_ci m_coordPrecision = m_precision; 1011e5c31af7Sopenharmony_ci m_hint = hint; 1012e5c31af7Sopenharmony_ci m_surfaceType = surfaceType; 1013e5c31af7Sopenharmony_ci m_numSamples = numSamples; 1014e5c31af7Sopenharmony_ci m_useAsymmetricCoords = true; 1015e5c31af7Sopenharmony_ci} 1016e5c31af7Sopenharmony_ci 1017e5c31af7Sopenharmony_civoid LinearDerivateCase::init (void) 1018e5c31af7Sopenharmony_ci{ 1019e5c31af7Sopenharmony_ci const tcu::IVec2 viewportSize = getViewportSize(); 1020e5c31af7Sopenharmony_ci const float w = float(viewportSize.x()); 1021e5c31af7Sopenharmony_ci const float h = float(viewportSize.y()); 1022e5c31af7Sopenharmony_ci const bool packToInt = m_surfaceType == SURFACETYPE_FLOAT_FBO; 1023e5c31af7Sopenharmony_ci map<string, string> fragmentParams; 1024e5c31af7Sopenharmony_ci 1025e5c31af7Sopenharmony_ci fragmentParams["OUTPUT_TYPE"] = glu::getDataTypeName(packToInt ? glu::TYPE_UINT_VEC4 : glu::TYPE_FLOAT_VEC4); 1026e5c31af7Sopenharmony_ci fragmentParams["OUTPUT_PREC"] = glu::getPrecisionName(packToInt ? glu::PRECISION_HIGHP : m_precision); 1027e5c31af7Sopenharmony_ci fragmentParams["PRECISION"] = glu::getPrecisionName(m_precision); 1028e5c31af7Sopenharmony_ci fragmentParams["DATATYPE"] = glu::getDataTypeName(m_dataType); 1029e5c31af7Sopenharmony_ci fragmentParams["FUNC"] = getDerivateFuncName(m_func); 1030e5c31af7Sopenharmony_ci 1031e5c31af7Sopenharmony_ci if (packToInt) 1032e5c31af7Sopenharmony_ci { 1033e5c31af7Sopenharmony_ci fragmentParams["CAST_TO_OUTPUT"] = m_dataType == glu::TYPE_FLOAT_VEC4 ? "floatBitsToUint(res)" : 1034e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC3 ? "floatBitsToUint(vec4(res, 1.0))" : 1035e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC2 ? "floatBitsToUint(vec4(res, 0.0, 1.0))" : 1036e5c31af7Sopenharmony_ci /* TYPE_FLOAT */ "floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))"; 1037e5c31af7Sopenharmony_ci } 1038e5c31af7Sopenharmony_ci else 1039e5c31af7Sopenharmony_ci { 1040e5c31af7Sopenharmony_ci fragmentParams["CAST_TO_OUTPUT"] = m_dataType == glu::TYPE_FLOAT_VEC4 ? "res" : 1041e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec4(res, 1.0)" : 1042e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec4(res, 0.0, 1.0)" : 1043e5c31af7Sopenharmony_ci /* TYPE_FLOAT */ "vec4(res, 0.0, 0.0, 1.0)"; 1044e5c31af7Sopenharmony_ci } 1045e5c31af7Sopenharmony_ci 1046e5c31af7Sopenharmony_ci m_fragmentSrc = tcu::StringTemplate(m_fragmentTmpl.c_str()).specialize(fragmentParams); 1047e5c31af7Sopenharmony_ci 1048e5c31af7Sopenharmony_ci switch (m_precision) 1049e5c31af7Sopenharmony_ci { 1050e5c31af7Sopenharmony_ci case glu::PRECISION_HIGHP: 1051e5c31af7Sopenharmony_ci m_coordMin = tcu::Vec4(-97.f, 0.2f, 71.f, 74.f); 1052e5c31af7Sopenharmony_ci m_coordMax = tcu::Vec4(-13.2f, -77.f, 44.f, 76.f); 1053e5c31af7Sopenharmony_ci break; 1054e5c31af7Sopenharmony_ci 1055e5c31af7Sopenharmony_ci case glu::PRECISION_MEDIUMP: 1056e5c31af7Sopenharmony_ci m_coordMin = tcu::Vec4(-37.0f, 47.f, -7.f, 0.0f); 1057e5c31af7Sopenharmony_ci m_coordMax = tcu::Vec4(-1.0f, 12.f, 7.f, 19.f); 1058e5c31af7Sopenharmony_ci break; 1059e5c31af7Sopenharmony_ci 1060e5c31af7Sopenharmony_ci case glu::PRECISION_LOWP: 1061e5c31af7Sopenharmony_ci m_coordMin = tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f); 1062e5c31af7Sopenharmony_ci m_coordMax = tcu::Vec4(1.0f, 1.0f, -1.0f, -1.0f); 1063e5c31af7Sopenharmony_ci break; 1064e5c31af7Sopenharmony_ci 1065e5c31af7Sopenharmony_ci default: 1066e5c31af7Sopenharmony_ci DE_ASSERT(false); 1067e5c31af7Sopenharmony_ci } 1068e5c31af7Sopenharmony_ci 1069e5c31af7Sopenharmony_ci if (m_surfaceType == SURFACETYPE_FLOAT_FBO) 1070e5c31af7Sopenharmony_ci { 1071e5c31af7Sopenharmony_ci // No scale or bias used for accuracy. 1072e5c31af7Sopenharmony_ci m_derivScale = tcu::Vec4(1.0f); 1073e5c31af7Sopenharmony_ci m_derivBias = tcu::Vec4(0.0f); 1074e5c31af7Sopenharmony_ci } 1075e5c31af7Sopenharmony_ci else 1076e5c31af7Sopenharmony_ci { 1077e5c31af7Sopenharmony_ci // Compute scale - bias that normalizes to 0..1 range. 1078e5c31af7Sopenharmony_ci const tcu::Vec4 dx = (m_coordMax - m_coordMin) / tcu::Vec4(w, w, w*0.5f, -w*0.5f); 1079e5c31af7Sopenharmony_ci const tcu::Vec4 dy = (m_coordMax - m_coordMin) / tcu::Vec4(h, h, h*0.5f, -h*0.5f); 1080e5c31af7Sopenharmony_ci 1081e5c31af7Sopenharmony_ci switch (m_func) 1082e5c31af7Sopenharmony_ci { 1083e5c31af7Sopenharmony_ci case DERIVATE_DFDX: 1084e5c31af7Sopenharmony_ci m_derivScale = 0.5f / dx; 1085e5c31af7Sopenharmony_ci break; 1086e5c31af7Sopenharmony_ci 1087e5c31af7Sopenharmony_ci case DERIVATE_DFDY: 1088e5c31af7Sopenharmony_ci m_derivScale = 0.5f / dy; 1089e5c31af7Sopenharmony_ci break; 1090e5c31af7Sopenharmony_ci 1091e5c31af7Sopenharmony_ci case DERIVATE_FWIDTH: 1092e5c31af7Sopenharmony_ci m_derivScale = 0.5f / (tcu::abs(dx) + tcu::abs(dy)); 1093e5c31af7Sopenharmony_ci break; 1094e5c31af7Sopenharmony_ci 1095e5c31af7Sopenharmony_ci default: 1096e5c31af7Sopenharmony_ci DE_ASSERT(false); 1097e5c31af7Sopenharmony_ci } 1098e5c31af7Sopenharmony_ci 1099e5c31af7Sopenharmony_ci m_derivBias = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); 1100e5c31af7Sopenharmony_ci } 1101e5c31af7Sopenharmony_ci} 1102e5c31af7Sopenharmony_ci 1103e5c31af7Sopenharmony_ciqpTestResult LinearDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) 1104e5c31af7Sopenharmony_ci{ 1105e5c31af7Sopenharmony_ci const tcu::Vec4 xScale = tcu::Vec4(0.5f, 0.5f, 0.5f, -0.5f); 1106e5c31af7Sopenharmony_ci const tcu::Vec4 yScale = tcu::Vec4(0.5f, 0.5f, 0.5f, -0.5f); 1107e5c31af7Sopenharmony_ci 1108e5c31af7Sopenharmony_ci const tcu::Vec4 surfaceThreshold = getSurfaceThreshold() / abs(m_derivScale); 1109e5c31af7Sopenharmony_ci 1110e5c31af7Sopenharmony_ci if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY) 1111e5c31af7Sopenharmony_ci { 1112e5c31af7Sopenharmony_ci const bool isX = m_func == DERIVATE_DFDX; 1113e5c31af7Sopenharmony_ci const float div = isX ? float(result.getWidth()) : float(result.getHeight()); 1114e5c31af7Sopenharmony_ci const tcu::Vec4 scale = isX ? xScale : yScale; 1115e5c31af7Sopenharmony_ci tcu::Vec4 reference = ((m_coordMax - m_coordMin) / div); 1116e5c31af7Sopenharmony_ci const tcu::Vec4 opThreshold = getDerivateThreshold(m_precision, m_coordMin, m_coordMax, reference); 1117e5c31af7Sopenharmony_ci const tcu::Vec4 opThresholdW = getDerivateThresholdWarning(m_precision, m_coordMin, m_coordMax, reference); 1118e5c31af7Sopenharmony_ci const tcu::Vec4 threshold = max(surfaceThreshold, opThreshold); 1119e5c31af7Sopenharmony_ci const tcu::Vec4 thresholdW = max(surfaceThreshold, opThresholdW); 1120e5c31af7Sopenharmony_ci const int numComps = glu::getDataTypeFloatScalars(m_dataType); 1121e5c31af7Sopenharmony_ci 1122e5c31af7Sopenharmony_ci /* adjust the reference value for the correct dfdx or dfdy sample adjacency */ 1123e5c31af7Sopenharmony_ci reference = reference * scale; 1124e5c31af7Sopenharmony_ci 1125e5c31af7Sopenharmony_ci m_testCtx.getLog() 1126e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1127e5c31af7Sopenharmony_ci << "Verifying result image.\n" 1128e5c31af7Sopenharmony_ci << "\tValid derivative is " << LogVecComps(reference, numComps) << " with threshold " << LogVecComps(threshold, numComps) 1129e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1130e5c31af7Sopenharmony_ci 1131e5c31af7Sopenharmony_ci // short circuit if result is strictly within the normal value error bounds. 1132e5c31af7Sopenharmony_ci // This improves performance significantly. 1133e5c31af7Sopenharmony_ci if (verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, 1134e5c31af7Sopenharmony_ci reference, threshold, m_derivScale, m_derivBias, 1135e5c31af7Sopenharmony_ci LOG_NOTHING) == QP_TEST_RESULT_PASS) 1136e5c31af7Sopenharmony_ci { 1137e5c31af7Sopenharmony_ci m_testCtx.getLog() 1138e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1139e5c31af7Sopenharmony_ci << "No incorrect derivatives found, result valid." 1140e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1141e5c31af7Sopenharmony_ci 1142e5c31af7Sopenharmony_ci return QP_TEST_RESULT_PASS; 1143e5c31af7Sopenharmony_ci } 1144e5c31af7Sopenharmony_ci 1145e5c31af7Sopenharmony_ci // Check with relaxed threshold value 1146e5c31af7Sopenharmony_ci if (verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, 1147e5c31af7Sopenharmony_ci reference, thresholdW, m_derivScale, m_derivBias, 1148e5c31af7Sopenharmony_ci LOG_NOTHING) == QP_TEST_RESULT_PASS) 1149e5c31af7Sopenharmony_ci { 1150e5c31af7Sopenharmony_ci m_testCtx.getLog() 1151e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1152e5c31af7Sopenharmony_ci << "No incorrect derivatives found, result valid with quality warning." 1153e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1154e5c31af7Sopenharmony_ci 1155e5c31af7Sopenharmony_ci return QP_TEST_RESULT_QUALITY_WARNING; 1156e5c31af7Sopenharmony_ci } 1157e5c31af7Sopenharmony_ci 1158e5c31af7Sopenharmony_ci // some pixels exceed error bounds calculated for normal values. Verify that these 1159e5c31af7Sopenharmony_ci // potentially invalid pixels are in fact valid due to (for example) subnorm flushing. 1160e5c31af7Sopenharmony_ci 1161e5c31af7Sopenharmony_ci m_testCtx.getLog() 1162e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1163e5c31af7Sopenharmony_ci << "Initial verification failed, verifying image by calculating accurate error bounds for each result pixel.\n" 1164e5c31af7Sopenharmony_ci << "\tVerifying each result derivative is within its range of legal result values." 1165e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1166e5c31af7Sopenharmony_ci 1167e5c31af7Sopenharmony_ci { 1168e5c31af7Sopenharmony_ci const tcu::IVec2 viewportSize = getViewportSize(); 1169e5c31af7Sopenharmony_ci const float w = float(viewportSize.x()); 1170e5c31af7Sopenharmony_ci const float h = float(viewportSize.y()); 1171e5c31af7Sopenharmony_ci const tcu::Vec4 valueRamp = (m_coordMax - m_coordMin); 1172e5c31af7Sopenharmony_ci Linear2DFunctionEvaluator function; 1173e5c31af7Sopenharmony_ci 1174e5c31af7Sopenharmony_ci function.matrix.setRow(0, tcu::Vec3((valueRamp.x() / w) / 2.0f, (valueRamp.x() / h) / 2.0f, m_coordMin.x())); 1175e5c31af7Sopenharmony_ci function.matrix.setRow(1, tcu::Vec3((valueRamp.y() / w) / 2.0f, (valueRamp.y() / h) / 2.0f, m_coordMin.y())); 1176e5c31af7Sopenharmony_ci function.matrix.setRow(2, tcu::Vec3(valueRamp.z() / w, valueRamp.z() / h, m_coordMin.z() + m_coordMin.z()) / 2.0f); 1177e5c31af7Sopenharmony_ci function.matrix.setRow(3, tcu::Vec3(-valueRamp.w() / w, -valueRamp.w() / h, m_coordMax.w() + m_coordMax.w()) / 2.0f); 1178e5c31af7Sopenharmony_ci 1179e5c31af7Sopenharmony_ci return reverifyConstantDerivateWithFlushRelaxations(m_testCtx.getLog(), result, errorMask, 1180e5c31af7Sopenharmony_ci m_dataType, m_precision, m_derivScale, 1181e5c31af7Sopenharmony_ci m_derivBias, surfaceThreshold, m_func, 1182e5c31af7Sopenharmony_ci function); 1183e5c31af7Sopenharmony_ci } 1184e5c31af7Sopenharmony_ci } 1185e5c31af7Sopenharmony_ci else 1186e5c31af7Sopenharmony_ci { 1187e5c31af7Sopenharmony_ci DE_ASSERT(m_func == DERIVATE_FWIDTH); 1188e5c31af7Sopenharmony_ci const float w = float(result.getWidth()); 1189e5c31af7Sopenharmony_ci const float h = float(result.getHeight()); 1190e5c31af7Sopenharmony_ci 1191e5c31af7Sopenharmony_ci const tcu::Vec4 dx = ((m_coordMax - m_coordMin) / w) * xScale; 1192e5c31af7Sopenharmony_ci const tcu::Vec4 dy = ((m_coordMax - m_coordMin) / h) * yScale; 1193e5c31af7Sopenharmony_ci const tcu::Vec4 reference = tcu::abs(dx) + tcu::abs(dy); 1194e5c31af7Sopenharmony_ci const tcu::Vec4 dxThreshold = getDerivateThreshold(m_precision, m_coordMin*xScale, m_coordMax*xScale, dx); 1195e5c31af7Sopenharmony_ci const tcu::Vec4 dyThreshold = getDerivateThreshold(m_precision, m_coordMin*yScale, m_coordMax*yScale, dy); 1196e5c31af7Sopenharmony_ci const tcu::Vec4 dxThresholdW = getDerivateThresholdWarning(m_precision, m_coordMin*xScale, m_coordMax*xScale, dx); 1197e5c31af7Sopenharmony_ci const tcu::Vec4 dyThresholdW = getDerivateThresholdWarning(m_precision, m_coordMin*yScale, m_coordMax*yScale, dy); 1198e5c31af7Sopenharmony_ci const tcu::Vec4 threshold = max(surfaceThreshold, max(dxThreshold, dyThreshold)); 1199e5c31af7Sopenharmony_ci const tcu::Vec4 thresholdW = max(surfaceThreshold, max(dxThresholdW, dyThresholdW)); 1200e5c31af7Sopenharmony_ci qpTestResult testResult = QP_TEST_RESULT_FAIL; 1201e5c31af7Sopenharmony_ci 1202e5c31af7Sopenharmony_ci testResult = verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, 1203e5c31af7Sopenharmony_ci reference, threshold, m_derivScale, m_derivBias); 1204e5c31af7Sopenharmony_ci 1205e5c31af7Sopenharmony_ci // return if result is pass 1206e5c31af7Sopenharmony_ci if (testResult == QP_TEST_RESULT_PASS) 1207e5c31af7Sopenharmony_ci return testResult; 1208e5c31af7Sopenharmony_ci 1209e5c31af7Sopenharmony_ci // re-check with relaxed threshold 1210e5c31af7Sopenharmony_ci testResult = verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, 1211e5c31af7Sopenharmony_ci reference, thresholdW, m_derivScale, m_derivBias); 1212e5c31af7Sopenharmony_ci 1213e5c31af7Sopenharmony_ci // if with relaxed threshold test is passing then mark the result with quality warning. 1214e5c31af7Sopenharmony_ci if (testResult == QP_TEST_RESULT_PASS) 1215e5c31af7Sopenharmony_ci testResult = QP_TEST_RESULT_QUALITY_WARNING; 1216e5c31af7Sopenharmony_ci 1217e5c31af7Sopenharmony_ci return testResult; 1218e5c31af7Sopenharmony_ci } 1219e5c31af7Sopenharmony_ci} 1220e5c31af7Sopenharmony_ci 1221e5c31af7Sopenharmony_ci// TextureDerivateCase 1222e5c31af7Sopenharmony_ci 1223e5c31af7Sopenharmony_ciclass TextureDerivateCase : public TriangleDerivateCase 1224e5c31af7Sopenharmony_ci{ 1225e5c31af7Sopenharmony_cipublic: 1226e5c31af7Sopenharmony_ci TextureDerivateCase (Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type, glu::Precision precision, deUint32 hint, SurfaceType surfaceType, int numSamples); 1227e5c31af7Sopenharmony_ci ~TextureDerivateCase (void); 1228e5c31af7Sopenharmony_ci 1229e5c31af7Sopenharmony_ci void init (void); 1230e5c31af7Sopenharmony_ci void deinit (void); 1231e5c31af7Sopenharmony_ci 1232e5c31af7Sopenharmony_ciprotected: 1233e5c31af7Sopenharmony_ci void setupRenderState (deUint32 program); 1234e5c31af7Sopenharmony_ci qpTestResult verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask); 1235e5c31af7Sopenharmony_ci 1236e5c31af7Sopenharmony_ciprivate: 1237e5c31af7Sopenharmony_ci DerivateFunc m_func; 1238e5c31af7Sopenharmony_ci 1239e5c31af7Sopenharmony_ci tcu::Vec4 m_texValueMin; 1240e5c31af7Sopenharmony_ci tcu::Vec4 m_texValueMax; 1241e5c31af7Sopenharmony_ci glu::Texture2D* m_texture; 1242e5c31af7Sopenharmony_ci}; 1243e5c31af7Sopenharmony_ci 1244e5c31af7Sopenharmony_ciTextureDerivateCase::TextureDerivateCase (Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type, glu::Precision precision, deUint32 hint, SurfaceType surfaceType, int numSamples) 1245e5c31af7Sopenharmony_ci : TriangleDerivateCase (context, name, description) 1246e5c31af7Sopenharmony_ci , m_func (func) 1247e5c31af7Sopenharmony_ci , m_texture (DE_NULL) 1248e5c31af7Sopenharmony_ci{ 1249e5c31af7Sopenharmony_ci m_dataType = type; 1250e5c31af7Sopenharmony_ci m_precision = precision; 1251e5c31af7Sopenharmony_ci m_coordDataType = glu::TYPE_FLOAT_VEC2; 1252e5c31af7Sopenharmony_ci m_coordPrecision = glu::PRECISION_HIGHP; 1253e5c31af7Sopenharmony_ci m_hint = hint; 1254e5c31af7Sopenharmony_ci m_surfaceType = surfaceType; 1255e5c31af7Sopenharmony_ci m_numSamples = numSamples; 1256e5c31af7Sopenharmony_ci} 1257e5c31af7Sopenharmony_ci 1258e5c31af7Sopenharmony_ciTextureDerivateCase::~TextureDerivateCase (void) 1259e5c31af7Sopenharmony_ci{ 1260e5c31af7Sopenharmony_ci delete m_texture; 1261e5c31af7Sopenharmony_ci} 1262e5c31af7Sopenharmony_ci 1263e5c31af7Sopenharmony_civoid TextureDerivateCase::init (void) 1264e5c31af7Sopenharmony_ci{ 1265e5c31af7Sopenharmony_ci // Generate shader 1266e5c31af7Sopenharmony_ci { 1267e5c31af7Sopenharmony_ci const char* fragmentTmpl = 1268e5c31af7Sopenharmony_ci "#version 300 es\n" 1269e5c31af7Sopenharmony_ci "in highp vec2 v_coord;\n" 1270e5c31af7Sopenharmony_ci "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n" 1271e5c31af7Sopenharmony_ci "uniform ${PRECISION} sampler2D u_sampler;\n" 1272e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 1273e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 1274e5c31af7Sopenharmony_ci "void main (void)\n" 1275e5c31af7Sopenharmony_ci "{\n" 1276e5c31af7Sopenharmony_ci " ${PRECISION} vec4 tex = texture(u_sampler, v_coord);\n" 1277e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res = ${FUNC}(tex${SWIZZLE}) * u_scale + u_bias;\n" 1278e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 1279e5c31af7Sopenharmony_ci "}\n"; 1280e5c31af7Sopenharmony_ci 1281e5c31af7Sopenharmony_ci const bool packToInt = m_surfaceType == SURFACETYPE_FLOAT_FBO; 1282e5c31af7Sopenharmony_ci map<string, string> fragmentParams; 1283e5c31af7Sopenharmony_ci 1284e5c31af7Sopenharmony_ci fragmentParams["OUTPUT_TYPE"] = glu::getDataTypeName(packToInt ? glu::TYPE_UINT_VEC4 : glu::TYPE_FLOAT_VEC4); 1285e5c31af7Sopenharmony_ci fragmentParams["OUTPUT_PREC"] = glu::getPrecisionName(packToInt ? glu::PRECISION_HIGHP : m_precision); 1286e5c31af7Sopenharmony_ci fragmentParams["PRECISION"] = glu::getPrecisionName(m_precision); 1287e5c31af7Sopenharmony_ci fragmentParams["DATATYPE"] = glu::getDataTypeName(m_dataType); 1288e5c31af7Sopenharmony_ci fragmentParams["FUNC"] = getDerivateFuncName(m_func); 1289e5c31af7Sopenharmony_ci fragmentParams["SWIZZLE"] = m_dataType == glu::TYPE_FLOAT_VEC4 ? "" : 1290e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC3 ? ".xyz" : 1291e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC2 ? ".xy" : 1292e5c31af7Sopenharmony_ci /* TYPE_FLOAT */ ".x"; 1293e5c31af7Sopenharmony_ci 1294e5c31af7Sopenharmony_ci if (packToInt) 1295e5c31af7Sopenharmony_ci { 1296e5c31af7Sopenharmony_ci fragmentParams["CAST_TO_OUTPUT"] = m_dataType == glu::TYPE_FLOAT_VEC4 ? "floatBitsToUint(res)" : 1297e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC3 ? "floatBitsToUint(vec4(res, 1.0))" : 1298e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC2 ? "floatBitsToUint(vec4(res, 0.0, 1.0))" : 1299e5c31af7Sopenharmony_ci /* TYPE_FLOAT */ "floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))"; 1300e5c31af7Sopenharmony_ci } 1301e5c31af7Sopenharmony_ci else 1302e5c31af7Sopenharmony_ci { 1303e5c31af7Sopenharmony_ci fragmentParams["CAST_TO_OUTPUT"] = m_dataType == glu::TYPE_FLOAT_VEC4 ? "res" : 1304e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec4(res, 1.0)" : 1305e5c31af7Sopenharmony_ci m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec4(res, 0.0, 1.0)" : 1306e5c31af7Sopenharmony_ci /* TYPE_FLOAT */ "vec4(res, 0.0, 0.0, 1.0)"; 1307e5c31af7Sopenharmony_ci } 1308e5c31af7Sopenharmony_ci 1309e5c31af7Sopenharmony_ci m_fragmentSrc = tcu::StringTemplate(fragmentTmpl).specialize(fragmentParams); 1310e5c31af7Sopenharmony_ci } 1311e5c31af7Sopenharmony_ci 1312e5c31af7Sopenharmony_ci // Texture size matches viewport and nearest sampling is used. Thus texture sampling 1313e5c31af7Sopenharmony_ci // is equal to just interpolating the texture value range. 1314e5c31af7Sopenharmony_ci 1315e5c31af7Sopenharmony_ci // Determine value range for texture. 1316e5c31af7Sopenharmony_ci 1317e5c31af7Sopenharmony_ci switch (m_precision) 1318e5c31af7Sopenharmony_ci { 1319e5c31af7Sopenharmony_ci case glu::PRECISION_HIGHP: 1320e5c31af7Sopenharmony_ci m_texValueMin = tcu::Vec4(-97.f, 0.2f, 71.f, 74.f); 1321e5c31af7Sopenharmony_ci m_texValueMax = tcu::Vec4(-13.2f, -77.f, 44.f, 76.f); 1322e5c31af7Sopenharmony_ci break; 1323e5c31af7Sopenharmony_ci 1324e5c31af7Sopenharmony_ci case glu::PRECISION_MEDIUMP: 1325e5c31af7Sopenharmony_ci m_texValueMin = tcu::Vec4(-37.0f, 47.f, -7.f, 0.0f); 1326e5c31af7Sopenharmony_ci m_texValueMax = tcu::Vec4(-1.0f, 12.f, 7.f, 19.f); 1327e5c31af7Sopenharmony_ci break; 1328e5c31af7Sopenharmony_ci 1329e5c31af7Sopenharmony_ci case glu::PRECISION_LOWP: 1330e5c31af7Sopenharmony_ci m_texValueMin = tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f); 1331e5c31af7Sopenharmony_ci m_texValueMax = tcu::Vec4(1.0f, 1.0f, -1.0f, -1.0f); 1332e5c31af7Sopenharmony_ci break; 1333e5c31af7Sopenharmony_ci 1334e5c31af7Sopenharmony_ci default: 1335e5c31af7Sopenharmony_ci DE_ASSERT(false); 1336e5c31af7Sopenharmony_ci } 1337e5c31af7Sopenharmony_ci 1338e5c31af7Sopenharmony_ci // Lowp and mediump cases use RGBA16F format, while highp uses RGBA32F. 1339e5c31af7Sopenharmony_ci { 1340e5c31af7Sopenharmony_ci const tcu::IVec2 viewportSize = getViewportSize(); 1341e5c31af7Sopenharmony_ci DE_ASSERT(!m_texture); 1342e5c31af7Sopenharmony_ci m_texture = new glu::Texture2D(m_context.getRenderContext(), m_precision == glu::PRECISION_HIGHP ? GL_RGBA32F : GL_RGBA16F, viewportSize.x(), viewportSize.y()); 1343e5c31af7Sopenharmony_ci m_texture->getRefTexture().allocLevel(0); 1344e5c31af7Sopenharmony_ci } 1345e5c31af7Sopenharmony_ci 1346e5c31af7Sopenharmony_ci // Texture coordinates 1347e5c31af7Sopenharmony_ci m_coordMin = tcu::Vec4(0.0f); 1348e5c31af7Sopenharmony_ci m_coordMax = tcu::Vec4(1.0f); 1349e5c31af7Sopenharmony_ci 1350e5c31af7Sopenharmony_ci // Fill with gradients. 1351e5c31af7Sopenharmony_ci { 1352e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess level0 = m_texture->getRefTexture().getLevel(0); 1353e5c31af7Sopenharmony_ci for (int y = 0; y < level0.getHeight(); y++) 1354e5c31af7Sopenharmony_ci { 1355e5c31af7Sopenharmony_ci for (int x = 0; x < level0.getWidth(); x++) 1356e5c31af7Sopenharmony_ci { 1357e5c31af7Sopenharmony_ci const float xf = (float(x)+0.5f) / float(level0.getWidth()); 1358e5c31af7Sopenharmony_ci const float yf = (float(y)+0.5f) / float(level0.getHeight()); 1359e5c31af7Sopenharmony_ci // Make x and y data to have dependency to both axes so that dfdx(tex).y and dfdy(tex).x are nonzero. 1360e5c31af7Sopenharmony_ci const tcu::Vec4 s = tcu::Vec4(xf + yf/2.0f, yf + xf/2.0f, (xf+yf)/2.0f, 1.0f - (xf+yf)/2.0f); 1361e5c31af7Sopenharmony_ci 1362e5c31af7Sopenharmony_ci level0.setPixel(m_texValueMin + (m_texValueMax - m_texValueMin)*s, x, y); 1363e5c31af7Sopenharmony_ci } 1364e5c31af7Sopenharmony_ci } 1365e5c31af7Sopenharmony_ci } 1366e5c31af7Sopenharmony_ci 1367e5c31af7Sopenharmony_ci m_texture->upload(); 1368e5c31af7Sopenharmony_ci 1369e5c31af7Sopenharmony_ci if (m_surfaceType == SURFACETYPE_FLOAT_FBO) 1370e5c31af7Sopenharmony_ci { 1371e5c31af7Sopenharmony_ci // No scale or bias used for accuracy. 1372e5c31af7Sopenharmony_ci m_derivScale = tcu::Vec4(1.0f); 1373e5c31af7Sopenharmony_ci m_derivBias = tcu::Vec4(0.0f); 1374e5c31af7Sopenharmony_ci } 1375e5c31af7Sopenharmony_ci else 1376e5c31af7Sopenharmony_ci { 1377e5c31af7Sopenharmony_ci // Compute scale - bias that normalizes to 0..1 range. 1378e5c31af7Sopenharmony_ci const tcu::IVec2 viewportSize = getViewportSize(); 1379e5c31af7Sopenharmony_ci const float w = float(viewportSize.x()); 1380e5c31af7Sopenharmony_ci const float h = float(viewportSize.y()); 1381e5c31af7Sopenharmony_ci const tcu::Vec4 dx = (m_texValueMax - m_texValueMin) / tcu::Vec4(w, w, w*0.5f, -w*0.5f); 1382e5c31af7Sopenharmony_ci const tcu::Vec4 dy = (m_texValueMax - m_texValueMin) / tcu::Vec4(h, h, h*0.5f, -h*0.5f); 1383e5c31af7Sopenharmony_ci 1384e5c31af7Sopenharmony_ci switch (m_func) 1385e5c31af7Sopenharmony_ci { 1386e5c31af7Sopenharmony_ci case DERIVATE_DFDX: 1387e5c31af7Sopenharmony_ci m_derivScale = 0.5f / dx; 1388e5c31af7Sopenharmony_ci break; 1389e5c31af7Sopenharmony_ci 1390e5c31af7Sopenharmony_ci case DERIVATE_DFDY: 1391e5c31af7Sopenharmony_ci m_derivScale = 0.5f / dy; 1392e5c31af7Sopenharmony_ci break; 1393e5c31af7Sopenharmony_ci 1394e5c31af7Sopenharmony_ci case DERIVATE_FWIDTH: 1395e5c31af7Sopenharmony_ci m_derivScale = 0.5f / (tcu::abs(dx) + tcu::abs(dy)); 1396e5c31af7Sopenharmony_ci break; 1397e5c31af7Sopenharmony_ci 1398e5c31af7Sopenharmony_ci default: 1399e5c31af7Sopenharmony_ci DE_ASSERT(false); 1400e5c31af7Sopenharmony_ci } 1401e5c31af7Sopenharmony_ci 1402e5c31af7Sopenharmony_ci m_derivBias = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); 1403e5c31af7Sopenharmony_ci } 1404e5c31af7Sopenharmony_ci} 1405e5c31af7Sopenharmony_ci 1406e5c31af7Sopenharmony_civoid TextureDerivateCase::deinit (void) 1407e5c31af7Sopenharmony_ci{ 1408e5c31af7Sopenharmony_ci delete m_texture; 1409e5c31af7Sopenharmony_ci m_texture = DE_NULL; 1410e5c31af7Sopenharmony_ci} 1411e5c31af7Sopenharmony_ci 1412e5c31af7Sopenharmony_civoid TextureDerivateCase::setupRenderState (deUint32 program) 1413e5c31af7Sopenharmony_ci{ 1414e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1415e5c31af7Sopenharmony_ci const int texUnit = 1; 1416e5c31af7Sopenharmony_ci 1417e5c31af7Sopenharmony_ci gl.activeTexture (GL_TEXTURE0+texUnit); 1418e5c31af7Sopenharmony_ci gl.bindTexture (GL_TEXTURE_2D, m_texture->getGLTexture()); 1419e5c31af7Sopenharmony_ci gl.texParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1420e5c31af7Sopenharmony_ci gl.texParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1421e5c31af7Sopenharmony_ci gl.texParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1422e5c31af7Sopenharmony_ci gl.texParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1423e5c31af7Sopenharmony_ci 1424e5c31af7Sopenharmony_ci gl.uniform1i (gl.getUniformLocation(program, "u_sampler"), texUnit); 1425e5c31af7Sopenharmony_ci} 1426e5c31af7Sopenharmony_ci 1427e5c31af7Sopenharmony_ciqpTestResult TextureDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) 1428e5c31af7Sopenharmony_ci{ 1429e5c31af7Sopenharmony_ci // \note Edges are ignored in comparison 1430e5c31af7Sopenharmony_ci if (result.getWidth() < 2 || result.getHeight() < 2) 1431e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Too small viewport"); 1432e5c31af7Sopenharmony_ci 1433e5c31af7Sopenharmony_ci tcu::ConstPixelBufferAccess compareArea = tcu::getSubregion(result, 1, 1, result.getWidth()-2, result.getHeight()-2); 1434e5c31af7Sopenharmony_ci tcu::PixelBufferAccess maskArea = tcu::getSubregion(errorMask, 1, 1, errorMask.getWidth()-2, errorMask.getHeight()-2); 1435e5c31af7Sopenharmony_ci const tcu::Vec4 xScale = tcu::Vec4(1.0f, 0.5f, 0.5f, -0.5f); 1436e5c31af7Sopenharmony_ci const tcu::Vec4 yScale = tcu::Vec4(0.5f, 1.0f, 0.5f, -0.5f); 1437e5c31af7Sopenharmony_ci const float w = float(result.getWidth()); 1438e5c31af7Sopenharmony_ci const float h = float(result.getHeight()); 1439e5c31af7Sopenharmony_ci 1440e5c31af7Sopenharmony_ci const tcu::Vec4 surfaceThreshold = getSurfaceThreshold() / abs(m_derivScale); 1441e5c31af7Sopenharmony_ci 1442e5c31af7Sopenharmony_ci if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY) 1443e5c31af7Sopenharmony_ci { 1444e5c31af7Sopenharmony_ci const bool isX = m_func == DERIVATE_DFDX; 1445e5c31af7Sopenharmony_ci const float div = isX ? w : h; 1446e5c31af7Sopenharmony_ci const tcu::Vec4 scale = isX ? xScale : yScale; 1447e5c31af7Sopenharmony_ci tcu::Vec4 reference = ((m_texValueMax - m_texValueMin) / div); 1448e5c31af7Sopenharmony_ci const tcu::Vec4 opThreshold = getDerivateThreshold(m_precision, m_texValueMin, m_texValueMax, reference); 1449e5c31af7Sopenharmony_ci const tcu::Vec4 opThresholdW = getDerivateThresholdWarning(m_precision, m_texValueMin, m_texValueMax, reference); 1450e5c31af7Sopenharmony_ci const tcu::Vec4 threshold = max(surfaceThreshold, opThreshold); 1451e5c31af7Sopenharmony_ci const tcu::Vec4 thresholdW = max(surfaceThreshold, opThresholdW); 1452e5c31af7Sopenharmony_ci const int numComps = glu::getDataTypeFloatScalars(m_dataType); 1453e5c31af7Sopenharmony_ci 1454e5c31af7Sopenharmony_ci /* adjust the reference value for the correct dfdx or dfdy sample adjacency */ 1455e5c31af7Sopenharmony_ci reference = reference * scale; 1456e5c31af7Sopenharmony_ci 1457e5c31af7Sopenharmony_ci m_testCtx.getLog() 1458e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1459e5c31af7Sopenharmony_ci << "Verifying result image.\n" 1460e5c31af7Sopenharmony_ci << "\tValid derivative is " << LogVecComps(reference, numComps) << " with threshold " << LogVecComps(threshold, numComps) 1461e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1462e5c31af7Sopenharmony_ci 1463e5c31af7Sopenharmony_ci // short circuit if result is strictly within the normal value error bounds. 1464e5c31af7Sopenharmony_ci // This improves performance significantly. 1465e5c31af7Sopenharmony_ci if (verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, 1466e5c31af7Sopenharmony_ci reference, threshold, m_derivScale, m_derivBias, 1467e5c31af7Sopenharmony_ci LOG_NOTHING) == QP_TEST_RESULT_PASS) 1468e5c31af7Sopenharmony_ci { 1469e5c31af7Sopenharmony_ci m_testCtx.getLog() 1470e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1471e5c31af7Sopenharmony_ci << "No incorrect derivatives found, result valid." 1472e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1473e5c31af7Sopenharmony_ci 1474e5c31af7Sopenharmony_ci return QP_TEST_RESULT_PASS; 1475e5c31af7Sopenharmony_ci } 1476e5c31af7Sopenharmony_ci 1477e5c31af7Sopenharmony_ci m_testCtx.getLog() 1478e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1479e5c31af7Sopenharmony_ci << "Verifying result image.\n" 1480e5c31af7Sopenharmony_ci << "\tValid derivative is " << LogVecComps(reference, numComps) << " with Warning threshold " << LogVecComps(thresholdW, numComps) 1481e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1482e5c31af7Sopenharmony_ci 1483e5c31af7Sopenharmony_ci // Re-check with relaxed threshold 1484e5c31af7Sopenharmony_ci if (verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, 1485e5c31af7Sopenharmony_ci reference, thresholdW, m_derivScale, m_derivBias, 1486e5c31af7Sopenharmony_ci LOG_NOTHING) == QP_TEST_RESULT_PASS) 1487e5c31af7Sopenharmony_ci { 1488e5c31af7Sopenharmony_ci m_testCtx.getLog() 1489e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1490e5c31af7Sopenharmony_ci << "No incorrect derivatives found, result valid with quality warning." 1491e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1492e5c31af7Sopenharmony_ci 1493e5c31af7Sopenharmony_ci return QP_TEST_RESULT_QUALITY_WARNING; 1494e5c31af7Sopenharmony_ci } 1495e5c31af7Sopenharmony_ci 1496e5c31af7Sopenharmony_ci 1497e5c31af7Sopenharmony_ci // some pixels exceed error bounds calculated for normal values. Verify that these 1498e5c31af7Sopenharmony_ci // potentially invalid pixels are in fact valid due to (for example) subnorm flushing. 1499e5c31af7Sopenharmony_ci 1500e5c31af7Sopenharmony_ci m_testCtx.getLog() 1501e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1502e5c31af7Sopenharmony_ci << "Initial verification failed, verifying image by calculating accurate error bounds for each result pixel.\n" 1503e5c31af7Sopenharmony_ci << "\tVerifying each result derivative is within its range of legal result values." 1504e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1505e5c31af7Sopenharmony_ci 1506e5c31af7Sopenharmony_ci { 1507e5c31af7Sopenharmony_ci const tcu::Vec4 valueRamp = (m_texValueMax - m_texValueMin); 1508e5c31af7Sopenharmony_ci Linear2DFunctionEvaluator function; 1509e5c31af7Sopenharmony_ci 1510e5c31af7Sopenharmony_ci function.matrix.setRow(0, tcu::Vec3(valueRamp.x() / w, (valueRamp.x() / h) / 2.0f, m_texValueMin.x())); 1511e5c31af7Sopenharmony_ci function.matrix.setRow(1, tcu::Vec3((valueRamp.y() / w) / 2.0f, valueRamp.y() / h, m_texValueMin.y())); 1512e5c31af7Sopenharmony_ci function.matrix.setRow(2, tcu::Vec3(valueRamp.z() / w, valueRamp.z() / h, m_texValueMin.z() + m_texValueMin.z()) / 2.0f); 1513e5c31af7Sopenharmony_ci function.matrix.setRow(3, tcu::Vec3(-valueRamp.w() / w, -valueRamp.w() / h, m_texValueMax.w() + m_texValueMax.w()) / 2.0f); 1514e5c31af7Sopenharmony_ci 1515e5c31af7Sopenharmony_ci return reverifyConstantDerivateWithFlushRelaxations(m_testCtx.getLog(), compareArea, maskArea, 1516e5c31af7Sopenharmony_ci m_dataType, m_precision, m_derivScale, 1517e5c31af7Sopenharmony_ci m_derivBias, surfaceThreshold, m_func, 1518e5c31af7Sopenharmony_ci function); 1519e5c31af7Sopenharmony_ci } 1520e5c31af7Sopenharmony_ci } 1521e5c31af7Sopenharmony_ci else 1522e5c31af7Sopenharmony_ci { 1523e5c31af7Sopenharmony_ci DE_ASSERT(m_func == DERIVATE_FWIDTH); 1524e5c31af7Sopenharmony_ci const tcu::Vec4 dx = ((m_texValueMax - m_texValueMin) / w) * xScale; 1525e5c31af7Sopenharmony_ci const tcu::Vec4 dy = ((m_texValueMax - m_texValueMin) / h) * yScale; 1526e5c31af7Sopenharmony_ci const tcu::Vec4 reference = tcu::abs(dx) + tcu::abs(dy); 1527e5c31af7Sopenharmony_ci const tcu::Vec4 dxThreshold = getDerivateThreshold(m_precision, m_texValueMin*xScale, m_texValueMax*xScale, dx); 1528e5c31af7Sopenharmony_ci const tcu::Vec4 dyThreshold = getDerivateThreshold(m_precision, m_texValueMin*yScale, m_texValueMax*yScale, dy); 1529e5c31af7Sopenharmony_ci const tcu::Vec4 dxThresholdW = getDerivateThresholdWarning(m_precision, m_texValueMin*xScale, m_texValueMax*xScale, dx); 1530e5c31af7Sopenharmony_ci const tcu::Vec4 dyThresholdW = getDerivateThresholdWarning(m_precision, m_texValueMin*yScale, m_texValueMax*yScale, dy); 1531e5c31af7Sopenharmony_ci const tcu::Vec4 threshold = max(surfaceThreshold, max(dxThreshold, dyThreshold)); 1532e5c31af7Sopenharmony_ci const tcu::Vec4 thresholdW = max(surfaceThreshold, max(dxThresholdW, dyThresholdW)); 1533e5c31af7Sopenharmony_ci qpTestResult testResult = QP_TEST_RESULT_FAIL; 1534e5c31af7Sopenharmony_ci 1535e5c31af7Sopenharmony_ci testResult = verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, 1536e5c31af7Sopenharmony_ci reference, threshold, m_derivScale, m_derivBias); 1537e5c31af7Sopenharmony_ci 1538e5c31af7Sopenharmony_ci if (testResult == QP_TEST_RESULT_PASS) 1539e5c31af7Sopenharmony_ci return testResult; 1540e5c31af7Sopenharmony_ci 1541e5c31af7Sopenharmony_ci // Re-Check with relaxed threshold 1542e5c31af7Sopenharmony_ci testResult = verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, 1543e5c31af7Sopenharmony_ci reference, thresholdW, m_derivScale, m_derivBias); 1544e5c31af7Sopenharmony_ci 1545e5c31af7Sopenharmony_ci // If test is passing with relaxed threshold then mark quality warning 1546e5c31af7Sopenharmony_ci if (testResult == QP_TEST_RESULT_PASS) 1547e5c31af7Sopenharmony_ci testResult = QP_TEST_RESULT_QUALITY_WARNING; 1548e5c31af7Sopenharmony_ci 1549e5c31af7Sopenharmony_ci return testResult; 1550e5c31af7Sopenharmony_ci } 1551e5c31af7Sopenharmony_ci} 1552e5c31af7Sopenharmony_ci 1553e5c31af7Sopenharmony_ciShaderDerivateTests::ShaderDerivateTests (Context& context) 1554e5c31af7Sopenharmony_ci : TestCaseGroup(context, "derivate", "Derivate Function Tests") 1555e5c31af7Sopenharmony_ci{ 1556e5c31af7Sopenharmony_ci} 1557e5c31af7Sopenharmony_ci 1558e5c31af7Sopenharmony_ciShaderDerivateTests::~ShaderDerivateTests (void) 1559e5c31af7Sopenharmony_ci{ 1560e5c31af7Sopenharmony_ci} 1561e5c31af7Sopenharmony_ci 1562e5c31af7Sopenharmony_cistruct FunctionSpec 1563e5c31af7Sopenharmony_ci{ 1564e5c31af7Sopenharmony_ci std::string name; 1565e5c31af7Sopenharmony_ci DerivateFunc function; 1566e5c31af7Sopenharmony_ci glu::DataType dataType; 1567e5c31af7Sopenharmony_ci glu::Precision precision; 1568e5c31af7Sopenharmony_ci 1569e5c31af7Sopenharmony_ci FunctionSpec (const std::string& name_, DerivateFunc function_, glu::DataType dataType_, glu::Precision precision_) 1570e5c31af7Sopenharmony_ci : name (name_) 1571e5c31af7Sopenharmony_ci , function (function_) 1572e5c31af7Sopenharmony_ci , dataType (dataType_) 1573e5c31af7Sopenharmony_ci , precision (precision_) 1574e5c31af7Sopenharmony_ci { 1575e5c31af7Sopenharmony_ci } 1576e5c31af7Sopenharmony_ci}; 1577e5c31af7Sopenharmony_ci 1578e5c31af7Sopenharmony_civoid ShaderDerivateTests::init (void) 1579e5c31af7Sopenharmony_ci{ 1580e5c31af7Sopenharmony_ci static const struct 1581e5c31af7Sopenharmony_ci { 1582e5c31af7Sopenharmony_ci const char* name; 1583e5c31af7Sopenharmony_ci const char* description; 1584e5c31af7Sopenharmony_ci const char* source; 1585e5c31af7Sopenharmony_ci } s_linearDerivateCases[] = 1586e5c31af7Sopenharmony_ci { 1587e5c31af7Sopenharmony_ci { 1588e5c31af7Sopenharmony_ci "linear", 1589e5c31af7Sopenharmony_ci "Basic derivate of linearly interpolated argument", 1590e5c31af7Sopenharmony_ci 1591e5c31af7Sopenharmony_ci "#version 300 es\n" 1592e5c31af7Sopenharmony_ci "in ${PRECISION} ${DATATYPE} v_coord;\n" 1593e5c31af7Sopenharmony_ci "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n" 1594e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 1595e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 1596e5c31af7Sopenharmony_ci "void main (void)\n" 1597e5c31af7Sopenharmony_ci "{\n" 1598e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res = ${FUNC}(v_coord) * u_scale + u_bias;\n" 1599e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 1600e5c31af7Sopenharmony_ci "}\n" 1601e5c31af7Sopenharmony_ci }, 1602e5c31af7Sopenharmony_ci { 1603e5c31af7Sopenharmony_ci "in_function", 1604e5c31af7Sopenharmony_ci "Derivate of linear function argument", 1605e5c31af7Sopenharmony_ci 1606e5c31af7Sopenharmony_ci "#version 300 es\n" 1607e5c31af7Sopenharmony_ci "in ${PRECISION} ${DATATYPE} v_coord;\n" 1608e5c31af7Sopenharmony_ci "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n" 1609e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 1610e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 1611e5c31af7Sopenharmony_ci "\n" 1612e5c31af7Sopenharmony_ci "${PRECISION} ${DATATYPE} computeRes (${PRECISION} ${DATATYPE} value)\n" 1613e5c31af7Sopenharmony_ci "{\n" 1614e5c31af7Sopenharmony_ci " return ${FUNC}(v_coord) * u_scale + u_bias;\n" 1615e5c31af7Sopenharmony_ci "}\n" 1616e5c31af7Sopenharmony_ci "\n" 1617e5c31af7Sopenharmony_ci "void main (void)\n" 1618e5c31af7Sopenharmony_ci "{\n" 1619e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res = computeRes(v_coord);\n" 1620e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 1621e5c31af7Sopenharmony_ci "}\n" 1622e5c31af7Sopenharmony_ci }, 1623e5c31af7Sopenharmony_ci { 1624e5c31af7Sopenharmony_ci "static_if", 1625e5c31af7Sopenharmony_ci "Derivate of linearly interpolated value in static if", 1626e5c31af7Sopenharmony_ci 1627e5c31af7Sopenharmony_ci "#version 300 es\n" 1628e5c31af7Sopenharmony_ci "in ${PRECISION} ${DATATYPE} v_coord;\n" 1629e5c31af7Sopenharmony_ci "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n" 1630e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 1631e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 1632e5c31af7Sopenharmony_ci "void main (void)\n" 1633e5c31af7Sopenharmony_ci "{\n" 1634e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res;\n" 1635e5c31af7Sopenharmony_ci " if (false)\n" 1636e5c31af7Sopenharmony_ci " res = ${FUNC}(-v_coord) * u_scale + u_bias;\n" 1637e5c31af7Sopenharmony_ci " else\n" 1638e5c31af7Sopenharmony_ci " res = ${FUNC}(v_coord) * u_scale + u_bias;\n" 1639e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 1640e5c31af7Sopenharmony_ci "}\n" 1641e5c31af7Sopenharmony_ci }, 1642e5c31af7Sopenharmony_ci { 1643e5c31af7Sopenharmony_ci "static_loop", 1644e5c31af7Sopenharmony_ci "Derivate of linearly interpolated value in static loop", 1645e5c31af7Sopenharmony_ci 1646e5c31af7Sopenharmony_ci "#version 300 es\n" 1647e5c31af7Sopenharmony_ci "in ${PRECISION} ${DATATYPE} v_coord;\n" 1648e5c31af7Sopenharmony_ci "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n" 1649e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 1650e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 1651e5c31af7Sopenharmony_ci "void main (void)\n" 1652e5c31af7Sopenharmony_ci "{\n" 1653e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n" 1654e5c31af7Sopenharmony_ci " for (int i = 0; i < 2; i++)\n" 1655e5c31af7Sopenharmony_ci " res += ${FUNC}(v_coord * float(i));\n" 1656e5c31af7Sopenharmony_ci " res = res * u_scale + u_bias;\n" 1657e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 1658e5c31af7Sopenharmony_ci "}\n" 1659e5c31af7Sopenharmony_ci }, 1660e5c31af7Sopenharmony_ci { 1661e5c31af7Sopenharmony_ci "static_switch", 1662e5c31af7Sopenharmony_ci "Derivate of linearly interpolated value in static switch", 1663e5c31af7Sopenharmony_ci 1664e5c31af7Sopenharmony_ci "#version 300 es\n" 1665e5c31af7Sopenharmony_ci "in ${PRECISION} ${DATATYPE} v_coord;\n" 1666e5c31af7Sopenharmony_ci "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n" 1667e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 1668e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 1669e5c31af7Sopenharmony_ci "void main (void)\n" 1670e5c31af7Sopenharmony_ci "{\n" 1671e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res;\n" 1672e5c31af7Sopenharmony_ci " switch (1)\n" 1673e5c31af7Sopenharmony_ci " {\n" 1674e5c31af7Sopenharmony_ci " case 0: res = ${FUNC}(-v_coord) * u_scale + u_bias; break;\n" 1675e5c31af7Sopenharmony_ci " case 1: res = ${FUNC}(v_coord) * u_scale + u_bias; break;\n" 1676e5c31af7Sopenharmony_ci " }\n" 1677e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 1678e5c31af7Sopenharmony_ci "}\n" 1679e5c31af7Sopenharmony_ci }, 1680e5c31af7Sopenharmony_ci { 1681e5c31af7Sopenharmony_ci "uniform_if", 1682e5c31af7Sopenharmony_ci "Derivate of linearly interpolated value in uniform if", 1683e5c31af7Sopenharmony_ci 1684e5c31af7Sopenharmony_ci "#version 300 es\n" 1685e5c31af7Sopenharmony_ci "in ${PRECISION} ${DATATYPE} v_coord;\n" 1686e5c31af7Sopenharmony_ci "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n" 1687e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 1688e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 1689e5c31af7Sopenharmony_ci "uniform bool ub_true;\n" 1690e5c31af7Sopenharmony_ci "void main (void)\n" 1691e5c31af7Sopenharmony_ci "{\n" 1692e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res;\n" 1693e5c31af7Sopenharmony_ci " if (ub_true)" 1694e5c31af7Sopenharmony_ci " res = ${FUNC}(v_coord) * u_scale + u_bias;\n" 1695e5c31af7Sopenharmony_ci " else\n" 1696e5c31af7Sopenharmony_ci " res = ${FUNC}(-v_coord) * u_scale + u_bias;\n" 1697e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 1698e5c31af7Sopenharmony_ci "}\n" 1699e5c31af7Sopenharmony_ci }, 1700e5c31af7Sopenharmony_ci { 1701e5c31af7Sopenharmony_ci "uniform_loop", 1702e5c31af7Sopenharmony_ci "Derivate of linearly interpolated value in uniform loop", 1703e5c31af7Sopenharmony_ci 1704e5c31af7Sopenharmony_ci "#version 300 es\n" 1705e5c31af7Sopenharmony_ci "in ${PRECISION} ${DATATYPE} v_coord;\n" 1706e5c31af7Sopenharmony_ci "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n" 1707e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 1708e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 1709e5c31af7Sopenharmony_ci "uniform int ui_two;\n" 1710e5c31af7Sopenharmony_ci "void main (void)\n" 1711e5c31af7Sopenharmony_ci "{\n" 1712e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n" 1713e5c31af7Sopenharmony_ci " for (int i = 0; i < ui_two; i++)\n" 1714e5c31af7Sopenharmony_ci " res += ${FUNC}(v_coord * float(i));\n" 1715e5c31af7Sopenharmony_ci " res = res * u_scale + u_bias;\n" 1716e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 1717e5c31af7Sopenharmony_ci "}\n" 1718e5c31af7Sopenharmony_ci }, 1719e5c31af7Sopenharmony_ci { 1720e5c31af7Sopenharmony_ci "uniform_switch", 1721e5c31af7Sopenharmony_ci "Derivate of linearly interpolated value in uniform switch", 1722e5c31af7Sopenharmony_ci 1723e5c31af7Sopenharmony_ci "#version 300 es\n" 1724e5c31af7Sopenharmony_ci "in ${PRECISION} ${DATATYPE} v_coord;\n" 1725e5c31af7Sopenharmony_ci "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n" 1726e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_scale;\n" 1727e5c31af7Sopenharmony_ci "uniform ${PRECISION} ${DATATYPE} u_bias;\n" 1728e5c31af7Sopenharmony_ci "uniform int ui_one;\n" 1729e5c31af7Sopenharmony_ci "void main (void)\n" 1730e5c31af7Sopenharmony_ci "{\n" 1731e5c31af7Sopenharmony_ci " ${PRECISION} ${DATATYPE} res;\n" 1732e5c31af7Sopenharmony_ci " switch (ui_one)\n" 1733e5c31af7Sopenharmony_ci " {\n" 1734e5c31af7Sopenharmony_ci " case 0: res = ${FUNC}(-v_coord) * u_scale + u_bias; break;\n" 1735e5c31af7Sopenharmony_ci " case 1: res = ${FUNC}(v_coord) * u_scale + u_bias; break;\n" 1736e5c31af7Sopenharmony_ci " }\n" 1737e5c31af7Sopenharmony_ci " o_color = ${CAST_TO_OUTPUT};\n" 1738e5c31af7Sopenharmony_ci "}\n" 1739e5c31af7Sopenharmony_ci }, 1740e5c31af7Sopenharmony_ci }; 1741e5c31af7Sopenharmony_ci 1742e5c31af7Sopenharmony_ci static const struct 1743e5c31af7Sopenharmony_ci { 1744e5c31af7Sopenharmony_ci const char* name; 1745e5c31af7Sopenharmony_ci SurfaceType surfaceType; 1746e5c31af7Sopenharmony_ci int numSamples; 1747e5c31af7Sopenharmony_ci } s_fboConfigs[] = 1748e5c31af7Sopenharmony_ci { 1749e5c31af7Sopenharmony_ci { "fbo", SURFACETYPE_DEFAULT_FRAMEBUFFER, 0 }, 1750e5c31af7Sopenharmony_ci { "fbo_msaa2", SURFACETYPE_UNORM_FBO, 2 }, 1751e5c31af7Sopenharmony_ci { "fbo_msaa4", SURFACETYPE_UNORM_FBO, 4 }, 1752e5c31af7Sopenharmony_ci { "fbo_float", SURFACETYPE_FLOAT_FBO, 0 }, 1753e5c31af7Sopenharmony_ci }; 1754e5c31af7Sopenharmony_ci 1755e5c31af7Sopenharmony_ci static const struct 1756e5c31af7Sopenharmony_ci { 1757e5c31af7Sopenharmony_ci const char* name; 1758e5c31af7Sopenharmony_ci deUint32 hint; 1759e5c31af7Sopenharmony_ci } s_hints[] = 1760e5c31af7Sopenharmony_ci { 1761e5c31af7Sopenharmony_ci { "fastest", GL_FASTEST }, 1762e5c31af7Sopenharmony_ci { "nicest", GL_NICEST }, 1763e5c31af7Sopenharmony_ci }; 1764e5c31af7Sopenharmony_ci 1765e5c31af7Sopenharmony_ci static const struct 1766e5c31af7Sopenharmony_ci { 1767e5c31af7Sopenharmony_ci const char* name; 1768e5c31af7Sopenharmony_ci SurfaceType surfaceType; 1769e5c31af7Sopenharmony_ci int numSamples; 1770e5c31af7Sopenharmony_ci } s_hintFboConfigs[] = 1771e5c31af7Sopenharmony_ci { 1772e5c31af7Sopenharmony_ci { "default", SURFACETYPE_DEFAULT_FRAMEBUFFER, 0 }, 1773e5c31af7Sopenharmony_ci { "fbo_msaa4", SURFACETYPE_UNORM_FBO, 4 }, 1774e5c31af7Sopenharmony_ci { "fbo_float", SURFACETYPE_FLOAT_FBO, 0 } 1775e5c31af7Sopenharmony_ci }; 1776e5c31af7Sopenharmony_ci 1777e5c31af7Sopenharmony_ci static const struct 1778e5c31af7Sopenharmony_ci { 1779e5c31af7Sopenharmony_ci const char* name; 1780e5c31af7Sopenharmony_ci SurfaceType surfaceType; 1781e5c31af7Sopenharmony_ci int numSamples; 1782e5c31af7Sopenharmony_ci deUint32 hint; 1783e5c31af7Sopenharmony_ci } s_textureConfigs[] = 1784e5c31af7Sopenharmony_ci { 1785e5c31af7Sopenharmony_ci { "basic", SURFACETYPE_DEFAULT_FRAMEBUFFER, 0, GL_DONT_CARE }, 1786e5c31af7Sopenharmony_ci { "msaa4", SURFACETYPE_UNORM_FBO, 4, GL_DONT_CARE }, 1787e5c31af7Sopenharmony_ci { "float_fastest", SURFACETYPE_FLOAT_FBO, 0, GL_FASTEST }, 1788e5c31af7Sopenharmony_ci { "float_nicest", SURFACETYPE_FLOAT_FBO, 0, GL_NICEST }, 1789e5c31af7Sopenharmony_ci }; 1790e5c31af7Sopenharmony_ci 1791e5c31af7Sopenharmony_ci // .dfdx, .dfdy, .fwidth 1792e5c31af7Sopenharmony_ci for (int funcNdx = 0; funcNdx < DERIVATE_LAST; funcNdx++) 1793e5c31af7Sopenharmony_ci { 1794e5c31af7Sopenharmony_ci const DerivateFunc function = DerivateFunc(funcNdx); 1795e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const functionGroup = new tcu::TestCaseGroup(m_testCtx, getDerivateFuncCaseName(function), getDerivateFuncName(function)); 1796e5c31af7Sopenharmony_ci addChild(functionGroup); 1797e5c31af7Sopenharmony_ci 1798e5c31af7Sopenharmony_ci // .constant - no precision variants, checks that derivate of constant arguments is 0 1799e5c31af7Sopenharmony_ci { 1800e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const constantGroup = new tcu::TestCaseGroup(m_testCtx, "constant", "Derivate of constant argument"); 1801e5c31af7Sopenharmony_ci functionGroup->addChild(constantGroup); 1802e5c31af7Sopenharmony_ci 1803e5c31af7Sopenharmony_ci for (int vecSize = 1; vecSize <= 4; vecSize++) 1804e5c31af7Sopenharmony_ci { 1805e5c31af7Sopenharmony_ci const glu::DataType dataType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT; 1806e5c31af7Sopenharmony_ci constantGroup->addChild(new ConstantDerivateCase(m_context, glu::getDataTypeName(dataType), "", function, dataType)); 1807e5c31af7Sopenharmony_ci } 1808e5c31af7Sopenharmony_ci } 1809e5c31af7Sopenharmony_ci 1810e5c31af7Sopenharmony_ci // Cases based on LinearDerivateCase 1811e5c31af7Sopenharmony_ci for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_linearDerivateCases); caseNdx++) 1812e5c31af7Sopenharmony_ci { 1813e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const linearCaseGroup = new tcu::TestCaseGroup(m_testCtx, s_linearDerivateCases[caseNdx].name, s_linearDerivateCases[caseNdx].description); 1814e5c31af7Sopenharmony_ci const char* source = s_linearDerivateCases[caseNdx].source; 1815e5c31af7Sopenharmony_ci functionGroup->addChild(linearCaseGroup); 1816e5c31af7Sopenharmony_ci 1817e5c31af7Sopenharmony_ci for (int vecSize = 1; vecSize <= 4; vecSize++) 1818e5c31af7Sopenharmony_ci { 1819e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++) 1820e5c31af7Sopenharmony_ci { 1821e5c31af7Sopenharmony_ci const glu::DataType dataType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT; 1822e5c31af7Sopenharmony_ci const glu::Precision precision = glu::Precision(precNdx); 1823e5c31af7Sopenharmony_ci const SurfaceType surfaceType = SURFACETYPE_DEFAULT_FRAMEBUFFER; 1824e5c31af7Sopenharmony_ci const int numSamples = 0; 1825e5c31af7Sopenharmony_ci const deUint32 hint = GL_DONT_CARE; 1826e5c31af7Sopenharmony_ci ostringstream caseName; 1827e5c31af7Sopenharmony_ci 1828e5c31af7Sopenharmony_ci if (caseNdx != 0 && precision == glu::PRECISION_LOWP) 1829e5c31af7Sopenharmony_ci continue; // Skip as lowp doesn't actually produce any bits when rendered to default FB. 1830e5c31af7Sopenharmony_ci 1831e5c31af7Sopenharmony_ci caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision); 1832e5c31af7Sopenharmony_ci 1833e5c31af7Sopenharmony_ci linearCaseGroup->addChild(new LinearDerivateCase(m_context, caseName.str().c_str(), "", function, dataType, precision, hint, surfaceType, numSamples, source)); 1834e5c31af7Sopenharmony_ci } 1835e5c31af7Sopenharmony_ci } 1836e5c31af7Sopenharmony_ci } 1837e5c31af7Sopenharmony_ci 1838e5c31af7Sopenharmony_ci // Fbo cases 1839e5c31af7Sopenharmony_ci for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_fboConfigs); caseNdx++) 1840e5c31af7Sopenharmony_ci { 1841e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const fboGroup = new tcu::TestCaseGroup(m_testCtx, s_fboConfigs[caseNdx].name, "Derivate usage when rendering into FBO"); 1842e5c31af7Sopenharmony_ci const char* source = s_linearDerivateCases[0].source; // use source from .linear group 1843e5c31af7Sopenharmony_ci const SurfaceType surfaceType = s_fboConfigs[caseNdx].surfaceType; 1844e5c31af7Sopenharmony_ci const int numSamples = s_fboConfigs[caseNdx].numSamples; 1845e5c31af7Sopenharmony_ci functionGroup->addChild(fboGroup); 1846e5c31af7Sopenharmony_ci 1847e5c31af7Sopenharmony_ci for (int vecSize = 1; vecSize <= 4; vecSize++) 1848e5c31af7Sopenharmony_ci { 1849e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++) 1850e5c31af7Sopenharmony_ci { 1851e5c31af7Sopenharmony_ci const glu::DataType dataType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT; 1852e5c31af7Sopenharmony_ci const glu::Precision precision = glu::Precision(precNdx); 1853e5c31af7Sopenharmony_ci const deUint32 hint = GL_DONT_CARE; 1854e5c31af7Sopenharmony_ci ostringstream caseName; 1855e5c31af7Sopenharmony_ci 1856e5c31af7Sopenharmony_ci if (surfaceType != SURFACETYPE_FLOAT_FBO && precision == glu::PRECISION_LOWP) 1857e5c31af7Sopenharmony_ci continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT. 1858e5c31af7Sopenharmony_ci 1859e5c31af7Sopenharmony_ci caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision); 1860e5c31af7Sopenharmony_ci 1861e5c31af7Sopenharmony_ci fboGroup->addChild(new LinearDerivateCase(m_context, caseName.str().c_str(), "", function, dataType, precision, hint, surfaceType, numSamples, source)); 1862e5c31af7Sopenharmony_ci } 1863e5c31af7Sopenharmony_ci } 1864e5c31af7Sopenharmony_ci } 1865e5c31af7Sopenharmony_ci 1866e5c31af7Sopenharmony_ci // .fastest, .nicest 1867e5c31af7Sopenharmony_ci for (int hintCaseNdx = 0; hintCaseNdx < DE_LENGTH_OF_ARRAY(s_hints); hintCaseNdx++) 1868e5c31af7Sopenharmony_ci { 1869e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const hintGroup = new tcu::TestCaseGroup(m_testCtx, s_hints[hintCaseNdx].name, "Shader derivate hints"); 1870e5c31af7Sopenharmony_ci const char* source = s_linearDerivateCases[0].source; // use source from .linear group 1871e5c31af7Sopenharmony_ci const deUint32 hint = s_hints[hintCaseNdx].hint; 1872e5c31af7Sopenharmony_ci functionGroup->addChild(hintGroup); 1873e5c31af7Sopenharmony_ci 1874e5c31af7Sopenharmony_ci for (int fboCaseNdx = 0; fboCaseNdx < DE_LENGTH_OF_ARRAY(s_hintFboConfigs); fboCaseNdx++) 1875e5c31af7Sopenharmony_ci { 1876e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const fboGroup = new tcu::TestCaseGroup(m_testCtx, s_hintFboConfigs[fboCaseNdx].name, ""); 1877e5c31af7Sopenharmony_ci const SurfaceType surfaceType = s_hintFboConfigs[fboCaseNdx].surfaceType; 1878e5c31af7Sopenharmony_ci const int numSamples = s_hintFboConfigs[fboCaseNdx].numSamples; 1879e5c31af7Sopenharmony_ci hintGroup->addChild(fboGroup); 1880e5c31af7Sopenharmony_ci 1881e5c31af7Sopenharmony_ci for (int vecSize = 1; vecSize <= 4; vecSize++) 1882e5c31af7Sopenharmony_ci { 1883e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++) 1884e5c31af7Sopenharmony_ci { 1885e5c31af7Sopenharmony_ci const glu::DataType dataType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT; 1886e5c31af7Sopenharmony_ci const glu::Precision precision = glu::Precision(precNdx); 1887e5c31af7Sopenharmony_ci ostringstream caseName; 1888e5c31af7Sopenharmony_ci 1889e5c31af7Sopenharmony_ci if (surfaceType != SURFACETYPE_FLOAT_FBO && precision == glu::PRECISION_LOWP) 1890e5c31af7Sopenharmony_ci continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT. 1891e5c31af7Sopenharmony_ci 1892e5c31af7Sopenharmony_ci caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision); 1893e5c31af7Sopenharmony_ci 1894e5c31af7Sopenharmony_ci fboGroup->addChild(new LinearDerivateCase(m_context, caseName.str().c_str(), "", function, dataType, precision, hint, surfaceType, numSamples, source)); 1895e5c31af7Sopenharmony_ci } 1896e5c31af7Sopenharmony_ci } 1897e5c31af7Sopenharmony_ci } 1898e5c31af7Sopenharmony_ci } 1899e5c31af7Sopenharmony_ci 1900e5c31af7Sopenharmony_ci // .texture 1901e5c31af7Sopenharmony_ci { 1902e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const textureGroup = new tcu::TestCaseGroup(m_testCtx, "texture", "Derivate of texture lookup result"); 1903e5c31af7Sopenharmony_ci functionGroup->addChild(textureGroup); 1904e5c31af7Sopenharmony_ci 1905e5c31af7Sopenharmony_ci for (int texCaseNdx = 0; texCaseNdx < DE_LENGTH_OF_ARRAY(s_textureConfigs); texCaseNdx++) 1906e5c31af7Sopenharmony_ci { 1907e5c31af7Sopenharmony_ci tcu::TestCaseGroup* const caseGroup = new tcu::TestCaseGroup(m_testCtx, s_textureConfigs[texCaseNdx].name, ""); 1908e5c31af7Sopenharmony_ci const SurfaceType surfaceType = s_textureConfigs[texCaseNdx].surfaceType; 1909e5c31af7Sopenharmony_ci const int numSamples = s_textureConfigs[texCaseNdx].numSamples; 1910e5c31af7Sopenharmony_ci const deUint32 hint = s_textureConfigs[texCaseNdx].hint; 1911e5c31af7Sopenharmony_ci textureGroup->addChild(caseGroup); 1912e5c31af7Sopenharmony_ci 1913e5c31af7Sopenharmony_ci for (int vecSize = 1; vecSize <= 4; vecSize++) 1914e5c31af7Sopenharmony_ci { 1915e5c31af7Sopenharmony_ci for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++) 1916e5c31af7Sopenharmony_ci { 1917e5c31af7Sopenharmony_ci const glu::DataType dataType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT; 1918e5c31af7Sopenharmony_ci const glu::Precision precision = glu::Precision(precNdx); 1919e5c31af7Sopenharmony_ci ostringstream caseName; 1920e5c31af7Sopenharmony_ci 1921e5c31af7Sopenharmony_ci if (surfaceType != SURFACETYPE_FLOAT_FBO && precision == glu::PRECISION_LOWP) 1922e5c31af7Sopenharmony_ci continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT. 1923e5c31af7Sopenharmony_ci 1924e5c31af7Sopenharmony_ci caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision); 1925e5c31af7Sopenharmony_ci 1926e5c31af7Sopenharmony_ci caseGroup->addChild(new TextureDerivateCase(m_context, caseName.str().c_str(), "", function, dataType, precision, hint, surfaceType, numSamples)); 1927e5c31af7Sopenharmony_ci } 1928e5c31af7Sopenharmony_ci } 1929e5c31af7Sopenharmony_ci } 1930e5c31af7Sopenharmony_ci } 1931e5c31af7Sopenharmony_ci } 1932e5c31af7Sopenharmony_ci} 1933e5c31af7Sopenharmony_ci 1934e5c31af7Sopenharmony_ci} // Functional 1935e5c31af7Sopenharmony_ci} // gles3 1936e5c31af7Sopenharmony_ci} // deqp 1937