1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES Utilities 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 Utility functions and structures for texture tests. This code 22e5c31af7Sopenharmony_ci * is originated from the modules/glshared/glsTextureTestUtil.hpp and it 23e5c31af7Sopenharmony_ci * is tightly coupled with the GLES and Vulkan texture tests! 24e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include "gluTextureTestUtil.hpp" 27e5c31af7Sopenharmony_ci 28e5c31af7Sopenharmony_ci#include "tcuFloat.hpp" 29e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp" 30e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 31e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp" 32e5c31af7Sopenharmony_ci 33e5c31af7Sopenharmony_ci#include "deMath.h" 34e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 35e5c31af7Sopenharmony_ci 36e5c31af7Sopenharmony_ci#include <string> 37e5c31af7Sopenharmony_ci 38e5c31af7Sopenharmony_ciusing std::string; 39e5c31af7Sopenharmony_ci 40e5c31af7Sopenharmony_cinamespace glu 41e5c31af7Sopenharmony_ci{ 42e5c31af7Sopenharmony_ci 43e5c31af7Sopenharmony_cinamespace TextureTestUtil 44e5c31af7Sopenharmony_ci{ 45e5c31af7Sopenharmony_ci 46e5c31af7Sopenharmony_cienum 47e5c31af7Sopenharmony_ci{ 48e5c31af7Sopenharmony_ci MIN_SUBPIXEL_BITS = 4 49e5c31af7Sopenharmony_ci}; 50e5c31af7Sopenharmony_ci 51e5c31af7Sopenharmony_ciSamplerType getSamplerType (tcu::TextureFormat format) 52e5c31af7Sopenharmony_ci{ 53e5c31af7Sopenharmony_ci using tcu::TextureFormat; 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_ci switch (format.type) 56e5c31af7Sopenharmony_ci { 57e5c31af7Sopenharmony_ci case TextureFormat::SIGNED_INT8: 58e5c31af7Sopenharmony_ci case TextureFormat::SIGNED_INT16: 59e5c31af7Sopenharmony_ci case TextureFormat::SIGNED_INT32: 60e5c31af7Sopenharmony_ci return SAMPLERTYPE_INT; 61e5c31af7Sopenharmony_ci 62e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT8: 63e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT32: 64e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT_1010102_REV: 65e5c31af7Sopenharmony_ci return SAMPLERTYPE_UINT; 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ci // Texture formats used in depth/stencil textures. 68e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT16: 69e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT_24_8: 70e5c31af7Sopenharmony_ci return (format.order == TextureFormat::D || format.order == TextureFormat::DS) ? SAMPLERTYPE_FLOAT : SAMPLERTYPE_UINT; 71e5c31af7Sopenharmony_ci 72e5c31af7Sopenharmony_ci default: 73e5c31af7Sopenharmony_ci return SAMPLERTYPE_FLOAT; 74e5c31af7Sopenharmony_ci } 75e5c31af7Sopenharmony_ci} 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ciSamplerType getFetchSamplerType (tcu::TextureFormat format) 78e5c31af7Sopenharmony_ci{ 79e5c31af7Sopenharmony_ci using tcu::TextureFormat; 80e5c31af7Sopenharmony_ci 81e5c31af7Sopenharmony_ci switch (format.type) 82e5c31af7Sopenharmony_ci { 83e5c31af7Sopenharmony_ci case TextureFormat::SIGNED_INT8: 84e5c31af7Sopenharmony_ci case TextureFormat::SIGNED_INT16: 85e5c31af7Sopenharmony_ci case TextureFormat::SIGNED_INT32: 86e5c31af7Sopenharmony_ci return SAMPLERTYPE_FETCH_INT; 87e5c31af7Sopenharmony_ci 88e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT8: 89e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT32: 90e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT_1010102_REV: 91e5c31af7Sopenharmony_ci return SAMPLERTYPE_FETCH_UINT; 92e5c31af7Sopenharmony_ci 93e5c31af7Sopenharmony_ci // Texture formats used in depth/stencil textures. 94e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT16: 95e5c31af7Sopenharmony_ci case TextureFormat::UNSIGNED_INT_24_8: 96e5c31af7Sopenharmony_ci return (format.order == TextureFormat::D || format.order == TextureFormat::DS) ? SAMPLERTYPE_FETCH_FLOAT : SAMPLERTYPE_FETCH_UINT; 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_ci default: 99e5c31af7Sopenharmony_ci return SAMPLERTYPE_FETCH_FLOAT; 100e5c31af7Sopenharmony_ci } 101e5c31af7Sopenharmony_ci} 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_cistatic tcu::Texture1DView getSubView (const tcu::Texture1DView& view, int baseLevel, int maxLevel, tcu::ImageViewMinLodParams* minLodParams DE_UNUSED_ATTR) 104e5c31af7Sopenharmony_ci{ 105e5c31af7Sopenharmony_ci const int clampedBase = de::clamp(baseLevel, 0, view.getNumLevels()-1); 106e5c31af7Sopenharmony_ci const int clampedMax = de::clamp(maxLevel, clampedBase, view.getNumLevels()-1); 107e5c31af7Sopenharmony_ci const int numLevels = clampedMax-clampedBase+1; 108e5c31af7Sopenharmony_ci return tcu::Texture1DView(numLevels, view.getLevels()+clampedBase); 109e5c31af7Sopenharmony_ci} 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_cistatic tcu::Texture2DView getSubView (const tcu::Texture2DView& view, int baseLevel, int maxLevel, tcu::ImageViewMinLodParams* minLodParams = DE_NULL) 112e5c31af7Sopenharmony_ci{ 113e5c31af7Sopenharmony_ci const int clampedBase = de::clamp(baseLevel, 0, view.getNumLevels()-1); 114e5c31af7Sopenharmony_ci const int clampedMax = de::clamp(maxLevel, clampedBase, view.getNumLevels()-1); 115e5c31af7Sopenharmony_ci const int numLevels = clampedMax-clampedBase+1; 116e5c31af7Sopenharmony_ci return tcu::Texture2DView(numLevels, view.getLevels()+clampedBase, view.isES2(), minLodParams); 117e5c31af7Sopenharmony_ci} 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_cistatic tcu::TextureCubeView getSubView (const tcu::TextureCubeView& view, int baseLevel, int maxLevel, tcu::ImageViewMinLodParams* minLodParams = DE_NULL) 120e5c31af7Sopenharmony_ci{ 121e5c31af7Sopenharmony_ci const int clampedBase = de::clamp(baseLevel, 0, view.getNumLevels()-1); 122e5c31af7Sopenharmony_ci const int clampedMax = de::clamp(maxLevel, clampedBase, view.getNumLevels()-1); 123e5c31af7Sopenharmony_ci const int numLevels = clampedMax-clampedBase+1; 124e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess* levels[tcu::CUBEFACE_LAST]; 125e5c31af7Sopenharmony_ci 126e5c31af7Sopenharmony_ci for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 127e5c31af7Sopenharmony_ci levels[face] = view.getFaceLevels((tcu::CubeFace)face) + clampedBase; 128e5c31af7Sopenharmony_ci 129e5c31af7Sopenharmony_ci return tcu::TextureCubeView(numLevels, levels, false, minLodParams); 130e5c31af7Sopenharmony_ci} 131e5c31af7Sopenharmony_ci 132e5c31af7Sopenharmony_cistatic tcu::Texture3DView getSubView (const tcu::Texture3DView& view, int baseLevel, int maxLevel, tcu::ImageViewMinLodParams* minLodParams = DE_NULL) 133e5c31af7Sopenharmony_ci{ 134e5c31af7Sopenharmony_ci const int clampedBase = de::clamp(baseLevel, 0, view.getNumLevels()-1); 135e5c31af7Sopenharmony_ci const int clampedMax = de::clamp(maxLevel, clampedBase, view.getNumLevels()-1); 136e5c31af7Sopenharmony_ci const int numLevels = clampedMax-clampedBase+1; 137e5c31af7Sopenharmony_ci return tcu::Texture3DView(numLevels, view.getLevels()+clampedBase, false, minLodParams); 138e5c31af7Sopenharmony_ci} 139e5c31af7Sopenharmony_ci 140e5c31af7Sopenharmony_cistatic tcu::TextureCubeArrayView getSubView (const tcu::TextureCubeArrayView& view, int baseLevel, int maxLevel, tcu::ImageViewMinLodParams* minLodParams DE_UNUSED_ATTR = DE_NULL) 141e5c31af7Sopenharmony_ci{ 142e5c31af7Sopenharmony_ci const int clampedBase = de::clamp(baseLevel, 0, view.getNumLevels()-1); 143e5c31af7Sopenharmony_ci const int clampedMax = de::clamp(maxLevel, clampedBase, view.getNumLevels()-1); 144e5c31af7Sopenharmony_ci const int numLevels = clampedMax-clampedBase+1; 145e5c31af7Sopenharmony_ci return tcu::TextureCubeArrayView(numLevels, view.getLevels()+clampedBase); 146e5c31af7Sopenharmony_ci} 147e5c31af7Sopenharmony_ci 148e5c31af7Sopenharmony_ciinline float linearInterpolate (float t, float minVal, float maxVal) 149e5c31af7Sopenharmony_ci{ 150e5c31af7Sopenharmony_ci return minVal + (maxVal - minVal) * t; 151e5c31af7Sopenharmony_ci} 152e5c31af7Sopenharmony_ci 153e5c31af7Sopenharmony_ciinline tcu::Vec4 linearInterpolate (float t, const tcu::Vec4& a, const tcu::Vec4& b) 154e5c31af7Sopenharmony_ci{ 155e5c31af7Sopenharmony_ci return a + (b - a) * t; 156e5c31af7Sopenharmony_ci} 157e5c31af7Sopenharmony_ci 158e5c31af7Sopenharmony_ciinline float bilinearInterpolate (float x, float y, const tcu::Vec4& quad) 159e5c31af7Sopenharmony_ci{ 160e5c31af7Sopenharmony_ci float w00 = (1.0f-x)*(1.0f-y); 161e5c31af7Sopenharmony_ci float w01 = (1.0f-x)*y; 162e5c31af7Sopenharmony_ci float w10 = x*(1.0f-y); 163e5c31af7Sopenharmony_ci float w11 = x*y; 164e5c31af7Sopenharmony_ci return quad.x()*w00 + quad.y()*w10 + quad.z()*w01 + quad.w()*w11; 165e5c31af7Sopenharmony_ci} 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_cifloat triangleInterpolate (float v0, float v1, float v2, float x, float y) 168e5c31af7Sopenharmony_ci{ 169e5c31af7Sopenharmony_ci return v0 + (v2-v0)*x + (v1-v0)*y; 170e5c31af7Sopenharmony_ci} 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_cifloat triangleInterpolate (const tcu::Vec3& v, float x, float y) 173e5c31af7Sopenharmony_ci{ 174e5c31af7Sopenharmony_ci return triangleInterpolate(v.x(), v.y(), v.z(), x, y); 175e5c31af7Sopenharmony_ci} 176e5c31af7Sopenharmony_ci 177e5c31af7Sopenharmony_ci// 1D lookup LOD computation. 178e5c31af7Sopenharmony_ci 179e5c31af7Sopenharmony_cifloat computeLodFromDerivates (LodMode mode, float dudx, float dudy) 180e5c31af7Sopenharmony_ci{ 181e5c31af7Sopenharmony_ci float p = 0.0f; 182e5c31af7Sopenharmony_ci switch (mode) 183e5c31af7Sopenharmony_ci { 184e5c31af7Sopenharmony_ci // \note [mika] Min and max bounds equal to exact with 1D textures 185e5c31af7Sopenharmony_ci case LODMODE_EXACT: 186e5c31af7Sopenharmony_ci case LODMODE_MIN_BOUND: 187e5c31af7Sopenharmony_ci case LODMODE_MAX_BOUND: 188e5c31af7Sopenharmony_ci p = de::max(deFloatAbs(dudx), deFloatAbs(dudy)); 189e5c31af7Sopenharmony_ci break; 190e5c31af7Sopenharmony_ci 191e5c31af7Sopenharmony_ci default: 192e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 193e5c31af7Sopenharmony_ci } 194e5c31af7Sopenharmony_ci 195e5c31af7Sopenharmony_ci return deFloatLog2(p); 196e5c31af7Sopenharmony_ci} 197e5c31af7Sopenharmony_ci 198e5c31af7Sopenharmony_cifloat computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, deInt32 srcSize, const tcu::Vec3& sq) 199e5c31af7Sopenharmony_ci{ 200e5c31af7Sopenharmony_ci float dux = (sq.z() - sq.x()) * (float)srcSize; 201e5c31af7Sopenharmony_ci float duy = (sq.y() - sq.x()) * (float)srcSize; 202e5c31af7Sopenharmony_ci float dx = (float)dstSize.x(); 203e5c31af7Sopenharmony_ci float dy = (float)dstSize.y(); 204e5c31af7Sopenharmony_ci 205e5c31af7Sopenharmony_ci return computeLodFromDerivates(mode, dux/dx, duy/dy); 206e5c31af7Sopenharmony_ci} 207e5c31af7Sopenharmony_ci 208e5c31af7Sopenharmony_ci// 2D lookup LOD computation. 209e5c31af7Sopenharmony_ci 210e5c31af7Sopenharmony_cifloat computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dudy, float dvdy) 211e5c31af7Sopenharmony_ci{ 212e5c31af7Sopenharmony_ci float p = 0.0f; 213e5c31af7Sopenharmony_ci switch (mode) 214e5c31af7Sopenharmony_ci { 215e5c31af7Sopenharmony_ci case LODMODE_EXACT: 216e5c31af7Sopenharmony_ci p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx), deFloatSqrt(dudy*dudy + dvdy*dvdy)); 217e5c31af7Sopenharmony_ci break; 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_ci case LODMODE_MIN_BOUND: 220e5c31af7Sopenharmony_ci case LODMODE_MAX_BOUND: 221e5c31af7Sopenharmony_ci { 222e5c31af7Sopenharmony_ci float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy)); 223e5c31af7Sopenharmony_ci float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy)); 224e5c31af7Sopenharmony_ci 225e5c31af7Sopenharmony_ci p = mode == LODMODE_MIN_BOUND ? de::max(mu, mv) : mu + mv; 226e5c31af7Sopenharmony_ci break; 227e5c31af7Sopenharmony_ci } 228e5c31af7Sopenharmony_ci 229e5c31af7Sopenharmony_ci default: 230e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 231e5c31af7Sopenharmony_ci } 232e5c31af7Sopenharmony_ci 233e5c31af7Sopenharmony_ci return deFloatLog2(p); 234e5c31af7Sopenharmony_ci} 235e5c31af7Sopenharmony_ci 236e5c31af7Sopenharmony_cifloat computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, const tcu::IVec2& srcSize, const tcu::Vec3& sq, const tcu::Vec3& tq) 237e5c31af7Sopenharmony_ci{ 238e5c31af7Sopenharmony_ci float dux = (sq.z() - sq.x()) * (float)srcSize.x(); 239e5c31af7Sopenharmony_ci float duy = (sq.y() - sq.x()) * (float)srcSize.x(); 240e5c31af7Sopenharmony_ci float dvx = (tq.z() - tq.x()) * (float)srcSize.y(); 241e5c31af7Sopenharmony_ci float dvy = (tq.y() - tq.x()) * (float)srcSize.y(); 242e5c31af7Sopenharmony_ci float dx = (float)dstSize.x(); 243e5c31af7Sopenharmony_ci float dy = (float)dstSize.y(); 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_ci return computeLodFromDerivates(mode, dux/dx, dvx/dx, duy/dy, dvy/dy); 246e5c31af7Sopenharmony_ci} 247e5c31af7Sopenharmony_ci 248e5c31af7Sopenharmony_ci// 3D lookup LOD computation. 249e5c31af7Sopenharmony_ci 250e5c31af7Sopenharmony_cifloat computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dwdx, float dudy, float dvdy, float dwdy) 251e5c31af7Sopenharmony_ci{ 252e5c31af7Sopenharmony_ci float p = 0.0f; 253e5c31af7Sopenharmony_ci switch (mode) 254e5c31af7Sopenharmony_ci { 255e5c31af7Sopenharmony_ci case LODMODE_EXACT: 256e5c31af7Sopenharmony_ci p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx + dwdx*dwdx), deFloatSqrt(dudy*dudy + dvdy*dvdy + dwdy*dwdy)); 257e5c31af7Sopenharmony_ci break; 258e5c31af7Sopenharmony_ci 259e5c31af7Sopenharmony_ci case LODMODE_MIN_BOUND: 260e5c31af7Sopenharmony_ci case LODMODE_MAX_BOUND: 261e5c31af7Sopenharmony_ci { 262e5c31af7Sopenharmony_ci float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy)); 263e5c31af7Sopenharmony_ci float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy)); 264e5c31af7Sopenharmony_ci float mw = de::max(deFloatAbs(dwdx), deFloatAbs(dwdy)); 265e5c31af7Sopenharmony_ci 266e5c31af7Sopenharmony_ci p = mode == LODMODE_MIN_BOUND ? de::max(de::max(mu, mv), mw) : (mu + mv + mw); 267e5c31af7Sopenharmony_ci break; 268e5c31af7Sopenharmony_ci } 269e5c31af7Sopenharmony_ci 270e5c31af7Sopenharmony_ci default: 271e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 272e5c31af7Sopenharmony_ci } 273e5c31af7Sopenharmony_ci 274e5c31af7Sopenharmony_ci return deFloatLog2(p); 275e5c31af7Sopenharmony_ci} 276e5c31af7Sopenharmony_ci 277e5c31af7Sopenharmony_cifloat computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, const tcu::IVec3& srcSize, const tcu::Vec3& sq, const tcu::Vec3& tq, const tcu::Vec3& rq) 278e5c31af7Sopenharmony_ci{ 279e5c31af7Sopenharmony_ci float dux = (sq.z() - sq.x()) * (float)srcSize.x(); 280e5c31af7Sopenharmony_ci float duy = (sq.y() - sq.x()) * (float)srcSize.x(); 281e5c31af7Sopenharmony_ci float dvx = (tq.z() - tq.x()) * (float)srcSize.y(); 282e5c31af7Sopenharmony_ci float dvy = (tq.y() - tq.x()) * (float)srcSize.y(); 283e5c31af7Sopenharmony_ci float dwx = (rq.z() - rq.x()) * (float)srcSize.z(); 284e5c31af7Sopenharmony_ci float dwy = (rq.y() - rq.x()) * (float)srcSize.z(); 285e5c31af7Sopenharmony_ci float dx = (float)dstSize.x(); 286e5c31af7Sopenharmony_ci float dy = (float)dstSize.y(); 287e5c31af7Sopenharmony_ci 288e5c31af7Sopenharmony_ci return computeLodFromDerivates(mode, dux/dx, dvx/dx, dwx/dx, duy/dy, dvy/dy, dwy/dy); 289e5c31af7Sopenharmony_ci} 290e5c31af7Sopenharmony_ci 291e5c31af7Sopenharmony_cistatic inline float projectedTriInterpolate (const tcu::Vec3& s, const tcu::Vec3& w, float nx, float ny) 292e5c31af7Sopenharmony_ci{ 293e5c31af7Sopenharmony_ci return (s[0]*(1.0f-nx-ny)/w[0] + s[1]*ny/w[1] + s[2]*nx/w[2]) / ((1.0f-nx-ny)/w[0] + ny/w[1] + nx/w[2]); 294e5c31af7Sopenharmony_ci} 295e5c31af7Sopenharmony_ci 296e5c31af7Sopenharmony_cistatic inline float triDerivateX (const tcu::Vec3& s, const tcu::Vec3& w, float wx, float width, float ny) 297e5c31af7Sopenharmony_ci{ 298e5c31af7Sopenharmony_ci float d = w[1]*w[2]*(width*(ny - 1.0f) + wx) - w[0]*(w[2]*width*ny + w[1]*wx); 299e5c31af7Sopenharmony_ci return (w[0]*w[1]*w[2]*width * (w[1]*(s[0] - s[2])*(ny - 1.0f) + ny*(w[2]*(s[1] - s[0]) + w[0]*(s[2] - s[1])))) / (d*d); 300e5c31af7Sopenharmony_ci} 301e5c31af7Sopenharmony_ci 302e5c31af7Sopenharmony_cistatic inline float triDerivateY (const tcu::Vec3& s, const tcu::Vec3& w, float wy, float height, float nx) 303e5c31af7Sopenharmony_ci{ 304e5c31af7Sopenharmony_ci float d = w[1]*w[2]*(height*(nx - 1.0f) + wy) - w[0]*(w[1]*height*nx + w[2]*wy); 305e5c31af7Sopenharmony_ci return (w[0]*w[1]*w[2]*height * (w[2]*(s[0] - s[1])*(nx - 1.0f) + nx*(w[0]*(s[1] - s[2]) + w[1]*(s[2] - s[0])))) / (d*d); 306e5c31af7Sopenharmony_ci} 307e5c31af7Sopenharmony_ci 308e5c31af7Sopenharmony_ci// 1D lookup LOD. 309e5c31af7Sopenharmony_cistatic float computeProjectedTriLod (LodMode mode, const tcu::Vec3& u, const tcu::Vec3& projection, float wx, float wy, float width, float height) 310e5c31af7Sopenharmony_ci{ 311e5c31af7Sopenharmony_ci // Exact derivatives. 312e5c31af7Sopenharmony_ci float dudx = triDerivateX(u, projection, wx, width, wy/height); 313e5c31af7Sopenharmony_ci float dudy = triDerivateY(u, projection, wy, height, wx/width); 314e5c31af7Sopenharmony_ci 315e5c31af7Sopenharmony_ci return computeLodFromDerivates(mode, dudx, dudy); 316e5c31af7Sopenharmony_ci} 317e5c31af7Sopenharmony_ci 318e5c31af7Sopenharmony_ci// 2D lookup LOD. 319e5c31af7Sopenharmony_cistatic float computeProjectedTriLod (LodMode mode, const tcu::Vec3& u, const tcu::Vec3& v, const tcu::Vec3& projection, float wx, float wy, float width, float height) 320e5c31af7Sopenharmony_ci{ 321e5c31af7Sopenharmony_ci // Exact derivatives. 322e5c31af7Sopenharmony_ci float dudx = triDerivateX(u, projection, wx, width, wy/height); 323e5c31af7Sopenharmony_ci float dvdx = triDerivateX(v, projection, wx, width, wy/height); 324e5c31af7Sopenharmony_ci float dudy = triDerivateY(u, projection, wy, height, wx/width); 325e5c31af7Sopenharmony_ci float dvdy = triDerivateY(v, projection, wy, height, wx/width); 326e5c31af7Sopenharmony_ci 327e5c31af7Sopenharmony_ci return computeLodFromDerivates(mode, dudx, dvdx, dudy, dvdy); 328e5c31af7Sopenharmony_ci} 329e5c31af7Sopenharmony_ci 330e5c31af7Sopenharmony_ci// 3D lookup LOD. 331e5c31af7Sopenharmony_cistatic float computeProjectedTriLod (LodMode mode, const tcu::Vec3& u, const tcu::Vec3& v, const tcu::Vec3& w, const tcu::Vec3& projection, float wx, float wy, float width, float height) 332e5c31af7Sopenharmony_ci{ 333e5c31af7Sopenharmony_ci // Exact derivatives. 334e5c31af7Sopenharmony_ci float dudx = triDerivateX(u, projection, wx, width, wy/height); 335e5c31af7Sopenharmony_ci float dvdx = triDerivateX(v, projection, wx, width, wy/height); 336e5c31af7Sopenharmony_ci float dwdx = triDerivateX(w, projection, wx, width, wy/height); 337e5c31af7Sopenharmony_ci float dudy = triDerivateY(u, projection, wy, height, wx/width); 338e5c31af7Sopenharmony_ci float dvdy = triDerivateY(v, projection, wy, height, wx/width); 339e5c31af7Sopenharmony_ci float dwdy = triDerivateY(w, projection, wy, height, wx/width); 340e5c31af7Sopenharmony_ci 341e5c31af7Sopenharmony_ci return computeLodFromDerivates(mode, dudx, dvdx, dwdx, dudy, dvdy, dwdy); 342e5c31af7Sopenharmony_ci} 343e5c31af7Sopenharmony_ci 344e5c31af7Sopenharmony_cistatic inline tcu::Vec4 execSample (const tcu::Texture1DView& src, const ReferenceParams& params, float s, float lod) 345e5c31af7Sopenharmony_ci{ 346e5c31af7Sopenharmony_ci if (params.samplerType == SAMPLERTYPE_SHADOW) 347e5c31af7Sopenharmony_ci return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, lod), 0.0, 0.0, 1.0f); 348e5c31af7Sopenharmony_ci else 349e5c31af7Sopenharmony_ci return src.sample(params.sampler, s, lod); 350e5c31af7Sopenharmony_ci} 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_cistatic inline tcu::Vec4 execSample (const tcu::Texture2DView& src, const ReferenceParams& params, float s, float t, float lod) 353e5c31af7Sopenharmony_ci{ 354e5c31af7Sopenharmony_ci if (params.samplerType == SAMPLERTYPE_SHADOW) 355e5c31af7Sopenharmony_ci return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, lod), 0.0, 0.0, 1.0f); 356e5c31af7Sopenharmony_ci else 357e5c31af7Sopenharmony_ci return src.sample(params.sampler, s, t, lod); 358e5c31af7Sopenharmony_ci} 359e5c31af7Sopenharmony_ci 360e5c31af7Sopenharmony_cistatic inline tcu::Vec4 execSample (const tcu::TextureCubeView& src, const ReferenceParams& params, float s, float t, float r, float lod) 361e5c31af7Sopenharmony_ci{ 362e5c31af7Sopenharmony_ci if (params.samplerType == SAMPLERTYPE_SHADOW) 363e5c31af7Sopenharmony_ci return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, lod), 0.0, 0.0, 1.0f); 364e5c31af7Sopenharmony_ci else 365e5c31af7Sopenharmony_ci return src.sample(params.sampler, s, t, r, lod); 366e5c31af7Sopenharmony_ci} 367e5c31af7Sopenharmony_ci 368e5c31af7Sopenharmony_cistatic inline tcu::Vec4 execSample (const tcu::Texture2DArrayView& src, const ReferenceParams& params, float s, float t, float r, float lod) 369e5c31af7Sopenharmony_ci{ 370e5c31af7Sopenharmony_ci if (params.samplerType == SAMPLERTYPE_SHADOW) 371e5c31af7Sopenharmony_ci return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, lod), 0.0, 0.0, 1.0f); 372e5c31af7Sopenharmony_ci else 373e5c31af7Sopenharmony_ci return src.sample(params.sampler, s, t, r, lod); 374e5c31af7Sopenharmony_ci} 375e5c31af7Sopenharmony_ci 376e5c31af7Sopenharmony_cistatic inline tcu::Vec4 execSample (const tcu::TextureCubeArrayView& src, const ReferenceParams& params, float s, float t, float r, float q, float lod) 377e5c31af7Sopenharmony_ci{ 378e5c31af7Sopenharmony_ci if (params.samplerType == SAMPLERTYPE_SHADOW) 379e5c31af7Sopenharmony_ci return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, q, lod), 0.0, 0.0, 1.0f); 380e5c31af7Sopenharmony_ci else 381e5c31af7Sopenharmony_ci return src.sample(params.sampler, s, t, r, q, lod); 382e5c31af7Sopenharmony_ci} 383e5c31af7Sopenharmony_ci 384e5c31af7Sopenharmony_cistatic inline tcu::Vec4 execSample (const tcu::Texture1DArrayView& src, const ReferenceParams& params, float s, float t, float lod) 385e5c31af7Sopenharmony_ci{ 386e5c31af7Sopenharmony_ci if (params.samplerType == SAMPLERTYPE_SHADOW) 387e5c31af7Sopenharmony_ci return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, lod), 0.0, 0.0, 1.0f); 388e5c31af7Sopenharmony_ci else 389e5c31af7Sopenharmony_ci return src.sample(params.sampler, s, t, lod); 390e5c31af7Sopenharmony_ci} 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_cistatic void sampleTextureNonProjected (const tcu::SurfaceAccess& dst, const tcu::Texture1DView& rawSrc, const tcu::Vec4& sq, const ReferenceParams& params) 393e5c31af7Sopenharmony_ci{ 394e5c31af7Sopenharmony_ci // Separate combined DS formats 395e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 396e5c31af7Sopenharmony_ci const tcu::Texture1DView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 397e5c31af7Sopenharmony_ci 398e5c31af7Sopenharmony_ci float lodBias = (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f; 399e5c31af7Sopenharmony_ci 400e5c31af7Sopenharmony_ci tcu::IVec2 dstSize = tcu::IVec2(dst.getWidth(), dst.getHeight()); 401e5c31af7Sopenharmony_ci int srcSize = src.getWidth(); 402e5c31af7Sopenharmony_ci 403e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 404e5c31af7Sopenharmony_ci tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 405e5c31af7Sopenharmony_ci float triLod[2] = { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias, params.minLod, params.maxLod), 406e5c31af7Sopenharmony_ci de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias, params.minLod, params.maxLod) }; 407e5c31af7Sopenharmony_ci 408e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 409e5c31af7Sopenharmony_ci { 410e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 411e5c31af7Sopenharmony_ci { 412e5c31af7Sopenharmony_ci float yf = ((float)y + 0.5f) / (float)dst.getHeight(); 413e5c31af7Sopenharmony_ci float xf = ((float)x + 0.5f) / (float)dst.getWidth(); 414e5c31af7Sopenharmony_ci 415e5c31af7Sopenharmony_ci int triNdx = xf + yf >= 1.0f ? 1 : 0; // Top left fill rule. 416e5c31af7Sopenharmony_ci float triX = triNdx ? 1.0f-xf : xf; 417e5c31af7Sopenharmony_ci float triY = triNdx ? 1.0f-yf : yf; 418e5c31af7Sopenharmony_ci 419e5c31af7Sopenharmony_ci float s = triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY); 420e5c31af7Sopenharmony_ci float lod = triLod[triNdx]; 421e5c31af7Sopenharmony_ci 422e5c31af7Sopenharmony_ci dst.setPixel(execSample(src, params, s, lod) * params.colorScale + params.colorBias, x, y); 423e5c31af7Sopenharmony_ci } 424e5c31af7Sopenharmony_ci } 425e5c31af7Sopenharmony_ci} 426e5c31af7Sopenharmony_ci 427e5c31af7Sopenharmony_citemplate<class PixelAccess> 428e5c31af7Sopenharmony_cistatic void sampleTextureNonProjected (const PixelAccess& dst, const tcu::Texture2DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params) 429e5c31af7Sopenharmony_ci{ 430e5c31af7Sopenharmony_ci // Separate combined DS formats 431e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 432e5c31af7Sopenharmony_ci tcu::Texture2DView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 433e5c31af7Sopenharmony_ci 434e5c31af7Sopenharmony_ci float lodBias = (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f; 435e5c31af7Sopenharmony_ci 436e5c31af7Sopenharmony_ci tcu::IVec2 dstSize = tcu::IVec2(dst.getWidth(), dst.getHeight()); 437e5c31af7Sopenharmony_ci tcu::IVec2 srcSize = tcu::IVec2(src.getWidth(), src.getHeight()); 438e5c31af7Sopenharmony_ci 439e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 440e5c31af7Sopenharmony_ci tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 441e5c31af7Sopenharmony_ci tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 442e5c31af7Sopenharmony_ci float triLod[2] = { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias, params.minLod, params.maxLod), 443e5c31af7Sopenharmony_ci de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias, params.minLod, params.maxLod) }; 444e5c31af7Sopenharmony_ci 445e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 446e5c31af7Sopenharmony_ci { 447e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 448e5c31af7Sopenharmony_ci { 449e5c31af7Sopenharmony_ci float yf = ((float)y + 0.5f) / (float)dst.getHeight(); 450e5c31af7Sopenharmony_ci float xf = ((float)x + 0.5f) / (float)dst.getWidth(); 451e5c31af7Sopenharmony_ci 452e5c31af7Sopenharmony_ci int triNdx = xf + yf >= 1.0f ? 1 : 0; // Top left fill rule. 453e5c31af7Sopenharmony_ci float triX = triNdx ? 1.0f-xf : xf; 454e5c31af7Sopenharmony_ci float triY = triNdx ? 1.0f-yf : yf; 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci float s = triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY); 457e5c31af7Sopenharmony_ci float t = triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY); 458e5c31af7Sopenharmony_ci float lod = triLod[triNdx]; 459e5c31af7Sopenharmony_ci 460e5c31af7Sopenharmony_ci if (params.imageViewMinLod != 0.0f && params.samplerType == SAMPLERTYPE_FETCH_FLOAT) 461e5c31af7Sopenharmony_ci lod = (float)params.lodTexelFetch; 462e5c31af7Sopenharmony_ci 463e5c31af7Sopenharmony_ci if (params.float16TexCoord) 464e5c31af7Sopenharmony_ci { 465e5c31af7Sopenharmony_ci s = tcu::Float16(s, tcu::ROUND_TO_ZERO).asFloat(); 466e5c31af7Sopenharmony_ci t = tcu::Float16(t, tcu::ROUND_TO_ZERO).asFloat(); 467e5c31af7Sopenharmony_ci } 468e5c31af7Sopenharmony_ci 469e5c31af7Sopenharmony_ci dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, x, y); 470e5c31af7Sopenharmony_ci } 471e5c31af7Sopenharmony_ci } 472e5c31af7Sopenharmony_ci} 473e5c31af7Sopenharmony_ci 474e5c31af7Sopenharmony_cistatic void sampleTextureProjected (const tcu::SurfaceAccess& dst, const tcu::Texture1DView& rawSrc, const tcu::Vec4& sq, const ReferenceParams& params) 475e5c31af7Sopenharmony_ci{ 476e5c31af7Sopenharmony_ci // Separate combined DS formats 477e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 478e5c31af7Sopenharmony_ci const tcu::Texture1DView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 479e5c31af7Sopenharmony_ci 480e5c31af7Sopenharmony_ci float lodBias = (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f; 481e5c31af7Sopenharmony_ci float dstW = (float)dst.getWidth(); 482e5c31af7Sopenharmony_ci float dstH = (float)dst.getHeight(); 483e5c31af7Sopenharmony_ci 484e5c31af7Sopenharmony_ci tcu::Vec4 uq = sq * (float)src.getWidth(); 485e5c31af7Sopenharmony_ci 486e5c31af7Sopenharmony_ci tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 487e5c31af7Sopenharmony_ci tcu::Vec3 triU[2] = { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) }; 488e5c31af7Sopenharmony_ci tcu::Vec3 triW[2] = { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) }; 489e5c31af7Sopenharmony_ci 490e5c31af7Sopenharmony_ci for (int py = 0; py < dst.getHeight(); py++) 491e5c31af7Sopenharmony_ci { 492e5c31af7Sopenharmony_ci for (int px = 0; px < dst.getWidth(); px++) 493e5c31af7Sopenharmony_ci { 494e5c31af7Sopenharmony_ci float wx = (float)px + 0.5f; 495e5c31af7Sopenharmony_ci float wy = (float)py + 0.5f; 496e5c31af7Sopenharmony_ci float nx = wx / dstW; 497e5c31af7Sopenharmony_ci float ny = wy / dstH; 498e5c31af7Sopenharmony_ci 499e5c31af7Sopenharmony_ci int triNdx = nx + ny >= 1.0f ? 1 : 0; 500e5c31af7Sopenharmony_ci float triWx = triNdx ? dstW - wx : wx; 501e5c31af7Sopenharmony_ci float triWy = triNdx ? dstH - wy : wy; 502e5c31af7Sopenharmony_ci float triNx = triNdx ? 1.0f - nx : nx; 503e5c31af7Sopenharmony_ci float triNy = triNdx ? 1.0f - ny : ny; 504e5c31af7Sopenharmony_ci 505e5c31af7Sopenharmony_ci float s = projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy); 506e5c31af7Sopenharmony_ci float lod = computeProjectedTriLod(params.lodMode, triU[triNdx], triW[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight()) 507e5c31af7Sopenharmony_ci + lodBias; 508e5c31af7Sopenharmony_ci 509e5c31af7Sopenharmony_ci dst.setPixel(execSample(src, params, s, lod) * params.colorScale + params.colorBias, px, py); 510e5c31af7Sopenharmony_ci } 511e5c31af7Sopenharmony_ci } 512e5c31af7Sopenharmony_ci} 513e5c31af7Sopenharmony_ci 514e5c31af7Sopenharmony_citemplate<class PixelAccess> 515e5c31af7Sopenharmony_cistatic void sampleTextureProjected (const PixelAccess& dst, const tcu::Texture2DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params) 516e5c31af7Sopenharmony_ci{ 517e5c31af7Sopenharmony_ci // Separate combined DS formats 518e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 519e5c31af7Sopenharmony_ci const tcu::Texture2DView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 520e5c31af7Sopenharmony_ci 521e5c31af7Sopenharmony_ci float lodBias = (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f; 522e5c31af7Sopenharmony_ci float dstW = (float)dst.getWidth(); 523e5c31af7Sopenharmony_ci float dstH = (float)dst.getHeight(); 524e5c31af7Sopenharmony_ci 525e5c31af7Sopenharmony_ci tcu::Vec4 uq = sq * (float)src.getWidth(); 526e5c31af7Sopenharmony_ci tcu::Vec4 vq = tq * (float)src.getHeight(); 527e5c31af7Sopenharmony_ci 528e5c31af7Sopenharmony_ci tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 529e5c31af7Sopenharmony_ci tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 530e5c31af7Sopenharmony_ci tcu::Vec3 triU[2] = { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) }; 531e5c31af7Sopenharmony_ci tcu::Vec3 triV[2] = { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) }; 532e5c31af7Sopenharmony_ci tcu::Vec3 triW[2] = { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) }; 533e5c31af7Sopenharmony_ci 534e5c31af7Sopenharmony_ci for (int py = 0; py < dst.getHeight(); py++) 535e5c31af7Sopenharmony_ci { 536e5c31af7Sopenharmony_ci for (int px = 0; px < dst.getWidth(); px++) 537e5c31af7Sopenharmony_ci { 538e5c31af7Sopenharmony_ci float wx = (float)px + 0.5f; 539e5c31af7Sopenharmony_ci float wy = (float)py + 0.5f; 540e5c31af7Sopenharmony_ci float nx = wx / dstW; 541e5c31af7Sopenharmony_ci float ny = wy / dstH; 542e5c31af7Sopenharmony_ci 543e5c31af7Sopenharmony_ci int triNdx = nx + ny >= 1.0f ? 1 : 0; 544e5c31af7Sopenharmony_ci float triWx = triNdx ? dstW - wx : wx; 545e5c31af7Sopenharmony_ci float triWy = triNdx ? dstH - wy : wy; 546e5c31af7Sopenharmony_ci float triNx = triNdx ? 1.0f - nx : nx; 547e5c31af7Sopenharmony_ci float triNy = triNdx ? 1.0f - ny : ny; 548e5c31af7Sopenharmony_ci 549e5c31af7Sopenharmony_ci float s = projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy); 550e5c31af7Sopenharmony_ci float t = projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy); 551e5c31af7Sopenharmony_ci float lod = computeProjectedTriLod(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight()) 552e5c31af7Sopenharmony_ci + lodBias; 553e5c31af7Sopenharmony_ci 554e5c31af7Sopenharmony_ci dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, px, py); 555e5c31af7Sopenharmony_ci } 556e5c31af7Sopenharmony_ci } 557e5c31af7Sopenharmony_ci} 558e5c31af7Sopenharmony_ci 559e5c31af7Sopenharmony_civoid sampleTexture (const tcu::PixelBufferAccess& dst, const tcu::Texture2DView& src, const float* texCoord, const ReferenceParams& params) 560e5c31af7Sopenharmony_ci{ 561e5c31af7Sopenharmony_ci tcu::ImageViewMinLodParams minLodParams = 562e5c31af7Sopenharmony_ci { 563e5c31af7Sopenharmony_ci params.baseLevel, // int baseLevel; 564e5c31af7Sopenharmony_ci { 565e5c31af7Sopenharmony_ci params.imageViewMinLod, // float minLod; 566e5c31af7Sopenharmony_ci params.imageViewMinLodMode, // ImageViewMinLodMode 567e5c31af7Sopenharmony_ci }, 568e5c31af7Sopenharmony_ci params.samplerType == SAMPLERTYPE_FETCH_FLOAT // bool intTexCoord; 569e5c31af7Sopenharmony_ci }; 570e5c31af7Sopenharmony_ci 571e5c31af7Sopenharmony_ci const tcu::Texture2DView view = getSubView(src, params.baseLevel, params.maxLevel, params.imageViewMinLod != 0.0f ? &minLodParams : DE_NULL); 572e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]); 573e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]); 574e5c31af7Sopenharmony_ci 575e5c31af7Sopenharmony_ci if (params.flags & ReferenceParams::PROJECTED) 576e5c31af7Sopenharmony_ci sampleTextureProjected(dst, view, sq, tq, params); 577e5c31af7Sopenharmony_ci else 578e5c31af7Sopenharmony_ci sampleTextureNonProjected(dst, view, sq, tq, params); 579e5c31af7Sopenharmony_ci} 580e5c31af7Sopenharmony_ci 581e5c31af7Sopenharmony_civoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture2DView& src, const float* texCoord, const ReferenceParams& params) 582e5c31af7Sopenharmony_ci{ 583e5c31af7Sopenharmony_ci tcu::ImageViewMinLodParams minLodParams = 584e5c31af7Sopenharmony_ci { 585e5c31af7Sopenharmony_ci params.baseLevel, // int baseLevel; 586e5c31af7Sopenharmony_ci { 587e5c31af7Sopenharmony_ci params.imageViewMinLod, // float minLod; 588e5c31af7Sopenharmony_ci params.imageViewMinLodMode, // ImageViewMinLodMode 589e5c31af7Sopenharmony_ci }, 590e5c31af7Sopenharmony_ci params.samplerType == SAMPLERTYPE_FETCH_FLOAT // bool intTexCoord; 591e5c31af7Sopenharmony_ci }; 592e5c31af7Sopenharmony_ci 593e5c31af7Sopenharmony_ci const tcu::Texture2DView view = getSubView(src, params.baseLevel, params.maxLevel, params.imageViewMinLod != 0.0f ? &minLodParams : DE_NULL); 594e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]); 595e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]); 596e5c31af7Sopenharmony_ci 597e5c31af7Sopenharmony_ci if (params.flags & ReferenceParams::PROJECTED) 598e5c31af7Sopenharmony_ci sampleTextureProjected(dst, view, sq, tq, params); 599e5c31af7Sopenharmony_ci else 600e5c31af7Sopenharmony_ci sampleTextureNonProjected(dst, view, sq, tq, params); 601e5c31af7Sopenharmony_ci} 602e5c31af7Sopenharmony_ci 603e5c31af7Sopenharmony_civoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture1DView& src, const float* texCoord, const ReferenceParams& params) 604e5c31af7Sopenharmony_ci{ 605e5c31af7Sopenharmony_ci const tcu::Texture1DView view = getSubView(src, params.baseLevel, params.maxLevel, DE_NULL); 606e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]); 607e5c31af7Sopenharmony_ci 608e5c31af7Sopenharmony_ci if (params.flags & ReferenceParams::PROJECTED) 609e5c31af7Sopenharmony_ci sampleTextureProjected(dst, view, sq, params); 610e5c31af7Sopenharmony_ci else 611e5c31af7Sopenharmony_ci sampleTextureNonProjected(dst, view, sq, params); 612e5c31af7Sopenharmony_ci} 613e5c31af7Sopenharmony_ci 614e5c31af7Sopenharmony_cistatic float computeCubeLodFromDerivates (LodMode lodMode, const tcu::Vec3& coord, const tcu::Vec3& coordDx, const tcu::Vec3& coordDy, const int faceSize) 615e5c31af7Sopenharmony_ci{ 616e5c31af7Sopenharmony_ci const tcu::CubeFace face = tcu::selectCubeFace(coord); 617e5c31af7Sopenharmony_ci int maNdx = 0; 618e5c31af7Sopenharmony_ci int sNdx = 0; 619e5c31af7Sopenharmony_ci int tNdx = 0; 620e5c31af7Sopenharmony_ci 621e5c31af7Sopenharmony_ci // \note Derivate signs don't matter when computing lod 622e5c31af7Sopenharmony_ci switch (face) 623e5c31af7Sopenharmony_ci { 624e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_X: 625e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break; 626e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Y: 627e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break; 628e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Z: 629e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break; 630e5c31af7Sopenharmony_ci default: 631e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 632e5c31af7Sopenharmony_ci } 633e5c31af7Sopenharmony_ci 634e5c31af7Sopenharmony_ci { 635e5c31af7Sopenharmony_ci const float sc = coord[sNdx]; 636e5c31af7Sopenharmony_ci const float tc = coord[tNdx]; 637e5c31af7Sopenharmony_ci const float ma = de::abs(coord[maNdx]); 638e5c31af7Sopenharmony_ci const float scdx = coordDx[sNdx]; 639e5c31af7Sopenharmony_ci const float tcdx = coordDx[tNdx]; 640e5c31af7Sopenharmony_ci const float madx = de::abs(coordDx[maNdx]); 641e5c31af7Sopenharmony_ci const float scdy = coordDy[sNdx]; 642e5c31af7Sopenharmony_ci const float tcdy = coordDy[tNdx]; 643e5c31af7Sopenharmony_ci const float mady = de::abs(coordDy[maNdx]); 644e5c31af7Sopenharmony_ci const float dudx = float(faceSize) * 0.5f * (scdx*ma - sc*madx) / (ma*ma); 645e5c31af7Sopenharmony_ci const float dvdx = float(faceSize) * 0.5f * (tcdx*ma - tc*madx) / (ma*ma); 646e5c31af7Sopenharmony_ci const float dudy = float(faceSize) * 0.5f * (scdy*ma - sc*mady) / (ma*ma); 647e5c31af7Sopenharmony_ci const float dvdy = float(faceSize) * 0.5f * (tcdy*ma - tc*mady) / (ma*ma); 648e5c31af7Sopenharmony_ci 649e5c31af7Sopenharmony_ci return computeLodFromDerivates(lodMode, dudx, dvdx, dudy, dvdy); 650e5c31af7Sopenharmony_ci } 651e5c31af7Sopenharmony_ci} 652e5c31af7Sopenharmony_ci 653e5c31af7Sopenharmony_cistatic void sampleTextureCube (const tcu::SurfaceAccess& dst, const tcu::TextureCubeView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params) 654e5c31af7Sopenharmony_ci{ 655e5c31af7Sopenharmony_ci // Separate combined DS formats 656e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 657e5c31af7Sopenharmony_ci const tcu::TextureCubeView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 658e5c31af7Sopenharmony_ci 659e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(dst.getWidth(), dst.getHeight()); 660e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 661e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 662e5c31af7Sopenharmony_ci const int srcSize = src.getSize(); 663e5c31af7Sopenharmony_ci 664e5c31af7Sopenharmony_ci // Coordinates per triangle. 665e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 666e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 667e5c31af7Sopenharmony_ci const tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 668e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) }; 669e5c31af7Sopenharmony_ci 670e5c31af7Sopenharmony_ci const float lodBias ((params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f); 671e5c31af7Sopenharmony_ci 672e5c31af7Sopenharmony_ci for (int py = 0; py < dst.getHeight(); py++) 673e5c31af7Sopenharmony_ci { 674e5c31af7Sopenharmony_ci for (int px = 0; px < dst.getWidth(); px++) 675e5c31af7Sopenharmony_ci { 676e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 677e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 678e5c31af7Sopenharmony_ci const float nx = wx / dstW; 679e5c31af7Sopenharmony_ci const float ny = wy / dstH; 680e5c31af7Sopenharmony_ci 681e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 682e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 683e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 684e5c31af7Sopenharmony_ci 685e5c31af7Sopenharmony_ci const tcu::Vec3 coord (triangleInterpolate(triS[triNdx], triNx, triNy), 686e5c31af7Sopenharmony_ci triangleInterpolate(triT[triNdx], triNx, triNy), 687e5c31af7Sopenharmony_ci triangleInterpolate(triR[triNdx], triNx, triNy)); 688e5c31af7Sopenharmony_ci const tcu::Vec3 coordDx (triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 689e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy), 690e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)); 691e5c31af7Sopenharmony_ci const tcu::Vec3 coordDy (triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 692e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx), 693e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)); 694e5c31af7Sopenharmony_ci 695e5c31af7Sopenharmony_ci const float lod = de::clamp(computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, srcSize) + lodBias, params.minLod, params.maxLod); 696e5c31af7Sopenharmony_ci 697e5c31af7Sopenharmony_ci dst.setPixel(execSample(src, params, coord.x(), coord.y(), coord.z(), lod) * params.colorScale + params.colorBias, px, py); 698e5c31af7Sopenharmony_ci } 699e5c31af7Sopenharmony_ci } 700e5c31af7Sopenharmony_ci} 701e5c31af7Sopenharmony_ci 702e5c31af7Sopenharmony_civoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::TextureCubeView& src, const float* texCoord, const ReferenceParams& params) 703e5c31af7Sopenharmony_ci{ 704e5c31af7Sopenharmony_ci tcu::ImageViewMinLodParams minLodParams = 705e5c31af7Sopenharmony_ci { 706e5c31af7Sopenharmony_ci params.baseLevel, // int baseLevel; 707e5c31af7Sopenharmony_ci { 708e5c31af7Sopenharmony_ci params.imageViewMinLod, // float minLod; 709e5c31af7Sopenharmony_ci params.imageViewMinLodMode, // ImageViewMinLodMode 710e5c31af7Sopenharmony_ci }, 711e5c31af7Sopenharmony_ci params.samplerType == SAMPLERTYPE_FETCH_FLOAT // bool intTexCoord; 712e5c31af7Sopenharmony_ci }; 713e5c31af7Sopenharmony_ci 714e5c31af7Sopenharmony_ci const tcu::TextureCubeView view = getSubView(src, params.baseLevel, params.maxLevel, params.imageViewMinLod != 0.0f ? &minLodParams : DE_NULL); 715e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]); 716e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]); 717e5c31af7Sopenharmony_ci const tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]); 718e5c31af7Sopenharmony_ci 719e5c31af7Sopenharmony_ci return sampleTextureCube(dst, view, sq, tq, rq, params); 720e5c31af7Sopenharmony_ci} 721e5c31af7Sopenharmony_ci 722e5c31af7Sopenharmony_cistatic void sampleTextureNonProjected (const tcu::SurfaceAccess& dst, const tcu::Texture2DArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params) 723e5c31af7Sopenharmony_ci{ 724e5c31af7Sopenharmony_ci // Separate combined DS formats 725e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 726e5c31af7Sopenharmony_ci const tcu::Texture2DArrayView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 727e5c31af7Sopenharmony_ci 728e5c31af7Sopenharmony_ci float lodBias = (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f; 729e5c31af7Sopenharmony_ci 730e5c31af7Sopenharmony_ci tcu::IVec2 dstSize = tcu::IVec2(dst.getWidth(), dst.getHeight()); 731e5c31af7Sopenharmony_ci tcu::IVec2 srcSize = tcu::IVec2(src.getWidth(), src.getHeight()); 732e5c31af7Sopenharmony_ci 733e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 734e5c31af7Sopenharmony_ci tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 735e5c31af7Sopenharmony_ci tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 736e5c31af7Sopenharmony_ci tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 737e5c31af7Sopenharmony_ci float triLod[2] = { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias, params.minLod, params.maxLod), 738e5c31af7Sopenharmony_ci de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias, params.minLod, params.maxLod) }; 739e5c31af7Sopenharmony_ci 740e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 741e5c31af7Sopenharmony_ci { 742e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 743e5c31af7Sopenharmony_ci { 744e5c31af7Sopenharmony_ci float yf = ((float)y + 0.5f) / (float)dst.getHeight(); 745e5c31af7Sopenharmony_ci float xf = ((float)x + 0.5f) / (float)dst.getWidth(); 746e5c31af7Sopenharmony_ci 747e5c31af7Sopenharmony_ci int triNdx = xf + yf >= 1.0f ? 1 : 0; // Top left fill rule. 748e5c31af7Sopenharmony_ci float triX = triNdx ? 1.0f-xf : xf; 749e5c31af7Sopenharmony_ci float triY = triNdx ? 1.0f-yf : yf; 750e5c31af7Sopenharmony_ci 751e5c31af7Sopenharmony_ci float s = triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY); 752e5c31af7Sopenharmony_ci float t = triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY); 753e5c31af7Sopenharmony_ci float r = triangleInterpolate(triR[triNdx].x(), triR[triNdx].y(), triR[triNdx].z(), triX, triY); 754e5c31af7Sopenharmony_ci float lod = triLod[triNdx]; 755e5c31af7Sopenharmony_ci 756e5c31af7Sopenharmony_ci dst.setPixel(execSample(src, params, s, t, r, lod) * params.colorScale + params.colorBias, x, y); 757e5c31af7Sopenharmony_ci } 758e5c31af7Sopenharmony_ci } 759e5c31af7Sopenharmony_ci} 760e5c31af7Sopenharmony_ci 761e5c31af7Sopenharmony_civoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture2DArrayView& src, const float* texCoord, const ReferenceParams& params) 762e5c31af7Sopenharmony_ci{ 763e5c31af7Sopenharmony_ci tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]); 764e5c31af7Sopenharmony_ci tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]); 765e5c31af7Sopenharmony_ci tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]); 766e5c31af7Sopenharmony_ci 767e5c31af7Sopenharmony_ci DE_ASSERT(!(params.flags & ReferenceParams::PROJECTED)); // \todo [2012-02-17 pyry] Support projected lookups. 768e5c31af7Sopenharmony_ci sampleTextureNonProjected(dst, src, sq, tq, rq, params); 769e5c31af7Sopenharmony_ci} 770e5c31af7Sopenharmony_ci 771e5c31af7Sopenharmony_cistatic void sampleTextureNonProjected (const tcu::SurfaceAccess& dst, const tcu::Texture1DArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params) 772e5c31af7Sopenharmony_ci{ 773e5c31af7Sopenharmony_ci // Separate combined DS formats 774e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 775e5c31af7Sopenharmony_ci const tcu::Texture1DArrayView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 776e5c31af7Sopenharmony_ci 777e5c31af7Sopenharmony_ci float lodBias = (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f; 778e5c31af7Sopenharmony_ci 779e5c31af7Sopenharmony_ci tcu::IVec2 dstSize = tcu::IVec2(dst.getWidth(), dst.getHeight()); 780e5c31af7Sopenharmony_ci deInt32 srcSize = src.getWidth(); 781e5c31af7Sopenharmony_ci 782e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 783e5c31af7Sopenharmony_ci tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 784e5c31af7Sopenharmony_ci tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 785e5c31af7Sopenharmony_ci float triLod[2] = { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias, 786e5c31af7Sopenharmony_ci computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias}; 787e5c31af7Sopenharmony_ci 788e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 789e5c31af7Sopenharmony_ci { 790e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 791e5c31af7Sopenharmony_ci { 792e5c31af7Sopenharmony_ci float yf = ((float)y + 0.5f) / (float)dst.getHeight(); 793e5c31af7Sopenharmony_ci float xf = ((float)x + 0.5f) / (float)dst.getWidth(); 794e5c31af7Sopenharmony_ci 795e5c31af7Sopenharmony_ci int triNdx = xf + yf >= 1.0f ? 1 : 0; // Top left fill rule. 796e5c31af7Sopenharmony_ci float triX = triNdx ? 1.0f-xf : xf; 797e5c31af7Sopenharmony_ci float triY = triNdx ? 1.0f-yf : yf; 798e5c31af7Sopenharmony_ci 799e5c31af7Sopenharmony_ci float s = triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY); 800e5c31af7Sopenharmony_ci float t = triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY); 801e5c31af7Sopenharmony_ci float lod = triLod[triNdx]; 802e5c31af7Sopenharmony_ci 803e5c31af7Sopenharmony_ci dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, x, y); 804e5c31af7Sopenharmony_ci } 805e5c31af7Sopenharmony_ci } 806e5c31af7Sopenharmony_ci} 807e5c31af7Sopenharmony_ci 808e5c31af7Sopenharmony_civoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture1DArrayView& src, const float* texCoord, const ReferenceParams& params) 809e5c31af7Sopenharmony_ci{ 810e5c31af7Sopenharmony_ci tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]); 811e5c31af7Sopenharmony_ci tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]); 812e5c31af7Sopenharmony_ci 813e5c31af7Sopenharmony_ci DE_ASSERT(!(params.flags & ReferenceParams::PROJECTED)); // \todo [2014-06-09 mika] Support projected lookups. 814e5c31af7Sopenharmony_ci sampleTextureNonProjected(dst, src, sq, tq, params); 815e5c31af7Sopenharmony_ci} 816e5c31af7Sopenharmony_ci 817e5c31af7Sopenharmony_cistatic void sampleTextureNonProjected (const tcu::SurfaceAccess& dst, const tcu::Texture3DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params) 818e5c31af7Sopenharmony_ci{ 819e5c31af7Sopenharmony_ci // Separate combined DS formats 820e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 821e5c31af7Sopenharmony_ci const tcu::Texture3DView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 822e5c31af7Sopenharmony_ci 823e5c31af7Sopenharmony_ci float lodBias = (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f; 824e5c31af7Sopenharmony_ci 825e5c31af7Sopenharmony_ci tcu::IVec2 dstSize = tcu::IVec2(dst.getWidth(), dst.getHeight()); 826e5c31af7Sopenharmony_ci tcu::IVec3 srcSize = tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth()); 827e5c31af7Sopenharmony_ci 828e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 829e5c31af7Sopenharmony_ci tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 830e5c31af7Sopenharmony_ci tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 831e5c31af7Sopenharmony_ci tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 832e5c31af7Sopenharmony_ci float triLod[2] = { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0], triR[0]) + lodBias, params.minLod, params.maxLod), 833e5c31af7Sopenharmony_ci de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1], triR[1]) + lodBias, params.minLod, params.maxLod) }; 834e5c31af7Sopenharmony_ci 835e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 836e5c31af7Sopenharmony_ci { 837e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 838e5c31af7Sopenharmony_ci { 839e5c31af7Sopenharmony_ci float yf = ((float)y + 0.5f) / (float)dst.getHeight(); 840e5c31af7Sopenharmony_ci float xf = ((float)x + 0.5f) / (float)dst.getWidth(); 841e5c31af7Sopenharmony_ci 842e5c31af7Sopenharmony_ci int triNdx = xf + yf >= 1.0f ? 1 : 0; // Top left fill rule. 843e5c31af7Sopenharmony_ci float triX = triNdx ? 1.0f-xf : xf; 844e5c31af7Sopenharmony_ci float triY = triNdx ? 1.0f-yf : yf; 845e5c31af7Sopenharmony_ci 846e5c31af7Sopenharmony_ci float s = triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY); 847e5c31af7Sopenharmony_ci float t = triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY); 848e5c31af7Sopenharmony_ci float r = triangleInterpolate(triR[triNdx].x(), triR[triNdx].y(), triR[triNdx].z(), triX, triY); 849e5c31af7Sopenharmony_ci float lod = triLod[triNdx]; 850e5c31af7Sopenharmony_ci 851e5c31af7Sopenharmony_ci if (params.imageViewMinLod != 0.0f && params.samplerType == SAMPLERTYPE_FETCH_FLOAT) 852e5c31af7Sopenharmony_ci lod = (float)params.lodTexelFetch; 853e5c31af7Sopenharmony_ci 854e5c31af7Sopenharmony_ci dst.setPixel(src.sample(params.sampler, s, t, r, lod) * params.colorScale + params.colorBias, x, y); 855e5c31af7Sopenharmony_ci } 856e5c31af7Sopenharmony_ci } 857e5c31af7Sopenharmony_ci} 858e5c31af7Sopenharmony_ci 859e5c31af7Sopenharmony_cistatic void sampleTextureProjected (const tcu::SurfaceAccess& dst, const tcu::Texture3DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params) 860e5c31af7Sopenharmony_ci{ 861e5c31af7Sopenharmony_ci // Separate combined DS formats 862e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 863e5c31af7Sopenharmony_ci const tcu::Texture3DView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 864e5c31af7Sopenharmony_ci 865e5c31af7Sopenharmony_ci float lodBias = (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f; 866e5c31af7Sopenharmony_ci float dstW = (float)dst.getWidth(); 867e5c31af7Sopenharmony_ci float dstH = (float)dst.getHeight(); 868e5c31af7Sopenharmony_ci 869e5c31af7Sopenharmony_ci tcu::Vec4 uq = sq * (float)src.getWidth(); 870e5c31af7Sopenharmony_ci tcu::Vec4 vq = tq * (float)src.getHeight(); 871e5c31af7Sopenharmony_ci tcu::Vec4 wq = rq * (float)src.getDepth(); 872e5c31af7Sopenharmony_ci 873e5c31af7Sopenharmony_ci tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 874e5c31af7Sopenharmony_ci tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 875e5c31af7Sopenharmony_ci tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 876e5c31af7Sopenharmony_ci tcu::Vec3 triU[2] = { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) }; 877e5c31af7Sopenharmony_ci tcu::Vec3 triV[2] = { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) }; 878e5c31af7Sopenharmony_ci tcu::Vec3 triW[2] = { wq.swizzle(0, 1, 2), wq.swizzle(3, 2, 1) }; 879e5c31af7Sopenharmony_ci tcu::Vec3 triP[2] = { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) }; 880e5c31af7Sopenharmony_ci 881e5c31af7Sopenharmony_ci for (int py = 0; py < dst.getHeight(); py++) 882e5c31af7Sopenharmony_ci { 883e5c31af7Sopenharmony_ci for (int px = 0; px < dst.getWidth(); px++) 884e5c31af7Sopenharmony_ci { 885e5c31af7Sopenharmony_ci float wx = (float)px + 0.5f; 886e5c31af7Sopenharmony_ci float wy = (float)py + 0.5f; 887e5c31af7Sopenharmony_ci float nx = wx / dstW; 888e5c31af7Sopenharmony_ci float ny = wy / dstH; 889e5c31af7Sopenharmony_ci 890e5c31af7Sopenharmony_ci int triNdx = nx + ny >= 1.0f ? 1 : 0; 891e5c31af7Sopenharmony_ci float triWx = triNdx ? dstW - wx : wx; 892e5c31af7Sopenharmony_ci float triWy = triNdx ? dstH - wy : wy; 893e5c31af7Sopenharmony_ci float triNx = triNdx ? 1.0f - nx : nx; 894e5c31af7Sopenharmony_ci float triNy = triNdx ? 1.0f - ny : ny; 895e5c31af7Sopenharmony_ci 896e5c31af7Sopenharmony_ci float s = projectedTriInterpolate(triS[triNdx], triP[triNdx], triNx, triNy); 897e5c31af7Sopenharmony_ci float t = projectedTriInterpolate(triT[triNdx], triP[triNdx], triNx, triNy); 898e5c31af7Sopenharmony_ci float r = projectedTriInterpolate(triR[triNdx], triP[triNdx], triNx, triNy); 899e5c31af7Sopenharmony_ci float lod = computeProjectedTriLod(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triP[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight()) 900e5c31af7Sopenharmony_ci + lodBias; 901e5c31af7Sopenharmony_ci 902e5c31af7Sopenharmony_ci dst.setPixel(src.sample(params.sampler, s, t, r, lod) * params.colorScale + params.colorBias, px, py); 903e5c31af7Sopenharmony_ci } 904e5c31af7Sopenharmony_ci } 905e5c31af7Sopenharmony_ci} 906e5c31af7Sopenharmony_ci 907e5c31af7Sopenharmony_civoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture3DView& src, const float* texCoord, const ReferenceParams& params) 908e5c31af7Sopenharmony_ci{ 909e5c31af7Sopenharmony_ci tcu::ImageViewMinLodParams minLodParams = 910e5c31af7Sopenharmony_ci { 911e5c31af7Sopenharmony_ci params.baseLevel, // int baseLevel; 912e5c31af7Sopenharmony_ci { 913e5c31af7Sopenharmony_ci params.imageViewMinLod, // float minLod; 914e5c31af7Sopenharmony_ci params.imageViewMinLodMode, // ImageViewMinLodMode 915e5c31af7Sopenharmony_ci }, 916e5c31af7Sopenharmony_ci params.samplerType == SAMPLERTYPE_FETCH_FLOAT // bool intTexCoord; 917e5c31af7Sopenharmony_ci }; 918e5c31af7Sopenharmony_ci 919e5c31af7Sopenharmony_ci const tcu::Texture3DView view = getSubView(src, params.baseLevel, params.maxLevel, params.imageViewMinLod != 0.0f ? &minLodParams : DE_NULL); 920e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]); 921e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]); 922e5c31af7Sopenharmony_ci const tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]); 923e5c31af7Sopenharmony_ci 924e5c31af7Sopenharmony_ci if (params.flags & ReferenceParams::PROJECTED) 925e5c31af7Sopenharmony_ci sampleTextureProjected(dst, view, sq, tq, rq, params); 926e5c31af7Sopenharmony_ci else 927e5c31af7Sopenharmony_ci sampleTextureNonProjected(dst, view, sq, tq, rq, params); 928e5c31af7Sopenharmony_ci} 929e5c31af7Sopenharmony_ci 930e5c31af7Sopenharmony_cistatic void sampleTextureCubeArray (const tcu::SurfaceAccess& dst, const tcu::TextureCubeArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const tcu::Vec4& qq, const ReferenceParams& params) 931e5c31af7Sopenharmony_ci{ 932e5c31af7Sopenharmony_ci // Separate combined DS formats 933e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 934e5c31af7Sopenharmony_ci const tcu::TextureCubeArrayView src = getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler); 935e5c31af7Sopenharmony_ci 936e5c31af7Sopenharmony_ci const float dstW = (float)dst.getWidth(); 937e5c31af7Sopenharmony_ci const float dstH = (float)dst.getHeight(); 938e5c31af7Sopenharmony_ci 939e5c31af7Sopenharmony_ci // Coordinates per triangle. 940e5c31af7Sopenharmony_ci tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 941e5c31af7Sopenharmony_ci tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 942e5c31af7Sopenharmony_ci tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 943e5c31af7Sopenharmony_ci tcu::Vec3 triQ[2] = { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) }; 944e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) }; 945e5c31af7Sopenharmony_ci 946e5c31af7Sopenharmony_ci const float lodBias = (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f; 947e5c31af7Sopenharmony_ci 948e5c31af7Sopenharmony_ci for (int py = 0; py < dst.getHeight(); py++) 949e5c31af7Sopenharmony_ci { 950e5c31af7Sopenharmony_ci for (int px = 0; px < dst.getWidth(); px++) 951e5c31af7Sopenharmony_ci { 952e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 953e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 954e5c31af7Sopenharmony_ci const float nx = wx / dstW; 955e5c31af7Sopenharmony_ci const float ny = wy / dstH; 956e5c31af7Sopenharmony_ci 957e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 958e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 959e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 960e5c31af7Sopenharmony_ci 961e5c31af7Sopenharmony_ci const tcu::Vec3 coord (triangleInterpolate(triS[triNdx], triNx, triNy), 962e5c31af7Sopenharmony_ci triangleInterpolate(triT[triNdx], triNx, triNy), 963e5c31af7Sopenharmony_ci triangleInterpolate(triR[triNdx], triNx, triNy)); 964e5c31af7Sopenharmony_ci 965e5c31af7Sopenharmony_ci const float coordQ = triangleInterpolate(triQ[triNdx], triNx, triNy); 966e5c31af7Sopenharmony_ci 967e5c31af7Sopenharmony_ci const tcu::Vec3 coordDx (triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 968e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy), 969e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)); 970e5c31af7Sopenharmony_ci const tcu::Vec3 coordDy (triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 971e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx), 972e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)); 973e5c31af7Sopenharmony_ci 974e5c31af7Sopenharmony_ci const float lod = de::clamp(computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, src.getSize()) + lodBias, params.minLod, params.maxLod); 975e5c31af7Sopenharmony_ci 976e5c31af7Sopenharmony_ci dst.setPixel(execSample(src, params, coord.x(), coord.y(), coord.z(), coordQ, lod) * params.colorScale + params.colorBias, px, py); 977e5c31af7Sopenharmony_ci } 978e5c31af7Sopenharmony_ci } 979e5c31af7Sopenharmony_ci} 980e5c31af7Sopenharmony_ci 981e5c31af7Sopenharmony_civoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::TextureCubeArrayView& src, const float* texCoord, const ReferenceParams& params) 982e5c31af7Sopenharmony_ci{ 983e5c31af7Sopenharmony_ci tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]); 984e5c31af7Sopenharmony_ci tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]); 985e5c31af7Sopenharmony_ci tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]); 986e5c31af7Sopenharmony_ci tcu::Vec4 qq = tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]); 987e5c31af7Sopenharmony_ci 988e5c31af7Sopenharmony_ci sampleTextureCubeArray(dst, src, sq, tq, rq, qq, params); 989e5c31af7Sopenharmony_ci} 990e5c31af7Sopenharmony_ci 991e5c31af7Sopenharmony_civoid fetchTexture (const tcu::SurfaceAccess& dst, const tcu::ConstPixelBufferAccess& src, const float* texCoord, const tcu::Vec4& colorScale, const tcu::Vec4& colorBias) 992e5c31af7Sopenharmony_ci{ 993e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]); 994e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 995e5c31af7Sopenharmony_ci 996e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 997e5c31af7Sopenharmony_ci { 998e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 999e5c31af7Sopenharmony_ci { 1000e5c31af7Sopenharmony_ci const float yf = ((float)y + 0.5f) / (float)dst.getHeight(); 1001e5c31af7Sopenharmony_ci const float xf = ((float)x + 0.5f) / (float)dst.getWidth(); 1002e5c31af7Sopenharmony_ci 1003e5c31af7Sopenharmony_ci const int triNdx = xf + yf >= 1.0f ? 1 : 0; // Top left fill rule. 1004e5c31af7Sopenharmony_ci const float triX = triNdx ? 1.0f-xf : xf; 1005e5c31af7Sopenharmony_ci const float triY = triNdx ? 1.0f-yf : yf; 1006e5c31af7Sopenharmony_ci 1007e5c31af7Sopenharmony_ci const float s = triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY); 1008e5c31af7Sopenharmony_ci 1009e5c31af7Sopenharmony_ci dst.setPixel(src.getPixel((int)s, 0) * colorScale + colorBias, x, y); 1010e5c31af7Sopenharmony_ci } 1011e5c31af7Sopenharmony_ci } 1012e5c31af7Sopenharmony_ci} 1013e5c31af7Sopenharmony_ci 1014e5c31af7Sopenharmony_cibool compareImages (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& rendered, tcu::RGBA threshold) 1015e5c31af7Sopenharmony_ci{ 1016e5c31af7Sopenharmony_ci return tcu::pixelThresholdCompare(log, "Result", "Image comparison result", reference, rendered, threshold, tcu::COMPARE_LOG_RESULT); 1017e5c31af7Sopenharmony_ci} 1018e5c31af7Sopenharmony_ci 1019e5c31af7Sopenharmony_cibool compareImages (tcu::TestLog& log, const char* name, const char* desc, const tcu::Surface& reference, const tcu::Surface& rendered, tcu::RGBA threshold) 1020e5c31af7Sopenharmony_ci{ 1021e5c31af7Sopenharmony_ci return tcu::pixelThresholdCompare(log, name, desc, reference, rendered, threshold, tcu::COMPARE_LOG_RESULT); 1022e5c31af7Sopenharmony_ci} 1023e5c31af7Sopenharmony_ci 1024e5c31af7Sopenharmony_ciint measureAccuracy (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& rendered, int bestScoreDiff, int worstScoreDiff) 1025e5c31af7Sopenharmony_ci{ 1026e5c31af7Sopenharmony_ci return tcu::measurePixelDiffAccuracy(log, "Result", "Image comparison result", reference, rendered, bestScoreDiff, worstScoreDiff, tcu::COMPARE_LOG_EVERYTHING); 1027e5c31af7Sopenharmony_ci} 1028e5c31af7Sopenharmony_ci 1029e5c31af7Sopenharmony_ciinline int rangeDiff (int x, int a, int b) 1030e5c31af7Sopenharmony_ci{ 1031e5c31af7Sopenharmony_ci if (x < a) 1032e5c31af7Sopenharmony_ci return a-x; 1033e5c31af7Sopenharmony_ci else if (x > b) 1034e5c31af7Sopenharmony_ci return x-b; 1035e5c31af7Sopenharmony_ci else 1036e5c31af7Sopenharmony_ci return 0; 1037e5c31af7Sopenharmony_ci} 1038e5c31af7Sopenharmony_ci 1039e5c31af7Sopenharmony_ciinline tcu::RGBA rangeDiff (tcu::RGBA p, tcu::RGBA a, tcu::RGBA b) 1040e5c31af7Sopenharmony_ci{ 1041e5c31af7Sopenharmony_ci int rMin = de::min(a.getRed(), b.getRed()); 1042e5c31af7Sopenharmony_ci int rMax = de::max(a.getRed(), b.getRed()); 1043e5c31af7Sopenharmony_ci int gMin = de::min(a.getGreen(), b.getGreen()); 1044e5c31af7Sopenharmony_ci int gMax = de::max(a.getGreen(), b.getGreen()); 1045e5c31af7Sopenharmony_ci int bMin = de::min(a.getBlue(), b.getBlue()); 1046e5c31af7Sopenharmony_ci int bMax = de::max(a.getBlue(), b.getBlue()); 1047e5c31af7Sopenharmony_ci int aMin = de::min(a.getAlpha(), b.getAlpha()); 1048e5c31af7Sopenharmony_ci int aMax = de::max(a.getAlpha(), b.getAlpha()); 1049e5c31af7Sopenharmony_ci 1050e5c31af7Sopenharmony_ci return tcu::RGBA(rangeDiff(p.getRed(), rMin, rMax), 1051e5c31af7Sopenharmony_ci rangeDiff(p.getGreen(), gMin, gMax), 1052e5c31af7Sopenharmony_ci rangeDiff(p.getBlue(), bMin, bMax), 1053e5c31af7Sopenharmony_ci rangeDiff(p.getAlpha(), aMin, aMax)); 1054e5c31af7Sopenharmony_ci} 1055e5c31af7Sopenharmony_ci 1056e5c31af7Sopenharmony_ciinline bool rangeCompare (tcu::RGBA p, tcu::RGBA a, tcu::RGBA b, tcu::RGBA threshold) 1057e5c31af7Sopenharmony_ci{ 1058e5c31af7Sopenharmony_ci tcu::RGBA diff = rangeDiff(p, a, b); 1059e5c31af7Sopenharmony_ci return diff.getRed() <= threshold.getRed() && 1060e5c31af7Sopenharmony_ci diff.getGreen() <= threshold.getGreen() && 1061e5c31af7Sopenharmony_ci diff.getBlue() <= threshold.getBlue() && 1062e5c31af7Sopenharmony_ci diff.getAlpha() <= threshold.getAlpha(); 1063e5c31af7Sopenharmony_ci} 1064e5c31af7Sopenharmony_ci 1065e5c31af7Sopenharmony_civoid computeQuadTexCoord1D (std::vector<float>& dst, float left, float right) 1066e5c31af7Sopenharmony_ci{ 1067e5c31af7Sopenharmony_ci dst.resize(4); 1068e5c31af7Sopenharmony_ci 1069e5c31af7Sopenharmony_ci dst[0] = left; 1070e5c31af7Sopenharmony_ci dst[1] = left; 1071e5c31af7Sopenharmony_ci dst[2] = right; 1072e5c31af7Sopenharmony_ci dst[3] = right; 1073e5c31af7Sopenharmony_ci} 1074e5c31af7Sopenharmony_ci 1075e5c31af7Sopenharmony_civoid computeQuadTexCoord1DArray (std::vector<float>& dst, int layerNdx, float left, float right) 1076e5c31af7Sopenharmony_ci{ 1077e5c31af7Sopenharmony_ci dst.resize(4*2); 1078e5c31af7Sopenharmony_ci 1079e5c31af7Sopenharmony_ci dst[0] = left; dst[1] = (float)layerNdx; 1080e5c31af7Sopenharmony_ci dst[2] = left; dst[3] = (float)layerNdx; 1081e5c31af7Sopenharmony_ci dst[4] = right; dst[5] = (float)layerNdx; 1082e5c31af7Sopenharmony_ci dst[6] = right; dst[7] = (float)layerNdx; 1083e5c31af7Sopenharmony_ci} 1084e5c31af7Sopenharmony_ci 1085e5c31af7Sopenharmony_civoid computeQuadTexCoord2D (std::vector<float>& dst, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight) 1086e5c31af7Sopenharmony_ci{ 1087e5c31af7Sopenharmony_ci dst.resize(4*2); 1088e5c31af7Sopenharmony_ci 1089e5c31af7Sopenharmony_ci dst[0] = bottomLeft.x(); dst[1] = bottomLeft.y(); 1090e5c31af7Sopenharmony_ci dst[2] = bottomLeft.x(); dst[3] = topRight.y(); 1091e5c31af7Sopenharmony_ci dst[4] = topRight.x(); dst[5] = bottomLeft.y(); 1092e5c31af7Sopenharmony_ci dst[6] = topRight.x(); dst[7] = topRight.y(); 1093e5c31af7Sopenharmony_ci} 1094e5c31af7Sopenharmony_ci 1095e5c31af7Sopenharmony_civoid computeQuadTexCoord2DArray (std::vector<float>& dst, int layerNdx, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight) 1096e5c31af7Sopenharmony_ci{ 1097e5c31af7Sopenharmony_ci dst.resize(4*3); 1098e5c31af7Sopenharmony_ci 1099e5c31af7Sopenharmony_ci dst[0] = bottomLeft.x(); dst[ 1] = bottomLeft.y(); dst[ 2] = (float)layerNdx; 1100e5c31af7Sopenharmony_ci dst[3] = bottomLeft.x(); dst[ 4] = topRight.y(); dst[ 5] = (float)layerNdx; 1101e5c31af7Sopenharmony_ci dst[6] = topRight.x(); dst[ 7] = bottomLeft.y(); dst[ 8] = (float)layerNdx; 1102e5c31af7Sopenharmony_ci dst[9] = topRight.x(); dst[10] = topRight.y(); dst[11] = (float)layerNdx; 1103e5c31af7Sopenharmony_ci} 1104e5c31af7Sopenharmony_ci 1105e5c31af7Sopenharmony_civoid computeQuadTexCoord3D (std::vector<float>& dst, const tcu::Vec3& p0, const tcu::Vec3& p1, const tcu::IVec3& dirSwz) 1106e5c31af7Sopenharmony_ci{ 1107e5c31af7Sopenharmony_ci tcu::Vec3 f0 = tcu::Vec3(0.0f, 0.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]); 1108e5c31af7Sopenharmony_ci tcu::Vec3 f1 = tcu::Vec3(0.0f, 1.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]); 1109e5c31af7Sopenharmony_ci tcu::Vec3 f2 = tcu::Vec3(1.0f, 0.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]); 1110e5c31af7Sopenharmony_ci tcu::Vec3 f3 = tcu::Vec3(1.0f, 1.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]); 1111e5c31af7Sopenharmony_ci 1112e5c31af7Sopenharmony_ci tcu::Vec3 v0 = p0 + (p1-p0)*f0; 1113e5c31af7Sopenharmony_ci tcu::Vec3 v1 = p0 + (p1-p0)*f1; 1114e5c31af7Sopenharmony_ci tcu::Vec3 v2 = p0 + (p1-p0)*f2; 1115e5c31af7Sopenharmony_ci tcu::Vec3 v3 = p0 + (p1-p0)*f3; 1116e5c31af7Sopenharmony_ci 1117e5c31af7Sopenharmony_ci dst.resize(4*3); 1118e5c31af7Sopenharmony_ci 1119e5c31af7Sopenharmony_ci dst[0] = v0.x(); dst[ 1] = v0.y(); dst[ 2] = v0.z(); 1120e5c31af7Sopenharmony_ci dst[3] = v1.x(); dst[ 4] = v1.y(); dst[ 5] = v1.z(); 1121e5c31af7Sopenharmony_ci dst[6] = v2.x(); dst[ 7] = v2.y(); dst[ 8] = v2.z(); 1122e5c31af7Sopenharmony_ci dst[9] = v3.x(); dst[10] = v3.y(); dst[11] = v3.z(); 1123e5c31af7Sopenharmony_ci} 1124e5c31af7Sopenharmony_ci 1125e5c31af7Sopenharmony_civoid computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face) 1126e5c31af7Sopenharmony_ci{ 1127e5c31af7Sopenharmony_ci static const float texCoordNegX[] = 1128e5c31af7Sopenharmony_ci { 1129e5c31af7Sopenharmony_ci -1.0f, 1.0f, -1.0f, 1130e5c31af7Sopenharmony_ci -1.0f, -1.0f, -1.0f, 1131e5c31af7Sopenharmony_ci -1.0f, 1.0f, 1.0f, 1132e5c31af7Sopenharmony_ci -1.0f, -1.0f, 1.0f 1133e5c31af7Sopenharmony_ci }; 1134e5c31af7Sopenharmony_ci static const float texCoordPosX[] = 1135e5c31af7Sopenharmony_ci { 1136e5c31af7Sopenharmony_ci +1.0f, 1.0f, 1.0f, 1137e5c31af7Sopenharmony_ci +1.0f, -1.0f, 1.0f, 1138e5c31af7Sopenharmony_ci +1.0f, 1.0f, -1.0f, 1139e5c31af7Sopenharmony_ci +1.0f, -1.0f, -1.0f 1140e5c31af7Sopenharmony_ci }; 1141e5c31af7Sopenharmony_ci static const float texCoordNegY[] = 1142e5c31af7Sopenharmony_ci { 1143e5c31af7Sopenharmony_ci -1.0f, -1.0f, 1.0f, 1144e5c31af7Sopenharmony_ci -1.0f, -1.0f, -1.0f, 1145e5c31af7Sopenharmony_ci 1.0f, -1.0f, 1.0f, 1146e5c31af7Sopenharmony_ci 1.0f, -1.0f, -1.0f 1147e5c31af7Sopenharmony_ci }; 1148e5c31af7Sopenharmony_ci static const float texCoordPosY[] = 1149e5c31af7Sopenharmony_ci { 1150e5c31af7Sopenharmony_ci -1.0f, +1.0f, -1.0f, 1151e5c31af7Sopenharmony_ci -1.0f, +1.0f, 1.0f, 1152e5c31af7Sopenharmony_ci 1.0f, +1.0f, -1.0f, 1153e5c31af7Sopenharmony_ci 1.0f, +1.0f, 1.0f 1154e5c31af7Sopenharmony_ci }; 1155e5c31af7Sopenharmony_ci static const float texCoordNegZ[] = 1156e5c31af7Sopenharmony_ci { 1157e5c31af7Sopenharmony_ci 1.0f, 1.0f, -1.0f, 1158e5c31af7Sopenharmony_ci 1.0f, -1.0f, -1.0f, 1159e5c31af7Sopenharmony_ci -1.0f, 1.0f, -1.0f, 1160e5c31af7Sopenharmony_ci -1.0f, -1.0f, -1.0f 1161e5c31af7Sopenharmony_ci }; 1162e5c31af7Sopenharmony_ci static const float texCoordPosZ[] = 1163e5c31af7Sopenharmony_ci { 1164e5c31af7Sopenharmony_ci -1.0f, 1.0f, +1.0f, 1165e5c31af7Sopenharmony_ci -1.0f, -1.0f, +1.0f, 1166e5c31af7Sopenharmony_ci 1.0f, 1.0f, +1.0f, 1167e5c31af7Sopenharmony_ci 1.0f, -1.0f, +1.0f 1168e5c31af7Sopenharmony_ci }; 1169e5c31af7Sopenharmony_ci 1170e5c31af7Sopenharmony_ci const float* texCoord = DE_NULL; 1171e5c31af7Sopenharmony_ci int texCoordSize = DE_LENGTH_OF_ARRAY(texCoordNegX); 1172e5c31af7Sopenharmony_ci 1173e5c31af7Sopenharmony_ci switch (face) 1174e5c31af7Sopenharmony_ci { 1175e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_X: texCoord = texCoordNegX; break; 1176e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_X: texCoord = texCoordPosX; break; 1177e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Y: texCoord = texCoordNegY; break; 1178e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Y: texCoord = texCoordPosY; break; 1179e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Z: texCoord = texCoordNegZ; break; 1180e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Z: texCoord = texCoordPosZ; break; 1181e5c31af7Sopenharmony_ci default: 1182e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1183e5c31af7Sopenharmony_ci return; 1184e5c31af7Sopenharmony_ci } 1185e5c31af7Sopenharmony_ci 1186e5c31af7Sopenharmony_ci dst.resize(texCoordSize); 1187e5c31af7Sopenharmony_ci std::copy(texCoord, texCoord+texCoordSize, dst.begin()); 1188e5c31af7Sopenharmony_ci} 1189e5c31af7Sopenharmony_ci 1190e5c31af7Sopenharmony_civoid computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight) 1191e5c31af7Sopenharmony_ci{ 1192e5c31af7Sopenharmony_ci int sRow = 0; 1193e5c31af7Sopenharmony_ci int tRow = 0; 1194e5c31af7Sopenharmony_ci int mRow = 0; 1195e5c31af7Sopenharmony_ci float sSign = 1.0f; 1196e5c31af7Sopenharmony_ci float tSign = 1.0f; 1197e5c31af7Sopenharmony_ci float mSign = 1.0f; 1198e5c31af7Sopenharmony_ci 1199e5c31af7Sopenharmony_ci switch (face) 1200e5c31af7Sopenharmony_ci { 1201e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f; tSign = -1.0f; break; 1202e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1; sSign = -1.0f; tSign = -1.0f; break; 1203e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f; tSign = -1.0f; break; 1204e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2; break; 1205e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f; break; 1206e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1; tSign = -1.0f; break; 1207e5c31af7Sopenharmony_ci default: 1208e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1209e5c31af7Sopenharmony_ci return; 1210e5c31af7Sopenharmony_ci } 1211e5c31af7Sopenharmony_ci 1212e5c31af7Sopenharmony_ci dst.resize(3*4); 1213e5c31af7Sopenharmony_ci 1214e5c31af7Sopenharmony_ci dst[0+mRow] = mSign; 1215e5c31af7Sopenharmony_ci dst[3+mRow] = mSign; 1216e5c31af7Sopenharmony_ci dst[6+mRow] = mSign; 1217e5c31af7Sopenharmony_ci dst[9+mRow] = mSign; 1218e5c31af7Sopenharmony_ci 1219e5c31af7Sopenharmony_ci dst[0+sRow] = sSign * bottomLeft.x(); 1220e5c31af7Sopenharmony_ci dst[3+sRow] = sSign * bottomLeft.x(); 1221e5c31af7Sopenharmony_ci dst[6+sRow] = sSign * topRight.x(); 1222e5c31af7Sopenharmony_ci dst[9+sRow] = sSign * topRight.x(); 1223e5c31af7Sopenharmony_ci 1224e5c31af7Sopenharmony_ci dst[0+tRow] = tSign * bottomLeft.y(); 1225e5c31af7Sopenharmony_ci dst[3+tRow] = tSign * topRight.y(); 1226e5c31af7Sopenharmony_ci dst[6+tRow] = tSign * bottomLeft.y(); 1227e5c31af7Sopenharmony_ci dst[9+tRow] = tSign * topRight.y(); 1228e5c31af7Sopenharmony_ci} 1229e5c31af7Sopenharmony_ci 1230e5c31af7Sopenharmony_civoid computeQuadTexCoordCubeArray (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight, const tcu::Vec2& layerRange) 1231e5c31af7Sopenharmony_ci{ 1232e5c31af7Sopenharmony_ci int sRow = 0; 1233e5c31af7Sopenharmony_ci int tRow = 0; 1234e5c31af7Sopenharmony_ci int mRow = 0; 1235e5c31af7Sopenharmony_ci const int qRow = 3; 1236e5c31af7Sopenharmony_ci float sSign = 1.0f; 1237e5c31af7Sopenharmony_ci float tSign = 1.0f; 1238e5c31af7Sopenharmony_ci float mSign = 1.0f; 1239e5c31af7Sopenharmony_ci const float l0 = layerRange.x(); 1240e5c31af7Sopenharmony_ci const float l1 = layerRange.y(); 1241e5c31af7Sopenharmony_ci 1242e5c31af7Sopenharmony_ci switch (face) 1243e5c31af7Sopenharmony_ci { 1244e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f; tSign = -1.0f; break; 1245e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1; sSign = -1.0f; tSign = -1.0f; break; 1246e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f; tSign = -1.0f; break; 1247e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2; break; 1248e5c31af7Sopenharmony_ci case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f; break; 1249e5c31af7Sopenharmony_ci case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1; tSign = -1.0f; break; 1250e5c31af7Sopenharmony_ci default: 1251e5c31af7Sopenharmony_ci DE_ASSERT(DE_FALSE); 1252e5c31af7Sopenharmony_ci return; 1253e5c31af7Sopenharmony_ci } 1254e5c31af7Sopenharmony_ci 1255e5c31af7Sopenharmony_ci dst.resize(4*4); 1256e5c31af7Sopenharmony_ci 1257e5c31af7Sopenharmony_ci dst[ 0+mRow] = mSign; 1258e5c31af7Sopenharmony_ci dst[ 4+mRow] = mSign; 1259e5c31af7Sopenharmony_ci dst[ 8+mRow] = mSign; 1260e5c31af7Sopenharmony_ci dst[12+mRow] = mSign; 1261e5c31af7Sopenharmony_ci 1262e5c31af7Sopenharmony_ci dst[ 0+sRow] = sSign * bottomLeft.x(); 1263e5c31af7Sopenharmony_ci dst[ 4+sRow] = sSign * bottomLeft.x(); 1264e5c31af7Sopenharmony_ci dst[ 8+sRow] = sSign * topRight.x(); 1265e5c31af7Sopenharmony_ci dst[12+sRow] = sSign * topRight.x(); 1266e5c31af7Sopenharmony_ci 1267e5c31af7Sopenharmony_ci dst[ 0+tRow] = tSign * bottomLeft.y(); 1268e5c31af7Sopenharmony_ci dst[ 4+tRow] = tSign * topRight.y(); 1269e5c31af7Sopenharmony_ci dst[ 8+tRow] = tSign * bottomLeft.y(); 1270e5c31af7Sopenharmony_ci dst[12+tRow] = tSign * topRight.y(); 1271e5c31af7Sopenharmony_ci 1272e5c31af7Sopenharmony_ci if (l0 != l1) 1273e5c31af7Sopenharmony_ci { 1274e5c31af7Sopenharmony_ci dst[ 0+qRow] = l0; 1275e5c31af7Sopenharmony_ci dst[ 4+qRow] = l0*0.5f + l1*0.5f; 1276e5c31af7Sopenharmony_ci dst[ 8+qRow] = l0*0.5f + l1*0.5f; 1277e5c31af7Sopenharmony_ci dst[12+qRow] = l1; 1278e5c31af7Sopenharmony_ci } 1279e5c31af7Sopenharmony_ci else 1280e5c31af7Sopenharmony_ci { 1281e5c31af7Sopenharmony_ci dst[ 0+qRow] = l0; 1282e5c31af7Sopenharmony_ci dst[ 4+qRow] = l0; 1283e5c31af7Sopenharmony_ci dst[ 8+qRow] = l0; 1284e5c31af7Sopenharmony_ci dst[12+qRow] = l0; 1285e5c31af7Sopenharmony_ci } 1286e5c31af7Sopenharmony_ci} 1287e5c31af7Sopenharmony_ci 1288e5c31af7Sopenharmony_ci// Texture result verification 1289e5c31af7Sopenharmony_ci 1290e5c31af7Sopenharmony_ci//! Verifies texture lookup results and returns number of failed pixels. 1291e5c31af7Sopenharmony_ciint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess& result, 1292e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 1293e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 1294e5c31af7Sopenharmony_ci const tcu::Texture1DView& baseView, 1295e5c31af7Sopenharmony_ci const float* texCoord, 1296e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 1297e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 1298e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 1299e5c31af7Sopenharmony_ci qpWatchDog* watchDog) 1300e5c31af7Sopenharmony_ci{ 1301e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 1302e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 1303e5c31af7Sopenharmony_ci 1304e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 1305e5c31af7Sopenharmony_ci const tcu::Texture1DView src = getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel, DE_NULL), srcLevelStorage, sampleParams.sampler); 1306e5c31af7Sopenharmony_ci 1307e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]); 1308e5c31af7Sopenharmony_ci 1309e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 1310e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 1311e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 1312e5c31af7Sopenharmony_ci const int srcSize = src.getWidth(); 1313e5c31af7Sopenharmony_ci 1314e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 1315e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 1316e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 1317e5c31af7Sopenharmony_ci 1318e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 1319e5c31af7Sopenharmony_ci 1320e5c31af7Sopenharmony_ci int numFailed = 0; 1321e5c31af7Sopenharmony_ci 1322e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 1323e5c31af7Sopenharmony_ci { 1324e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 1325e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 1326e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 1327e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 1328e5c31af7Sopenharmony_ci }; 1329e5c31af7Sopenharmony_ci 1330e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 1331e5c31af7Sopenharmony_ci 1332e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 1333e5c31af7Sopenharmony_ci { 1334e5c31af7Sopenharmony_ci // Ugly hack, validation can take way too long at the moment. 1335e5c31af7Sopenharmony_ci if (watchDog) 1336e5c31af7Sopenharmony_ci qpWatchDog_touch(watchDog); 1337e5c31af7Sopenharmony_ci 1338e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 1339e5c31af7Sopenharmony_ci { 1340e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = (result.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 1341e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = (reference.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 1342e5c31af7Sopenharmony_ci 1343e5c31af7Sopenharmony_ci // Try comparison to ideal reference first, and if that fails use slower verificator. 1344e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold))) 1345e5c31af7Sopenharmony_ci { 1346e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 1347e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 1348e5c31af7Sopenharmony_ci const float nx = wx / dstW; 1349e5c31af7Sopenharmony_ci const float ny = wy / dstH; 1350e5c31af7Sopenharmony_ci 1351e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 1352e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 1353e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 1354e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 1355e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 1356e5c31af7Sopenharmony_ci 1357e5c31af7Sopenharmony_ci const float coord = projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy); 1358e5c31af7Sopenharmony_ci const float coordDx = triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * float(srcSize); 1359e5c31af7Sopenharmony_ci const float coordDy = triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx) * float(srcSize); 1360e5c31af7Sopenharmony_ci 1361e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeLodBoundsFromDerivates(coordDx, coordDy, lodPrec); 1362e5c31af7Sopenharmony_ci 1363e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 1364e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 1365e5c31af7Sopenharmony_ci { 1366e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 1367e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 1368e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 1369e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 1370e5c31af7Sopenharmony_ci 1371e5c31af7Sopenharmony_ci const float coordDxo = triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * float(srcSize); 1372e5c31af7Sopenharmony_ci const float coordDyo = triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * float(srcSize); 1373e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec); 1374e5c31af7Sopenharmony_ci 1375e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 1376e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 1377e5c31af7Sopenharmony_ci } 1378e5c31af7Sopenharmony_ci 1379e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec); 1380e5c31af7Sopenharmony_ci const bool isOk = tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix); 1381e5c31af7Sopenharmony_ci 1382e5c31af7Sopenharmony_ci if (!isOk) 1383e5c31af7Sopenharmony_ci { 1384e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 1385e5c31af7Sopenharmony_ci numFailed += 1; 1386e5c31af7Sopenharmony_ci } 1387e5c31af7Sopenharmony_ci } 1388e5c31af7Sopenharmony_ci } 1389e5c31af7Sopenharmony_ci } 1390e5c31af7Sopenharmony_ci 1391e5c31af7Sopenharmony_ci return numFailed; 1392e5c31af7Sopenharmony_ci} 1393e5c31af7Sopenharmony_ci 1394e5c31af7Sopenharmony_ciint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess& result, 1395e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 1396e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 1397e5c31af7Sopenharmony_ci const tcu::Texture2DView& baseView, 1398e5c31af7Sopenharmony_ci const float* texCoord, 1399e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 1400e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 1401e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 1402e5c31af7Sopenharmony_ci qpWatchDog* watchDog) 1403e5c31af7Sopenharmony_ci{ 1404e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 1405e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 1406e5c31af7Sopenharmony_ci 1407e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 1408e5c31af7Sopenharmony_ci tcu::ImageViewMinLodParams minLodParams = 1409e5c31af7Sopenharmony_ci { 1410e5c31af7Sopenharmony_ci sampleParams.baseLevel, // int baseLevel; 1411e5c31af7Sopenharmony_ci { 1412e5c31af7Sopenharmony_ci sampleParams.imageViewMinLod, // float minLod; 1413e5c31af7Sopenharmony_ci sampleParams.imageViewMinLodMode, // ImageViewMinLodMode 1414e5c31af7Sopenharmony_ci }, 1415e5c31af7Sopenharmony_ci sampleParams.samplerType == SAMPLERTYPE_FETCH_FLOAT // bool intTexCoord; 1416e5c31af7Sopenharmony_ci }; 1417e5c31af7Sopenharmony_ci 1418e5c31af7Sopenharmony_ci const tcu::Texture2DView view = getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel, sampleParams.imageViewMinLod != 0.0f ? &minLodParams : DE_NULL); 1419e5c31af7Sopenharmony_ci 1420e5c31af7Sopenharmony_ci const tcu::Texture2DView src = getEffectiveTextureView(view, srcLevelStorage, sampleParams.sampler); 1421e5c31af7Sopenharmony_ci 1422e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]); 1423e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]); 1424e5c31af7Sopenharmony_ci 1425e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 1426e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 1427e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 1428e5c31af7Sopenharmony_ci const tcu::IVec2 srcSize = tcu::IVec2(src.getWidth(), src.getHeight()); 1429e5c31af7Sopenharmony_ci 1430e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 1431e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 1432e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 1433e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 1434e5c31af7Sopenharmony_ci 1435e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 1436e5c31af7Sopenharmony_ci 1437e5c31af7Sopenharmony_ci // imageViewMinLodRel is used to calculate the image level to sample from, when VK_EXT_image_view_min_lod extension is enabled. 1438e5c31af7Sopenharmony_ci // The value is relative to baseLevel as the Texture*View 'src' was created as the baseLevel being level[0]. 1439e5c31af7Sopenharmony_ci const float imageViewMinLodRel = sampleParams.imageViewMinLod - (float)sampleParams.baseLevel; 1440e5c31af7Sopenharmony_ci // We need to adapt ImageView's minLod value to the mipmap mdoe (i.e. nearest or linear) so we clamp with the right minLod value later. 1441e5c31af7Sopenharmony_ci const float imageViewMinLodRelMode = tcu::isSamplerMipmapModeLinear(sampleParams.sampler.minFilter) ? deFloatFloor(imageViewMinLodRel) : (float)deClamp32((int)deFloatCeil(imageViewMinLodRel + 0.5f) - 1, sampleParams.baseLevel, sampleParams.maxLevel); 1442e5c31af7Sopenharmony_ci const float minLod = (sampleParams.imageViewMinLod != 0.0f) ? de::max(imageViewMinLodRelMode, sampleParams.minLod) : sampleParams.minLod; 1443e5c31af7Sopenharmony_ci 1444e5c31af7Sopenharmony_ci const float posEps = 1.0f / float(1<<MIN_SUBPIXEL_BITS); 1445e5c31af7Sopenharmony_ci 1446e5c31af7Sopenharmony_ci int numFailed = 0; 1447e5c31af7Sopenharmony_ci 1448e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 1449e5c31af7Sopenharmony_ci { 1450e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 1451e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 1452e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 1453e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 1454e5c31af7Sopenharmony_ci }; 1455e5c31af7Sopenharmony_ci 1456e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 1457e5c31af7Sopenharmony_ci 1458e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 1459e5c31af7Sopenharmony_ci { 1460e5c31af7Sopenharmony_ci // Ugly hack, validation can take way too long at the moment. 1461e5c31af7Sopenharmony_ci if (watchDog) 1462e5c31af7Sopenharmony_ci qpWatchDog_touch(watchDog); 1463e5c31af7Sopenharmony_ci 1464e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 1465e5c31af7Sopenharmony_ci { 1466e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = (result.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 1467e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = (reference.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 1468e5c31af7Sopenharmony_ci 1469e5c31af7Sopenharmony_ci // Try comparison to ideal reference first, and if that fails use slower verificator. 1470e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold))) 1471e5c31af7Sopenharmony_ci { 1472e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 1473e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 1474e5c31af7Sopenharmony_ci const float nx = wx / dstW; 1475e5c31af7Sopenharmony_ci const float ny = wy / dstH; 1476e5c31af7Sopenharmony_ci 1477e5c31af7Sopenharmony_ci const bool tri0 = (wx-posEps)/dstW + (wy-posEps)/dstH <= 1.0f; 1478e5c31af7Sopenharmony_ci const bool tri1 = (wx+posEps)/dstW + (wy+posEps)/dstH >= 1.0f; 1479e5c31af7Sopenharmony_ci 1480e5c31af7Sopenharmony_ci bool isOk = false; 1481e5c31af7Sopenharmony_ci 1482e5c31af7Sopenharmony_ci DE_ASSERT(tri0 || tri1); 1483e5c31af7Sopenharmony_ci 1484e5c31af7Sopenharmony_ci // Pixel can belong to either of the triangles if it lies close enough to the edge. 1485e5c31af7Sopenharmony_ci for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++) 1486e5c31af7Sopenharmony_ci { 1487e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 1488e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 1489e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 1490e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 1491e5c31af7Sopenharmony_ci 1492e5c31af7Sopenharmony_ci const tcu::Vec2 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 1493e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy)); 1494e5c31af7Sopenharmony_ci const tcu::Vec2 coordDx = tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 1495e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat(); 1496e5c31af7Sopenharmony_ci const tcu::Vec2 coordDy = tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 1497e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat(); 1498e5c31af7Sopenharmony_ci 1499e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec); 1500e5c31af7Sopenharmony_ci 1501e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 1502e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 1503e5c31af7Sopenharmony_ci { 1504e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 1505e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 1506e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 1507e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 1508e5c31af7Sopenharmony_ci 1509e5c31af7Sopenharmony_ci const tcu::Vec2 coordDxo = tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), 1510e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat(); 1511e5c31af7Sopenharmony_ci const tcu::Vec2 coordDyo = tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), 1512e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat(); 1513e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec); 1514e5c31af7Sopenharmony_ci 1515e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 1516e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 1517e5c31af7Sopenharmony_ci } 1518e5c31af7Sopenharmony_ci 1519e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(minLod, sampleParams.maxLod), lodPrec); 1520e5c31af7Sopenharmony_ci if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix)) 1521e5c31af7Sopenharmony_ci { 1522e5c31af7Sopenharmony_ci isOk = true; 1523e5c31af7Sopenharmony_ci break; 1524e5c31af7Sopenharmony_ci } 1525e5c31af7Sopenharmony_ci } 1526e5c31af7Sopenharmony_ci 1527e5c31af7Sopenharmony_ci if (!isOk) 1528e5c31af7Sopenharmony_ci { 1529e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 1530e5c31af7Sopenharmony_ci numFailed += 1; 1531e5c31af7Sopenharmony_ci } 1532e5c31af7Sopenharmony_ci } 1533e5c31af7Sopenharmony_ci } 1534e5c31af7Sopenharmony_ci } 1535e5c31af7Sopenharmony_ci 1536e5c31af7Sopenharmony_ci return numFailed; 1537e5c31af7Sopenharmony_ci} 1538e5c31af7Sopenharmony_ci 1539e5c31af7Sopenharmony_cibool verifyTextureResult (tcu::TestContext& testCtx, 1540e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 1541e5c31af7Sopenharmony_ci const tcu::Texture1DView& src, 1542e5c31af7Sopenharmony_ci const float* texCoord, 1543e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 1544e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 1545e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 1546e5c31af7Sopenharmony_ci const tcu::PixelFormat& pixelFormat) 1547e5c31af7Sopenharmony_ci{ 1548e5c31af7Sopenharmony_ci tcu::TestLog& log = testCtx.getLog(); 1549e5c31af7Sopenharmony_ci tcu::Surface reference (result.getWidth(), result.getHeight()); 1550e5c31af7Sopenharmony_ci tcu::Surface errorMask (result.getWidth(), result.getHeight()); 1551e5c31af7Sopenharmony_ci int numFailedPixels; 1552e5c31af7Sopenharmony_ci 1553e5c31af7Sopenharmony_ci DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask); 1554e5c31af7Sopenharmony_ci 1555e5c31af7Sopenharmony_ci sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams); 1556e5c31af7Sopenharmony_ci numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog()); 1557e5c31af7Sopenharmony_ci 1558e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 1559e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 1560e5c31af7Sopenharmony_ci 1561e5c31af7Sopenharmony_ci log << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 1562e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Rendered", "Rendered image", result); 1563e5c31af7Sopenharmony_ci 1564e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 1565e5c31af7Sopenharmony_ci { 1566e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 1567e5c31af7Sopenharmony_ci << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 1568e5c31af7Sopenharmony_ci } 1569e5c31af7Sopenharmony_ci 1570e5c31af7Sopenharmony_ci log << tcu::TestLog::EndImageSet; 1571e5c31af7Sopenharmony_ci 1572e5c31af7Sopenharmony_ci return numFailedPixels == 0; 1573e5c31af7Sopenharmony_ci} 1574e5c31af7Sopenharmony_ci 1575e5c31af7Sopenharmony_cibool verifyTextureResult (tcu::TestContext& testCtx, 1576e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 1577e5c31af7Sopenharmony_ci const tcu::Texture2DView& src, 1578e5c31af7Sopenharmony_ci const float* texCoord, 1579e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 1580e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 1581e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 1582e5c31af7Sopenharmony_ci const tcu::PixelFormat& pixelFormat) 1583e5c31af7Sopenharmony_ci{ 1584e5c31af7Sopenharmony_ci tcu::TestLog& log = testCtx.getLog(); 1585e5c31af7Sopenharmony_ci tcu::Surface reference (result.getWidth(), result.getHeight()); 1586e5c31af7Sopenharmony_ci tcu::Surface errorMask (result.getWidth(), result.getHeight()); 1587e5c31af7Sopenharmony_ci int numFailedPixels; 1588e5c31af7Sopenharmony_ci 1589e5c31af7Sopenharmony_ci DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask); 1590e5c31af7Sopenharmony_ci 1591e5c31af7Sopenharmony_ci sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams); 1592e5c31af7Sopenharmony_ci numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog()); 1593e5c31af7Sopenharmony_ci 1594e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 1595e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 1596e5c31af7Sopenharmony_ci 1597e5c31af7Sopenharmony_ci log << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 1598e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Rendered", "Rendered image", result); 1599e5c31af7Sopenharmony_ci 1600e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 1601e5c31af7Sopenharmony_ci { 1602e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 1603e5c31af7Sopenharmony_ci << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 1604e5c31af7Sopenharmony_ci } 1605e5c31af7Sopenharmony_ci 1606e5c31af7Sopenharmony_ci log << tcu::TestLog::EndImageSet; 1607e5c31af7Sopenharmony_ci 1608e5c31af7Sopenharmony_ci return numFailedPixels == 0; 1609e5c31af7Sopenharmony_ci} 1610e5c31af7Sopenharmony_ci 1611e5c31af7Sopenharmony_ci//! Verifies texture lookup results and returns number of failed pixels. 1612e5c31af7Sopenharmony_ciint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess& result, 1613e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 1614e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 1615e5c31af7Sopenharmony_ci const tcu::TextureCubeView& baseView, 1616e5c31af7Sopenharmony_ci const float* texCoord, 1617e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 1618e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 1619e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 1620e5c31af7Sopenharmony_ci qpWatchDog* watchDog) 1621e5c31af7Sopenharmony_ci{ 1622e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 1623e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 1624e5c31af7Sopenharmony_ci 1625e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 1626e5c31af7Sopenharmony_ci tcu::ImageViewMinLodParams minLodParams = 1627e5c31af7Sopenharmony_ci { 1628e5c31af7Sopenharmony_ci sampleParams.baseLevel, // int baseLevel; 1629e5c31af7Sopenharmony_ci { 1630e5c31af7Sopenharmony_ci sampleParams.imageViewMinLod, // float minLod; 1631e5c31af7Sopenharmony_ci sampleParams.imageViewMinLodMode, // ImageViewMinLodMode 1632e5c31af7Sopenharmony_ci }, 1633e5c31af7Sopenharmony_ci sampleParams.samplerType == SAMPLERTYPE_FETCH_FLOAT // bool intTexCoord; 1634e5c31af7Sopenharmony_ci }; 1635e5c31af7Sopenharmony_ci 1636e5c31af7Sopenharmony_ci const tcu::TextureCubeView src = getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel, sampleParams.imageViewMinLod != 0.0f ? &minLodParams : DE_NULL), srcLevelStorage, sampleParams.sampler); 1637e5c31af7Sopenharmony_ci 1638e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]); 1639e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]); 1640e5c31af7Sopenharmony_ci const tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]); 1641e5c31af7Sopenharmony_ci 1642e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 1643e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 1644e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 1645e5c31af7Sopenharmony_ci const int srcSize = src.getSize(); 1646e5c31af7Sopenharmony_ci 1647e5c31af7Sopenharmony_ci // Coordinates per triangle. 1648e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 1649e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 1650e5c31af7Sopenharmony_ci const tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 1651e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 1652e5c31af7Sopenharmony_ci 1653e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 1654e5c31af7Sopenharmony_ci 1655e5c31af7Sopenharmony_ci const float posEps = 1.0f / float(1<<MIN_SUBPIXEL_BITS); 1656e5c31af7Sopenharmony_ci 1657e5c31af7Sopenharmony_ci // imageViewMinLodRel is used to calculate the image level to sample from, when VK_EXT_image_view_min_lod extension is enabled. 1658e5c31af7Sopenharmony_ci // The value is relative to baseLevel as the Texture*View 'src' was created as the baseLevel being level[0]. 1659e5c31af7Sopenharmony_ci const float imageViewMinLodRel = sampleParams.imageViewMinLod - (float)sampleParams.baseLevel; 1660e5c31af7Sopenharmony_ci // We need to adapt ImageView's minLod value to the mipmap mdoe (i.e. nearest or linear) so we clamp with the right minLod value later. 1661e5c31af7Sopenharmony_ci const float imageViewMinLodRelMode = tcu::isSamplerMipmapModeLinear(sampleParams.sampler.minFilter) ? deFloatFloor(imageViewMinLodRel) : (float)deClamp32((int)deFloatCeil(imageViewMinLodRel + 0.5f) - 1, sampleParams.baseLevel, sampleParams.maxLevel); 1662e5c31af7Sopenharmony_ci const float minLod = (sampleParams.imageViewMinLod != 0.0f) ? de::max(imageViewMinLodRelMode, sampleParams.minLod) : sampleParams.minLod; 1663e5c31af7Sopenharmony_ci 1664e5c31af7Sopenharmony_ci int numFailed = 0; 1665e5c31af7Sopenharmony_ci 1666e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 1667e5c31af7Sopenharmony_ci { 1668e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 1669e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 1670e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 1671e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 1672e5c31af7Sopenharmony_ci 1673e5c31af7Sopenharmony_ci // \note Not strictly allowed by spec, but implementations do this in practice. 1674e5c31af7Sopenharmony_ci tcu::Vec2(-1, -1), 1675e5c31af7Sopenharmony_ci tcu::Vec2(-1, +1), 1676e5c31af7Sopenharmony_ci tcu::Vec2(+1, -1), 1677e5c31af7Sopenharmony_ci tcu::Vec2(+1, +1), 1678e5c31af7Sopenharmony_ci }; 1679e5c31af7Sopenharmony_ci 1680e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 1681e5c31af7Sopenharmony_ci 1682e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 1683e5c31af7Sopenharmony_ci { 1684e5c31af7Sopenharmony_ci // Ugly hack, validation can take way too long at the moment. 1685e5c31af7Sopenharmony_ci if (watchDog) 1686e5c31af7Sopenharmony_ci qpWatchDog_touch(watchDog); 1687e5c31af7Sopenharmony_ci 1688e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 1689e5c31af7Sopenharmony_ci { 1690e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = (result.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 1691e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = (reference.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 1692e5c31af7Sopenharmony_ci 1693e5c31af7Sopenharmony_ci // Try comparison to ideal reference first, and if that fails use slower verificator. 1694e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold))) 1695e5c31af7Sopenharmony_ci { 1696e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 1697e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 1698e5c31af7Sopenharmony_ci const float nx = wx / dstW; 1699e5c31af7Sopenharmony_ci const float ny = wy / dstH; 1700e5c31af7Sopenharmony_ci 1701e5c31af7Sopenharmony_ci const bool tri0 = (wx-posEps)/dstW + (wy-posEps)/dstH <= 1.0f; 1702e5c31af7Sopenharmony_ci const bool tri1 = (wx+posEps)/dstW + (wy+posEps)/dstH >= 1.0f; 1703e5c31af7Sopenharmony_ci 1704e5c31af7Sopenharmony_ci bool isOk = false; 1705e5c31af7Sopenharmony_ci 1706e5c31af7Sopenharmony_ci DE_ASSERT(tri0 || tri1); 1707e5c31af7Sopenharmony_ci 1708e5c31af7Sopenharmony_ci // Pixel can belong to either of the triangles if it lies close enough to the edge. 1709e5c31af7Sopenharmony_ci for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++) 1710e5c31af7Sopenharmony_ci { 1711e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 1712e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 1713e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 1714e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 1715e5c31af7Sopenharmony_ci 1716e5c31af7Sopenharmony_ci const tcu::Vec3 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 1717e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), 1718e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)); 1719e5c31af7Sopenharmony_ci const tcu::Vec3 coordDx (triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 1720e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy), 1721e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)); 1722e5c31af7Sopenharmony_ci const tcu::Vec3 coordDy (triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 1723e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx), 1724e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)); 1725e5c31af7Sopenharmony_ci 1726e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec); 1727e5c31af7Sopenharmony_ci 1728e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 1729e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 1730e5c31af7Sopenharmony_ci { 1731e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 1732e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 1733e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 1734e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 1735e5c31af7Sopenharmony_ci 1736e5c31af7Sopenharmony_ci const tcu::Vec3 coordO (projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo), 1737e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo), 1738e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo)); 1739e5c31af7Sopenharmony_ci const tcu::Vec3 coordDxo (triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), 1740e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo), 1741e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)); 1742e5c31af7Sopenharmony_ci const tcu::Vec3 coordDyo (triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), 1743e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo), 1744e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)); 1745e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec); 1746e5c31af7Sopenharmony_ci 1747e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 1748e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 1749e5c31af7Sopenharmony_ci } 1750e5c31af7Sopenharmony_ci 1751e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(minLod, sampleParams.maxLod), lodPrec); 1752e5c31af7Sopenharmony_ci 1753e5c31af7Sopenharmony_ci if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix)) 1754e5c31af7Sopenharmony_ci { 1755e5c31af7Sopenharmony_ci isOk = true; 1756e5c31af7Sopenharmony_ci break; 1757e5c31af7Sopenharmony_ci } 1758e5c31af7Sopenharmony_ci } 1759e5c31af7Sopenharmony_ci 1760e5c31af7Sopenharmony_ci if (!isOk) 1761e5c31af7Sopenharmony_ci { 1762e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 1763e5c31af7Sopenharmony_ci numFailed += 1; 1764e5c31af7Sopenharmony_ci } 1765e5c31af7Sopenharmony_ci } 1766e5c31af7Sopenharmony_ci } 1767e5c31af7Sopenharmony_ci } 1768e5c31af7Sopenharmony_ci 1769e5c31af7Sopenharmony_ci return numFailed; 1770e5c31af7Sopenharmony_ci} 1771e5c31af7Sopenharmony_ci 1772e5c31af7Sopenharmony_cibool verifyTextureResult (tcu::TestContext& testCtx, 1773e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 1774e5c31af7Sopenharmony_ci const tcu::TextureCubeView& src, 1775e5c31af7Sopenharmony_ci const float* texCoord, 1776e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 1777e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 1778e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 1779e5c31af7Sopenharmony_ci const tcu::PixelFormat& pixelFormat) 1780e5c31af7Sopenharmony_ci{ 1781e5c31af7Sopenharmony_ci tcu::TestLog& log = testCtx.getLog(); 1782e5c31af7Sopenharmony_ci tcu::Surface reference (result.getWidth(), result.getHeight()); 1783e5c31af7Sopenharmony_ci tcu::Surface errorMask (result.getWidth(), result.getHeight()); 1784e5c31af7Sopenharmony_ci int numFailedPixels; 1785e5c31af7Sopenharmony_ci 1786e5c31af7Sopenharmony_ci DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask); 1787e5c31af7Sopenharmony_ci 1788e5c31af7Sopenharmony_ci sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams); 1789e5c31af7Sopenharmony_ci numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog()); 1790e5c31af7Sopenharmony_ci 1791e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 1792e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 1793e5c31af7Sopenharmony_ci 1794e5c31af7Sopenharmony_ci log << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 1795e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Rendered", "Rendered image", result); 1796e5c31af7Sopenharmony_ci 1797e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 1798e5c31af7Sopenharmony_ci { 1799e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 1800e5c31af7Sopenharmony_ci << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 1801e5c31af7Sopenharmony_ci } 1802e5c31af7Sopenharmony_ci 1803e5c31af7Sopenharmony_ci log << tcu::TestLog::EndImageSet; 1804e5c31af7Sopenharmony_ci 1805e5c31af7Sopenharmony_ci return numFailedPixels == 0; 1806e5c31af7Sopenharmony_ci} 1807e5c31af7Sopenharmony_ci 1808e5c31af7Sopenharmony_ci//! Verifies texture lookup results and returns number of failed pixels. 1809e5c31af7Sopenharmony_ciint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess& result, 1810e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 1811e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 1812e5c31af7Sopenharmony_ci const tcu::Texture3DView& baseView, 1813e5c31af7Sopenharmony_ci const float* texCoord, 1814e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 1815e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 1816e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 1817e5c31af7Sopenharmony_ci qpWatchDog* watchDog) 1818e5c31af7Sopenharmony_ci{ 1819e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 1820e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 1821e5c31af7Sopenharmony_ci 1822e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 1823e5c31af7Sopenharmony_ci tcu::ImageViewMinLodParams minLodParams = 1824e5c31af7Sopenharmony_ci { 1825e5c31af7Sopenharmony_ci sampleParams.baseLevel, // int baseLevel; 1826e5c31af7Sopenharmony_ci { 1827e5c31af7Sopenharmony_ci sampleParams.imageViewMinLod, // float minLod; 1828e5c31af7Sopenharmony_ci sampleParams.imageViewMinLodMode, // ImageViewMinLodMode 1829e5c31af7Sopenharmony_ci }, 1830e5c31af7Sopenharmony_ci sampleParams.samplerType == SAMPLERTYPE_FETCH_FLOAT // bool intTexCoord; 1831e5c31af7Sopenharmony_ci }; 1832e5c31af7Sopenharmony_ci 1833e5c31af7Sopenharmony_ci const tcu::Texture3DView src = getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel, sampleParams.imageViewMinLod != 0.0f ? &minLodParams : DE_NULL), srcLevelStorage, sampleParams.sampler); 1834e5c31af7Sopenharmony_ci 1835e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]); 1836e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]); 1837e5c31af7Sopenharmony_ci const tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]); 1838e5c31af7Sopenharmony_ci 1839e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 1840e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 1841e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 1842e5c31af7Sopenharmony_ci const tcu::IVec3 srcSize = tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth()); 1843e5c31af7Sopenharmony_ci 1844e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 1845e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 1846e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 1847e5c31af7Sopenharmony_ci const tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 1848e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 1849e5c31af7Sopenharmony_ci 1850e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 1851e5c31af7Sopenharmony_ci 1852e5c31af7Sopenharmony_ci // imageViewMinLodRel is used to calculate the image level to sample from, when VK_EXT_image_view_min_lod extension is enabled. 1853e5c31af7Sopenharmony_ci // The value is relative to baseLevel as the Texture*View 'src' was created as the baseLevel being level[0]. 1854e5c31af7Sopenharmony_ci const float imageViewMinLodRel = sampleParams.imageViewMinLod - (float)sampleParams.baseLevel; 1855e5c31af7Sopenharmony_ci // We need to adapt ImageView's minLod value to the mipmap mdoe (i.e. nearest or linear) so we clamp with the right minLod value later. 1856e5c31af7Sopenharmony_ci const float imageViewMinLodRelMode = tcu::isSamplerMipmapModeLinear(sampleParams.sampler.minFilter) ? deFloatFloor(imageViewMinLodRel) : (float)deClamp32((int)deFloatCeil(imageViewMinLodRel + 0.5f) - 1, sampleParams.baseLevel, sampleParams.maxLevel); 1857e5c31af7Sopenharmony_ci const float minLod = (sampleParams.imageViewMinLod != 0.0f) ? de::max(imageViewMinLodRelMode, sampleParams.minLod) : sampleParams.minLod; 1858e5c31af7Sopenharmony_ci 1859e5c31af7Sopenharmony_ci const float posEps = 1.0f / float(1<<MIN_SUBPIXEL_BITS); 1860e5c31af7Sopenharmony_ci 1861e5c31af7Sopenharmony_ci int numFailed = 0; 1862e5c31af7Sopenharmony_ci 1863e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 1864e5c31af7Sopenharmony_ci { 1865e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 1866e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 1867e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 1868e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 1869e5c31af7Sopenharmony_ci }; 1870e5c31af7Sopenharmony_ci 1871e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 1872e5c31af7Sopenharmony_ci 1873e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 1874e5c31af7Sopenharmony_ci { 1875e5c31af7Sopenharmony_ci // Ugly hack, validation can take way too long at the moment. 1876e5c31af7Sopenharmony_ci if (watchDog) 1877e5c31af7Sopenharmony_ci qpWatchDog_touch(watchDog); 1878e5c31af7Sopenharmony_ci 1879e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 1880e5c31af7Sopenharmony_ci { 1881e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = (result.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 1882e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = (reference.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 1883e5c31af7Sopenharmony_ci 1884e5c31af7Sopenharmony_ci // Try comparison to ideal reference first, and if that fails use slower verificator. 1885e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold))) 1886e5c31af7Sopenharmony_ci { 1887e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 1888e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 1889e5c31af7Sopenharmony_ci const float nx = wx / dstW; 1890e5c31af7Sopenharmony_ci const float ny = wy / dstH; 1891e5c31af7Sopenharmony_ci 1892e5c31af7Sopenharmony_ci const bool tri0 = (wx-posEps)/dstW + (wy-posEps)/dstH <= 1.0f; 1893e5c31af7Sopenharmony_ci const bool tri1 = (wx+posEps)/dstW + (wy+posEps)/dstH >= 1.0f; 1894e5c31af7Sopenharmony_ci 1895e5c31af7Sopenharmony_ci bool isOk = false; 1896e5c31af7Sopenharmony_ci 1897e5c31af7Sopenharmony_ci DE_ASSERT(tri0 || tri1); 1898e5c31af7Sopenharmony_ci 1899e5c31af7Sopenharmony_ci // Pixel can belong to either of the triangles if it lies close enough to the edge. 1900e5c31af7Sopenharmony_ci for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++) 1901e5c31af7Sopenharmony_ci { 1902e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 1903e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 1904e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 1905e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 1906e5c31af7Sopenharmony_ci 1907e5c31af7Sopenharmony_ci const tcu::Vec3 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 1908e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), 1909e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)); 1910e5c31af7Sopenharmony_ci const tcu::Vec3 coordDx = tcu::Vec3(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 1911e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy), 1912e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat(); 1913e5c31af7Sopenharmony_ci const tcu::Vec3 coordDy = tcu::Vec3(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 1914e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx), 1915e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat(); 1916e5c31af7Sopenharmony_ci 1917e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDx.z(), coordDy.x(), coordDy.y(), coordDy.z(), lodPrec); 1918e5c31af7Sopenharmony_ci 1919e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 1920e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 1921e5c31af7Sopenharmony_ci { 1922e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 1923e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 1924e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 1925e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 1926e5c31af7Sopenharmony_ci 1927e5c31af7Sopenharmony_ci const tcu::Vec3 coordDxo = tcu::Vec3(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), 1928e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo), 1929e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat(); 1930e5c31af7Sopenharmony_ci const tcu::Vec3 coordDyo = tcu::Vec3(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), 1931e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo), 1932e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat(); 1933e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDxo.z(), coordDyo.x(), coordDyo.y(), coordDyo.z(), lodPrec); 1934e5c31af7Sopenharmony_ci 1935e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 1936e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 1937e5c31af7Sopenharmony_ci } 1938e5c31af7Sopenharmony_ci 1939e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(minLod, sampleParams.maxLod), lodPrec); 1940e5c31af7Sopenharmony_ci 1941e5c31af7Sopenharmony_ci if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix)) 1942e5c31af7Sopenharmony_ci { 1943e5c31af7Sopenharmony_ci isOk = true; 1944e5c31af7Sopenharmony_ci break; 1945e5c31af7Sopenharmony_ci } 1946e5c31af7Sopenharmony_ci } 1947e5c31af7Sopenharmony_ci 1948e5c31af7Sopenharmony_ci if (!isOk) 1949e5c31af7Sopenharmony_ci { 1950e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 1951e5c31af7Sopenharmony_ci numFailed += 1; 1952e5c31af7Sopenharmony_ci } 1953e5c31af7Sopenharmony_ci } 1954e5c31af7Sopenharmony_ci } 1955e5c31af7Sopenharmony_ci } 1956e5c31af7Sopenharmony_ci 1957e5c31af7Sopenharmony_ci return numFailed; 1958e5c31af7Sopenharmony_ci} 1959e5c31af7Sopenharmony_ci 1960e5c31af7Sopenharmony_cibool verifyTextureResult (tcu::TestContext& testCtx, 1961e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 1962e5c31af7Sopenharmony_ci const tcu::Texture3DView& src, 1963e5c31af7Sopenharmony_ci const float* texCoord, 1964e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 1965e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 1966e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 1967e5c31af7Sopenharmony_ci const tcu::PixelFormat& pixelFormat) 1968e5c31af7Sopenharmony_ci{ 1969e5c31af7Sopenharmony_ci tcu::TestLog& log = testCtx.getLog(); 1970e5c31af7Sopenharmony_ci tcu::Surface reference (result.getWidth(), result.getHeight()); 1971e5c31af7Sopenharmony_ci tcu::Surface errorMask (result.getWidth(), result.getHeight()); 1972e5c31af7Sopenharmony_ci int numFailedPixels; 1973e5c31af7Sopenharmony_ci 1974e5c31af7Sopenharmony_ci DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask); 1975e5c31af7Sopenharmony_ci 1976e5c31af7Sopenharmony_ci sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams); 1977e5c31af7Sopenharmony_ci numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog()); 1978e5c31af7Sopenharmony_ci 1979e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 1980e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 1981e5c31af7Sopenharmony_ci 1982e5c31af7Sopenharmony_ci log << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 1983e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Rendered", "Rendered image", result); 1984e5c31af7Sopenharmony_ci 1985e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 1986e5c31af7Sopenharmony_ci { 1987e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 1988e5c31af7Sopenharmony_ci << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 1989e5c31af7Sopenharmony_ci } 1990e5c31af7Sopenharmony_ci 1991e5c31af7Sopenharmony_ci log << tcu::TestLog::EndImageSet; 1992e5c31af7Sopenharmony_ci 1993e5c31af7Sopenharmony_ci return numFailedPixels == 0; 1994e5c31af7Sopenharmony_ci} 1995e5c31af7Sopenharmony_ci 1996e5c31af7Sopenharmony_ci//! Verifies texture lookup results and returns number of failed pixels. 1997e5c31af7Sopenharmony_ciint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess& result, 1998e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 1999e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 2000e5c31af7Sopenharmony_ci const tcu::Texture1DArrayView& baseView, 2001e5c31af7Sopenharmony_ci const float* texCoord, 2002e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2003e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 2004e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2005e5c31af7Sopenharmony_ci qpWatchDog* watchDog) 2006e5c31af7Sopenharmony_ci{ 2007e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 2008e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 2009e5c31af7Sopenharmony_ci 2010e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 2011e5c31af7Sopenharmony_ci const tcu::Texture1DArrayView src = getEffectiveTextureView(baseView, srcLevelStorage, sampleParams.sampler); 2012e5c31af7Sopenharmony_ci 2013e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]); 2014e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]); 2015e5c31af7Sopenharmony_ci 2016e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 2017e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 2018e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 2019e5c31af7Sopenharmony_ci const float srcSize = float(src.getWidth()); // For lod computation, thus #layers is ignored. 2020e5c31af7Sopenharmony_ci 2021e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 2022e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 2023e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 2024e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 2025e5c31af7Sopenharmony_ci 2026e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 2027e5c31af7Sopenharmony_ci 2028e5c31af7Sopenharmony_ci int numFailed = 0; 2029e5c31af7Sopenharmony_ci 2030e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 2031e5c31af7Sopenharmony_ci { 2032e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 2033e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 2034e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 2035e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 2036e5c31af7Sopenharmony_ci }; 2037e5c31af7Sopenharmony_ci 2038e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 2039e5c31af7Sopenharmony_ci 2040e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 2041e5c31af7Sopenharmony_ci { 2042e5c31af7Sopenharmony_ci // Ugly hack, validation can take way too long at the moment. 2043e5c31af7Sopenharmony_ci if (watchDog) 2044e5c31af7Sopenharmony_ci qpWatchDog_touch(watchDog); 2045e5c31af7Sopenharmony_ci 2046e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 2047e5c31af7Sopenharmony_ci { 2048e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = (result.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 2049e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = (reference.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 2050e5c31af7Sopenharmony_ci 2051e5c31af7Sopenharmony_ci // Try comparison to ideal reference first, and if that fails use slower verificator. 2052e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold))) 2053e5c31af7Sopenharmony_ci { 2054e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 2055e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 2056e5c31af7Sopenharmony_ci const float nx = wx / dstW; 2057e5c31af7Sopenharmony_ci const float ny = wy / dstH; 2058e5c31af7Sopenharmony_ci 2059e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 2060e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 2061e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 2062e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 2063e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 2064e5c31af7Sopenharmony_ci 2065e5c31af7Sopenharmony_ci const tcu::Vec2 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 2066e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy)); 2067e5c31af7Sopenharmony_ci const float coordDx = triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * srcSize; 2068e5c31af7Sopenharmony_ci const float coordDy = triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx) * srcSize; 2069e5c31af7Sopenharmony_ci 2070e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeLodBoundsFromDerivates(coordDx, coordDy, lodPrec); 2071e5c31af7Sopenharmony_ci 2072e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 2073e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 2074e5c31af7Sopenharmony_ci { 2075e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 2076e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 2077e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 2078e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 2079e5c31af7Sopenharmony_ci 2080e5c31af7Sopenharmony_ci const float coordDxo = triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * srcSize; 2081e5c31af7Sopenharmony_ci const float coordDyo = triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * srcSize; 2082e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec); 2083e5c31af7Sopenharmony_ci 2084e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 2085e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 2086e5c31af7Sopenharmony_ci } 2087e5c31af7Sopenharmony_ci 2088e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec); 2089e5c31af7Sopenharmony_ci const bool isOk = tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix); 2090e5c31af7Sopenharmony_ci 2091e5c31af7Sopenharmony_ci if (!isOk) 2092e5c31af7Sopenharmony_ci { 2093e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2094e5c31af7Sopenharmony_ci numFailed += 1; 2095e5c31af7Sopenharmony_ci } 2096e5c31af7Sopenharmony_ci } 2097e5c31af7Sopenharmony_ci } 2098e5c31af7Sopenharmony_ci } 2099e5c31af7Sopenharmony_ci 2100e5c31af7Sopenharmony_ci return numFailed; 2101e5c31af7Sopenharmony_ci} 2102e5c31af7Sopenharmony_ci 2103e5c31af7Sopenharmony_ci//! Verifies texture lookup results and returns number of failed pixels. 2104e5c31af7Sopenharmony_ciint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess& result, 2105e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 2106e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 2107e5c31af7Sopenharmony_ci const tcu::Texture2DArrayView& baseView, 2108e5c31af7Sopenharmony_ci const float* texCoord, 2109e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2110e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 2111e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2112e5c31af7Sopenharmony_ci qpWatchDog* watchDog) 2113e5c31af7Sopenharmony_ci{ 2114e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 2115e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 2116e5c31af7Sopenharmony_ci 2117e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 2118e5c31af7Sopenharmony_ci const tcu::Texture2DArrayView src = getEffectiveTextureView(baseView, srcLevelStorage, sampleParams.sampler); 2119e5c31af7Sopenharmony_ci 2120e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]); 2121e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]); 2122e5c31af7Sopenharmony_ci const tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]); 2123e5c31af7Sopenharmony_ci 2124e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 2125e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 2126e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 2127e5c31af7Sopenharmony_ci const tcu::Vec2 srcSize = tcu::IVec2(src.getWidth(), src.getHeight()).asFloat(); // For lod computation, thus #layers is ignored. 2128e5c31af7Sopenharmony_ci 2129e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 2130e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 2131e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 2132e5c31af7Sopenharmony_ci const tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 2133e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 2134e5c31af7Sopenharmony_ci 2135e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 2136e5c31af7Sopenharmony_ci 2137e5c31af7Sopenharmony_ci int numFailed = 0; 2138e5c31af7Sopenharmony_ci 2139e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 2140e5c31af7Sopenharmony_ci { 2141e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 2142e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 2143e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 2144e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 2145e5c31af7Sopenharmony_ci }; 2146e5c31af7Sopenharmony_ci 2147e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 2148e5c31af7Sopenharmony_ci 2149e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 2150e5c31af7Sopenharmony_ci { 2151e5c31af7Sopenharmony_ci // Ugly hack, validation can take way too long at the moment. 2152e5c31af7Sopenharmony_ci if (watchDog) 2153e5c31af7Sopenharmony_ci qpWatchDog_touch(watchDog); 2154e5c31af7Sopenharmony_ci 2155e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 2156e5c31af7Sopenharmony_ci { 2157e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = (result.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 2158e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = (reference.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 2159e5c31af7Sopenharmony_ci 2160e5c31af7Sopenharmony_ci // Try comparison to ideal reference first, and if that fails use slower verificator. 2161e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold))) 2162e5c31af7Sopenharmony_ci { 2163e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 2164e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 2165e5c31af7Sopenharmony_ci const float nx = wx / dstW; 2166e5c31af7Sopenharmony_ci const float ny = wy / dstH; 2167e5c31af7Sopenharmony_ci 2168e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 2169e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 2170e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 2171e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 2172e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 2173e5c31af7Sopenharmony_ci 2174e5c31af7Sopenharmony_ci const tcu::Vec3 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 2175e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), 2176e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)); 2177e5c31af7Sopenharmony_ci const tcu::Vec2 coordDx = tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 2178e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize; 2179e5c31af7Sopenharmony_ci const tcu::Vec2 coordDy = tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 2180e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize; 2181e5c31af7Sopenharmony_ci 2182e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec); 2183e5c31af7Sopenharmony_ci 2184e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 2185e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 2186e5c31af7Sopenharmony_ci { 2187e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 2188e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 2189e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 2190e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 2191e5c31af7Sopenharmony_ci 2192e5c31af7Sopenharmony_ci const tcu::Vec2 coordDxo = tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), 2193e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize; 2194e5c31af7Sopenharmony_ci const tcu::Vec2 coordDyo = tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), 2195e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize; 2196e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec); 2197e5c31af7Sopenharmony_ci 2198e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 2199e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 2200e5c31af7Sopenharmony_ci } 2201e5c31af7Sopenharmony_ci 2202e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec); 2203e5c31af7Sopenharmony_ci const bool isOk = tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix); 2204e5c31af7Sopenharmony_ci 2205e5c31af7Sopenharmony_ci if (!isOk) 2206e5c31af7Sopenharmony_ci { 2207e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2208e5c31af7Sopenharmony_ci numFailed += 1; 2209e5c31af7Sopenharmony_ci } 2210e5c31af7Sopenharmony_ci } 2211e5c31af7Sopenharmony_ci } 2212e5c31af7Sopenharmony_ci } 2213e5c31af7Sopenharmony_ci 2214e5c31af7Sopenharmony_ci return numFailed; 2215e5c31af7Sopenharmony_ci} 2216e5c31af7Sopenharmony_ci 2217e5c31af7Sopenharmony_cibool verifyTextureResult (tcu::TestContext& testCtx, 2218e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 2219e5c31af7Sopenharmony_ci const tcu::Texture1DArrayView& src, 2220e5c31af7Sopenharmony_ci const float* texCoord, 2221e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2222e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 2223e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2224e5c31af7Sopenharmony_ci const tcu::PixelFormat& pixelFormat) 2225e5c31af7Sopenharmony_ci{ 2226e5c31af7Sopenharmony_ci tcu::TestLog& log = testCtx.getLog(); 2227e5c31af7Sopenharmony_ci tcu::Surface reference (result.getWidth(), result.getHeight()); 2228e5c31af7Sopenharmony_ci tcu::Surface errorMask (result.getWidth(), result.getHeight()); 2229e5c31af7Sopenharmony_ci int numFailedPixels; 2230e5c31af7Sopenharmony_ci 2231e5c31af7Sopenharmony_ci DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask); 2232e5c31af7Sopenharmony_ci 2233e5c31af7Sopenharmony_ci sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams); 2234e5c31af7Sopenharmony_ci numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog()); 2235e5c31af7Sopenharmony_ci 2236e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 2237e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 2238e5c31af7Sopenharmony_ci 2239e5c31af7Sopenharmony_ci log << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 2240e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Rendered", "Rendered image", result); 2241e5c31af7Sopenharmony_ci 2242e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 2243e5c31af7Sopenharmony_ci { 2244e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 2245e5c31af7Sopenharmony_ci << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 2246e5c31af7Sopenharmony_ci } 2247e5c31af7Sopenharmony_ci 2248e5c31af7Sopenharmony_ci log << tcu::TestLog::EndImageSet; 2249e5c31af7Sopenharmony_ci 2250e5c31af7Sopenharmony_ci return numFailedPixels == 0; 2251e5c31af7Sopenharmony_ci} 2252e5c31af7Sopenharmony_ci 2253e5c31af7Sopenharmony_cibool verifyTextureResult (tcu::TestContext& testCtx, 2254e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 2255e5c31af7Sopenharmony_ci const tcu::Texture2DArrayView& src, 2256e5c31af7Sopenharmony_ci const float* texCoord, 2257e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2258e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 2259e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2260e5c31af7Sopenharmony_ci const tcu::PixelFormat& pixelFormat) 2261e5c31af7Sopenharmony_ci{ 2262e5c31af7Sopenharmony_ci tcu::TestLog& log = testCtx.getLog(); 2263e5c31af7Sopenharmony_ci tcu::Surface reference (result.getWidth(), result.getHeight()); 2264e5c31af7Sopenharmony_ci tcu::Surface errorMask (result.getWidth(), result.getHeight()); 2265e5c31af7Sopenharmony_ci int numFailedPixels; 2266e5c31af7Sopenharmony_ci 2267e5c31af7Sopenharmony_ci DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask); 2268e5c31af7Sopenharmony_ci 2269e5c31af7Sopenharmony_ci sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams); 2270e5c31af7Sopenharmony_ci numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog()); 2271e5c31af7Sopenharmony_ci 2272e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 2273e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 2274e5c31af7Sopenharmony_ci 2275e5c31af7Sopenharmony_ci log << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 2276e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Rendered", "Rendered image", result); 2277e5c31af7Sopenharmony_ci 2278e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 2279e5c31af7Sopenharmony_ci { 2280e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 2281e5c31af7Sopenharmony_ci << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 2282e5c31af7Sopenharmony_ci } 2283e5c31af7Sopenharmony_ci 2284e5c31af7Sopenharmony_ci log << tcu::TestLog::EndImageSet; 2285e5c31af7Sopenharmony_ci 2286e5c31af7Sopenharmony_ci return numFailedPixels == 0; 2287e5c31af7Sopenharmony_ci} 2288e5c31af7Sopenharmony_ci 2289e5c31af7Sopenharmony_ci//! Verifies texture lookup results and returns number of failed pixels. 2290e5c31af7Sopenharmony_ciint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess& result, 2291e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 2292e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 2293e5c31af7Sopenharmony_ci const tcu::TextureCubeArrayView& baseView, 2294e5c31af7Sopenharmony_ci const float* texCoord, 2295e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2296e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 2297e5c31af7Sopenharmony_ci const tcu::IVec4& coordBits, 2298e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2299e5c31af7Sopenharmony_ci qpWatchDog* watchDog) 2300e5c31af7Sopenharmony_ci{ 2301e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 2302e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 2303e5c31af7Sopenharmony_ci 2304e5c31af7Sopenharmony_ci std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 2305e5c31af7Sopenharmony_ci tcu::ImageViewMinLodParams minLodParams = 2306e5c31af7Sopenharmony_ci { 2307e5c31af7Sopenharmony_ci sampleParams.baseLevel, // int baseLevel; 2308e5c31af7Sopenharmony_ci { 2309e5c31af7Sopenharmony_ci sampleParams.imageViewMinLod, // float minLod; 2310e5c31af7Sopenharmony_ci sampleParams.imageViewMinLodMode, // ImageViewMinLodMode 2311e5c31af7Sopenharmony_ci }, 2312e5c31af7Sopenharmony_ci sampleParams.samplerType == SAMPLERTYPE_FETCH_FLOAT // bool intTexCoord; 2313e5c31af7Sopenharmony_ci }; 2314e5c31af7Sopenharmony_ci 2315e5c31af7Sopenharmony_ci const tcu::TextureCubeArrayView src = getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel, sampleParams.imageViewMinLod != 0.0f ? &minLodParams : DE_NULL), srcLevelStorage, sampleParams.sampler); 2316e5c31af7Sopenharmony_ci 2317e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]); 2318e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]); 2319e5c31af7Sopenharmony_ci const tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]); 2320e5c31af7Sopenharmony_ci const tcu::Vec4 qq = tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]); 2321e5c31af7Sopenharmony_ci 2322e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 2323e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 2324e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 2325e5c31af7Sopenharmony_ci const int srcSize = src.getSize(); 2326e5c31af7Sopenharmony_ci 2327e5c31af7Sopenharmony_ci // Coordinates per triangle. 2328e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 2329e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 2330e5c31af7Sopenharmony_ci const tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 2331e5c31af7Sopenharmony_ci const tcu::Vec3 triQ[2] = { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) }; 2332e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 2333e5c31af7Sopenharmony_ci 2334e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 2335e5c31af7Sopenharmony_ci 2336e5c31af7Sopenharmony_ci const float posEps = 1.0f / float((1<<4) + 1); // ES3 requires at least 4 subpixel bits. 2337e5c31af7Sopenharmony_ci 2338e5c31af7Sopenharmony_ci int numFailed = 0; 2339e5c31af7Sopenharmony_ci 2340e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 2341e5c31af7Sopenharmony_ci { 2342e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 2343e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 2344e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 2345e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 2346e5c31af7Sopenharmony_ci 2347e5c31af7Sopenharmony_ci // \note Not strictly allowed by spec, but implementations do this in practice. 2348e5c31af7Sopenharmony_ci tcu::Vec2(-1, -1), 2349e5c31af7Sopenharmony_ci tcu::Vec2(-1, +1), 2350e5c31af7Sopenharmony_ci tcu::Vec2(+1, -1), 2351e5c31af7Sopenharmony_ci tcu::Vec2(+1, +1), 2352e5c31af7Sopenharmony_ci }; 2353e5c31af7Sopenharmony_ci 2354e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 2355e5c31af7Sopenharmony_ci 2356e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 2357e5c31af7Sopenharmony_ci { 2358e5c31af7Sopenharmony_ci // Ugly hack, validation can take way too long at the moment. 2359e5c31af7Sopenharmony_ci if (watchDog) 2360e5c31af7Sopenharmony_ci qpWatchDog_touch(watchDog); 2361e5c31af7Sopenharmony_ci 2362e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 2363e5c31af7Sopenharmony_ci { 2364e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = (result.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 2365e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = (reference.getPixel(px, py) - sampleParams.colorBias) / sampleParams.colorScale; 2366e5c31af7Sopenharmony_ci 2367e5c31af7Sopenharmony_ci // Try comparison to ideal reference first, and if that fails use slower verificator. 2368e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold))) 2369e5c31af7Sopenharmony_ci { 2370e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 2371e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 2372e5c31af7Sopenharmony_ci const float nx = wx / dstW; 2373e5c31af7Sopenharmony_ci const float ny = wy / dstH; 2374e5c31af7Sopenharmony_ci 2375e5c31af7Sopenharmony_ci const bool tri0 = nx + ny - posEps <= 1.0f; 2376e5c31af7Sopenharmony_ci const bool tri1 = nx + ny + posEps >= 1.0f; 2377e5c31af7Sopenharmony_ci 2378e5c31af7Sopenharmony_ci bool isOk = false; 2379e5c31af7Sopenharmony_ci 2380e5c31af7Sopenharmony_ci DE_ASSERT(tri0 || tri1); 2381e5c31af7Sopenharmony_ci 2382e5c31af7Sopenharmony_ci // Pixel can belong to either of the triangles if it lies close enough to the edge. 2383e5c31af7Sopenharmony_ci for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++) 2384e5c31af7Sopenharmony_ci { 2385e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 2386e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 2387e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 2388e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 2389e5c31af7Sopenharmony_ci 2390e5c31af7Sopenharmony_ci const tcu::Vec4 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 2391e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), 2392e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy), 2393e5c31af7Sopenharmony_ci projectedTriInterpolate(triQ[triNdx], triW[triNdx], triNx, triNy)); 2394e5c31af7Sopenharmony_ci const tcu::Vec3 coordDx (triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 2395e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy), 2396e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)); 2397e5c31af7Sopenharmony_ci const tcu::Vec3 coordDy (triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 2398e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx), 2399e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)); 2400e5c31af7Sopenharmony_ci 2401e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeCubeLodBoundsFromDerivates(coord.toWidth<3>(), coordDx, coordDy, srcSize, lodPrec); 2402e5c31af7Sopenharmony_ci 2403e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 2404e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 2405e5c31af7Sopenharmony_ci { 2406e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 2407e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 2408e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 2409e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 2410e5c31af7Sopenharmony_ci 2411e5c31af7Sopenharmony_ci const tcu::Vec3 coordO (projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo), 2412e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo), 2413e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo)); 2414e5c31af7Sopenharmony_ci const tcu::Vec3 coordDxo (triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), 2415e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo), 2416e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)); 2417e5c31af7Sopenharmony_ci const tcu::Vec3 coordDyo (triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), 2418e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo), 2419e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)); 2420e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec); 2421e5c31af7Sopenharmony_ci 2422e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 2423e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 2424e5c31af7Sopenharmony_ci } 2425e5c31af7Sopenharmony_ci 2426e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec); 2427e5c31af7Sopenharmony_ci 2428e5c31af7Sopenharmony_ci if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coordBits, coord, clampedLod, resPix)) 2429e5c31af7Sopenharmony_ci { 2430e5c31af7Sopenharmony_ci isOk = true; 2431e5c31af7Sopenharmony_ci break; 2432e5c31af7Sopenharmony_ci } 2433e5c31af7Sopenharmony_ci } 2434e5c31af7Sopenharmony_ci 2435e5c31af7Sopenharmony_ci if (!isOk) 2436e5c31af7Sopenharmony_ci { 2437e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2438e5c31af7Sopenharmony_ci numFailed += 1; 2439e5c31af7Sopenharmony_ci } 2440e5c31af7Sopenharmony_ci } 2441e5c31af7Sopenharmony_ci } 2442e5c31af7Sopenharmony_ci } 2443e5c31af7Sopenharmony_ci 2444e5c31af7Sopenharmony_ci return numFailed; 2445e5c31af7Sopenharmony_ci} 2446e5c31af7Sopenharmony_ci 2447e5c31af7Sopenharmony_cibool verifyTextureResult (tcu::TestContext& testCtx, 2448e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& result, 2449e5c31af7Sopenharmony_ci const tcu::TextureCubeArrayView& src, 2450e5c31af7Sopenharmony_ci const float* texCoord, 2451e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2452e5c31af7Sopenharmony_ci const tcu::LookupPrecision& lookupPrec, 2453e5c31af7Sopenharmony_ci const tcu::IVec4& coordBits, 2454e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2455e5c31af7Sopenharmony_ci const tcu::PixelFormat& pixelFormat) 2456e5c31af7Sopenharmony_ci{ 2457e5c31af7Sopenharmony_ci tcu::TestLog& log = testCtx.getLog(); 2458e5c31af7Sopenharmony_ci tcu::Surface reference (result.getWidth(), result.getHeight()); 2459e5c31af7Sopenharmony_ci tcu::Surface errorMask (result.getWidth(), result.getHeight()); 2460e5c31af7Sopenharmony_ci int numFailedPixels; 2461e5c31af7Sopenharmony_ci 2462e5c31af7Sopenharmony_ci DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask); 2463e5c31af7Sopenharmony_ci 2464e5c31af7Sopenharmony_ci sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams); 2465e5c31af7Sopenharmony_ci numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, coordBits, lodPrec, testCtx.getWatchDog()); 2466e5c31af7Sopenharmony_ci 2467e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 2468e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 2469e5c31af7Sopenharmony_ci 2470e5c31af7Sopenharmony_ci log << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 2471e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Rendered", "Rendered image", result); 2472e5c31af7Sopenharmony_ci 2473e5c31af7Sopenharmony_ci if (numFailedPixels > 0) 2474e5c31af7Sopenharmony_ci { 2475e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 2476e5c31af7Sopenharmony_ci << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 2477e5c31af7Sopenharmony_ci } 2478e5c31af7Sopenharmony_ci 2479e5c31af7Sopenharmony_ci log << tcu::TestLog::EndImageSet; 2480e5c31af7Sopenharmony_ci 2481e5c31af7Sopenharmony_ci return numFailedPixels == 0; 2482e5c31af7Sopenharmony_ci} 2483e5c31af7Sopenharmony_ci 2484e5c31af7Sopenharmony_ci// Shadow lookup verification 2485e5c31af7Sopenharmony_ci 2486e5c31af7Sopenharmony_ciint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess& result, 2487e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 2488e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 2489e5c31af7Sopenharmony_ci const tcu::Texture2DView& src, 2490e5c31af7Sopenharmony_ci const float* texCoord, 2491e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2492e5c31af7Sopenharmony_ci const tcu::TexComparePrecision& comparePrec, 2493e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2494e5c31af7Sopenharmony_ci const tcu::Vec3& nonShadowThreshold) 2495e5c31af7Sopenharmony_ci{ 2496e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 2497e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 2498e5c31af7Sopenharmony_ci 2499e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]); 2500e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]); 2501e5c31af7Sopenharmony_ci 2502e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 2503e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 2504e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 2505e5c31af7Sopenharmony_ci const tcu::IVec2 srcSize = tcu::IVec2(src.getWidth(), src.getHeight()); 2506e5c31af7Sopenharmony_ci 2507e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 2508e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 2509e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 2510e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 2511e5c31af7Sopenharmony_ci 2512e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 2513e5c31af7Sopenharmony_ci 2514e5c31af7Sopenharmony_ci const float minLod = (sampleParams.imageViewMinLod != 0.0f) ? de::max(deFloatFloor(sampleParams.imageViewMinLod), sampleParams.minLod) : sampleParams.minLod; 2515e5c31af7Sopenharmony_ci 2516e5c31af7Sopenharmony_ci int numFailed = 0; 2517e5c31af7Sopenharmony_ci 2518e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 2519e5c31af7Sopenharmony_ci { 2520e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 2521e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 2522e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 2523e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 2524e5c31af7Sopenharmony_ci }; 2525e5c31af7Sopenharmony_ci 2526e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 2527e5c31af7Sopenharmony_ci 2528e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 2529e5c31af7Sopenharmony_ci { 2530e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 2531e5c31af7Sopenharmony_ci { 2532e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = result.getPixel(px, py); 2533e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = reference.getPixel(px, py); 2534e5c31af7Sopenharmony_ci 2535e5c31af7Sopenharmony_ci // Other channels should trivially match to reference. 2536e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold))) 2537e5c31af7Sopenharmony_ci { 2538e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2539e5c31af7Sopenharmony_ci numFailed += 1; 2540e5c31af7Sopenharmony_ci continue; 2541e5c31af7Sopenharmony_ci } 2542e5c31af7Sopenharmony_ci 2543e5c31af7Sopenharmony_ci // Reference result is known to be a valid result, we can 2544e5c31af7Sopenharmony_ci // skip verification if thes results are equal 2545e5c31af7Sopenharmony_ci if (resPix.x() != refPix.x()) 2546e5c31af7Sopenharmony_ci { 2547e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 2548e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 2549e5c31af7Sopenharmony_ci const float nx = wx / dstW; 2550e5c31af7Sopenharmony_ci const float ny = wy / dstH; 2551e5c31af7Sopenharmony_ci 2552e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 2553e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 2554e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 2555e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 2556e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 2557e5c31af7Sopenharmony_ci 2558e5c31af7Sopenharmony_ci const tcu::Vec2 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 2559e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy)); 2560e5c31af7Sopenharmony_ci const tcu::Vec2 coordDx = tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 2561e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat(); 2562e5c31af7Sopenharmony_ci const tcu::Vec2 coordDy = tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 2563e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat(); 2564e5c31af7Sopenharmony_ci 2565e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec); 2566e5c31af7Sopenharmony_ci 2567e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 2568e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 2569e5c31af7Sopenharmony_ci { 2570e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 2571e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 2572e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 2573e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 2574e5c31af7Sopenharmony_ci 2575e5c31af7Sopenharmony_ci const tcu::Vec2 coordDxo = tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), 2576e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat(); 2577e5c31af7Sopenharmony_ci const tcu::Vec2 coordDyo = tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), 2578e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat(); 2579e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec); 2580e5c31af7Sopenharmony_ci 2581e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 2582e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 2583e5c31af7Sopenharmony_ci } 2584e5c31af7Sopenharmony_ci 2585e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(minLod, sampleParams.maxLod), lodPrec); 2586e5c31af7Sopenharmony_ci const bool isOk = tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x()); 2587e5c31af7Sopenharmony_ci 2588e5c31af7Sopenharmony_ci if (!isOk) 2589e5c31af7Sopenharmony_ci { 2590e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2591e5c31af7Sopenharmony_ci numFailed += 1; 2592e5c31af7Sopenharmony_ci } 2593e5c31af7Sopenharmony_ci } 2594e5c31af7Sopenharmony_ci } 2595e5c31af7Sopenharmony_ci } 2596e5c31af7Sopenharmony_ci 2597e5c31af7Sopenharmony_ci return numFailed; 2598e5c31af7Sopenharmony_ci} 2599e5c31af7Sopenharmony_ci 2600e5c31af7Sopenharmony_ciint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess& result, 2601e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 2602e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 2603e5c31af7Sopenharmony_ci const tcu::TextureCubeView& src, 2604e5c31af7Sopenharmony_ci const float* texCoord, 2605e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2606e5c31af7Sopenharmony_ci const tcu::TexComparePrecision& comparePrec, 2607e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2608e5c31af7Sopenharmony_ci const tcu::Vec3& nonShadowThreshold) 2609e5c31af7Sopenharmony_ci{ 2610e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 2611e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 2612e5c31af7Sopenharmony_ci 2613e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]); 2614e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]); 2615e5c31af7Sopenharmony_ci const tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]); 2616e5c31af7Sopenharmony_ci 2617e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 2618e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 2619e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 2620e5c31af7Sopenharmony_ci const int srcSize = src.getSize(); 2621e5c31af7Sopenharmony_ci 2622e5c31af7Sopenharmony_ci // Coordinates per triangle. 2623e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 2624e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 2625e5c31af7Sopenharmony_ci const tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 2626e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 2627e5c31af7Sopenharmony_ci 2628e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 2629e5c31af7Sopenharmony_ci 2630e5c31af7Sopenharmony_ci const float minLod = (sampleParams.imageViewMinLod != 0.0f) ? de::max(deFloatFloor(sampleParams.imageViewMinLod), sampleParams.minLod) : sampleParams.minLod; 2631e5c31af7Sopenharmony_ci 2632e5c31af7Sopenharmony_ci int numFailed = 0; 2633e5c31af7Sopenharmony_ci 2634e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 2635e5c31af7Sopenharmony_ci { 2636e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 2637e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 2638e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 2639e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 2640e5c31af7Sopenharmony_ci }; 2641e5c31af7Sopenharmony_ci 2642e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 2643e5c31af7Sopenharmony_ci 2644e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 2645e5c31af7Sopenharmony_ci { 2646e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 2647e5c31af7Sopenharmony_ci { 2648e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = result.getPixel(px, py); 2649e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = reference.getPixel(px, py); 2650e5c31af7Sopenharmony_ci 2651e5c31af7Sopenharmony_ci // Other channels should trivially match to reference. 2652e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold))) 2653e5c31af7Sopenharmony_ci { 2654e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2655e5c31af7Sopenharmony_ci numFailed += 1; 2656e5c31af7Sopenharmony_ci continue; 2657e5c31af7Sopenharmony_ci } 2658e5c31af7Sopenharmony_ci 2659e5c31af7Sopenharmony_ci // Reference result is known to be a valid result, we can 2660e5c31af7Sopenharmony_ci // skip verification if thes results are equal 2661e5c31af7Sopenharmony_ci if (resPix.x() != refPix.x()) 2662e5c31af7Sopenharmony_ci { 2663e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 2664e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 2665e5c31af7Sopenharmony_ci const float nx = wx / dstW; 2666e5c31af7Sopenharmony_ci const float ny = wy / dstH; 2667e5c31af7Sopenharmony_ci 2668e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 2669e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 2670e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 2671e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 2672e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 2673e5c31af7Sopenharmony_ci 2674e5c31af7Sopenharmony_ci const tcu::Vec3 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 2675e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), 2676e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)); 2677e5c31af7Sopenharmony_ci const tcu::Vec3 coordDx (triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 2678e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy), 2679e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)); 2680e5c31af7Sopenharmony_ci const tcu::Vec3 coordDy (triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 2681e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx), 2682e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)); 2683e5c31af7Sopenharmony_ci 2684e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec); 2685e5c31af7Sopenharmony_ci 2686e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 2687e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 2688e5c31af7Sopenharmony_ci { 2689e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 2690e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 2691e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 2692e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 2693e5c31af7Sopenharmony_ci 2694e5c31af7Sopenharmony_ci const tcu::Vec3 coordO (projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo), 2695e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo), 2696e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo)); 2697e5c31af7Sopenharmony_ci const tcu::Vec3 coordDxo (triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), 2698e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo), 2699e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)); 2700e5c31af7Sopenharmony_ci const tcu::Vec3 coordDyo (triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), 2701e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo), 2702e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)); 2703e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec); 2704e5c31af7Sopenharmony_ci 2705e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 2706e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 2707e5c31af7Sopenharmony_ci } 2708e5c31af7Sopenharmony_ci 2709e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(minLod, sampleParams.maxLod), lodPrec); 2710e5c31af7Sopenharmony_ci const bool isOk = tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x()); 2711e5c31af7Sopenharmony_ci 2712e5c31af7Sopenharmony_ci if (!isOk) 2713e5c31af7Sopenharmony_ci { 2714e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2715e5c31af7Sopenharmony_ci numFailed += 1; 2716e5c31af7Sopenharmony_ci } 2717e5c31af7Sopenharmony_ci } 2718e5c31af7Sopenharmony_ci } 2719e5c31af7Sopenharmony_ci } 2720e5c31af7Sopenharmony_ci 2721e5c31af7Sopenharmony_ci return numFailed; 2722e5c31af7Sopenharmony_ci} 2723e5c31af7Sopenharmony_ci 2724e5c31af7Sopenharmony_ciint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess& result, 2725e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 2726e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 2727e5c31af7Sopenharmony_ci const tcu::Texture2DArrayView& src, 2728e5c31af7Sopenharmony_ci const float* texCoord, 2729e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2730e5c31af7Sopenharmony_ci const tcu::TexComparePrecision& comparePrec, 2731e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2732e5c31af7Sopenharmony_ci const tcu::Vec3& nonShadowThreshold) 2733e5c31af7Sopenharmony_ci{ 2734e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 2735e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 2736e5c31af7Sopenharmony_ci 2737e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]); 2738e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]); 2739e5c31af7Sopenharmony_ci const tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]); 2740e5c31af7Sopenharmony_ci 2741e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 2742e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 2743e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 2744e5c31af7Sopenharmony_ci const tcu::IVec2 srcSize = tcu::IVec2(src.getWidth(), src.getHeight()); 2745e5c31af7Sopenharmony_ci 2746e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 2747e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 2748e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 2749e5c31af7Sopenharmony_ci const tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 2750e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 2751e5c31af7Sopenharmony_ci 2752e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 2753e5c31af7Sopenharmony_ci 2754e5c31af7Sopenharmony_ci int numFailed = 0; 2755e5c31af7Sopenharmony_ci 2756e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 2757e5c31af7Sopenharmony_ci { 2758e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 2759e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 2760e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 2761e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 2762e5c31af7Sopenharmony_ci }; 2763e5c31af7Sopenharmony_ci 2764e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 2765e5c31af7Sopenharmony_ci 2766e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 2767e5c31af7Sopenharmony_ci { 2768e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 2769e5c31af7Sopenharmony_ci { 2770e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = result.getPixel(px, py); 2771e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = reference.getPixel(px, py); 2772e5c31af7Sopenharmony_ci 2773e5c31af7Sopenharmony_ci // Other channels should trivially match to reference. 2774e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold))) 2775e5c31af7Sopenharmony_ci { 2776e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2777e5c31af7Sopenharmony_ci numFailed += 1; 2778e5c31af7Sopenharmony_ci continue; 2779e5c31af7Sopenharmony_ci } 2780e5c31af7Sopenharmony_ci 2781e5c31af7Sopenharmony_ci // Reference result is known to be a valid result, we can 2782e5c31af7Sopenharmony_ci // skip verification if thes results are equal 2783e5c31af7Sopenharmony_ci if (resPix.x() != refPix.x()) 2784e5c31af7Sopenharmony_ci { 2785e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 2786e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 2787e5c31af7Sopenharmony_ci const float nx = wx / dstW; 2788e5c31af7Sopenharmony_ci const float ny = wy / dstH; 2789e5c31af7Sopenharmony_ci 2790e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 2791e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 2792e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 2793e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 2794e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 2795e5c31af7Sopenharmony_ci 2796e5c31af7Sopenharmony_ci const tcu::Vec3 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 2797e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), 2798e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy)); 2799e5c31af7Sopenharmony_ci const tcu::Vec2 coordDx = tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 2800e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat(); 2801e5c31af7Sopenharmony_ci const tcu::Vec2 coordDy = tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 2802e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat(); 2803e5c31af7Sopenharmony_ci 2804e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec); 2805e5c31af7Sopenharmony_ci 2806e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 2807e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 2808e5c31af7Sopenharmony_ci { 2809e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 2810e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 2811e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 2812e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 2813e5c31af7Sopenharmony_ci 2814e5c31af7Sopenharmony_ci const tcu::Vec2 coordDxo = tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), 2815e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat(); 2816e5c31af7Sopenharmony_ci const tcu::Vec2 coordDyo = tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), 2817e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat(); 2818e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec); 2819e5c31af7Sopenharmony_ci 2820e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 2821e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 2822e5c31af7Sopenharmony_ci } 2823e5c31af7Sopenharmony_ci 2824e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec); 2825e5c31af7Sopenharmony_ci const bool isOk = tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x()); 2826e5c31af7Sopenharmony_ci 2827e5c31af7Sopenharmony_ci if (!isOk) 2828e5c31af7Sopenharmony_ci { 2829e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2830e5c31af7Sopenharmony_ci numFailed += 1; 2831e5c31af7Sopenharmony_ci } 2832e5c31af7Sopenharmony_ci } 2833e5c31af7Sopenharmony_ci } 2834e5c31af7Sopenharmony_ci } 2835e5c31af7Sopenharmony_ci 2836e5c31af7Sopenharmony_ci return numFailed; 2837e5c31af7Sopenharmony_ci} 2838e5c31af7Sopenharmony_ci 2839e5c31af7Sopenharmony_ciint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess& result, 2840e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 2841e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 2842e5c31af7Sopenharmony_ci const tcu::Texture1DView& src, 2843e5c31af7Sopenharmony_ci const float* texCoord, 2844e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2845e5c31af7Sopenharmony_ci const tcu::TexComparePrecision& comparePrec, 2846e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2847e5c31af7Sopenharmony_ci const tcu::Vec3& nonShadowThreshold) 2848e5c31af7Sopenharmony_ci{ 2849e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 2850e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 2851e5c31af7Sopenharmony_ci DE_ASSERT(result.getHeight() == 1); 2852e5c31af7Sopenharmony_ci 2853e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]); 2854e5c31af7Sopenharmony_ci 2855e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), 1); 2856e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 2857e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 2858e5c31af7Sopenharmony_ci const float srcSize = float(src.getWidth()); 2859e5c31af7Sopenharmony_ci 2860e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 2861e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 2862e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 2863e5c31af7Sopenharmony_ci 2864e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 2865e5c31af7Sopenharmony_ci 2866e5c31af7Sopenharmony_ci int numFailed = 0; 2867e5c31af7Sopenharmony_ci 2868e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 2869e5c31af7Sopenharmony_ci { 2870e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 2871e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 2872e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 2873e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 2874e5c31af7Sopenharmony_ci }; 2875e5c31af7Sopenharmony_ci 2876e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 2877e5c31af7Sopenharmony_ci 2878e5c31af7Sopenharmony_ci const int py = 0; 2879e5c31af7Sopenharmony_ci { 2880e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 2881e5c31af7Sopenharmony_ci { 2882e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = result.getPixel(px, py); 2883e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = reference.getPixel(px, py); 2884e5c31af7Sopenharmony_ci 2885e5c31af7Sopenharmony_ci // Other channels should trivially match to reference. 2886e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold))) 2887e5c31af7Sopenharmony_ci { 2888e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2889e5c31af7Sopenharmony_ci numFailed += 1; 2890e5c31af7Sopenharmony_ci continue; 2891e5c31af7Sopenharmony_ci } 2892e5c31af7Sopenharmony_ci 2893e5c31af7Sopenharmony_ci // Reference result is known to be a valid result, we can 2894e5c31af7Sopenharmony_ci // skip verification if thes results are equal 2895e5c31af7Sopenharmony_ci if (resPix.x() != refPix.x()) 2896e5c31af7Sopenharmony_ci { 2897e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 2898e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 2899e5c31af7Sopenharmony_ci const float nx = wx / dstW; 2900e5c31af7Sopenharmony_ci const float ny = wy / dstH; 2901e5c31af7Sopenharmony_ci 2902e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 2903e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 2904e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 2905e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 2906e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 2907e5c31af7Sopenharmony_ci 2908e5c31af7Sopenharmony_ci const float coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy)); 2909e5c31af7Sopenharmony_ci const float coordDx = triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * srcSize; 2910e5c31af7Sopenharmony_ci 2911e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeLodBoundsFromDerivates(coordDx, coordDx, lodPrec); 2912e5c31af7Sopenharmony_ci 2913e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 2914e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 2915e5c31af7Sopenharmony_ci { 2916e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 2917e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 2918e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 2919e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 2920e5c31af7Sopenharmony_ci 2921e5c31af7Sopenharmony_ci const float coordDxo = triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * srcSize; 2922e5c31af7Sopenharmony_ci const float coordDyo = triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * srcSize; 2923e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec); 2924e5c31af7Sopenharmony_ci 2925e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 2926e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 2927e5c31af7Sopenharmony_ci } 2928e5c31af7Sopenharmony_ci 2929e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec); 2930e5c31af7Sopenharmony_ci const bool isOk = tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, tcu::Vec1(coord), clampedLod, sampleParams.ref, resPix.x()); 2931e5c31af7Sopenharmony_ci 2932e5c31af7Sopenharmony_ci if (!isOk) 2933e5c31af7Sopenharmony_ci { 2934e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2935e5c31af7Sopenharmony_ci numFailed += 1; 2936e5c31af7Sopenharmony_ci } 2937e5c31af7Sopenharmony_ci } 2938e5c31af7Sopenharmony_ci } 2939e5c31af7Sopenharmony_ci } 2940e5c31af7Sopenharmony_ci 2941e5c31af7Sopenharmony_ci return numFailed; 2942e5c31af7Sopenharmony_ci} 2943e5c31af7Sopenharmony_ci 2944e5c31af7Sopenharmony_ciint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess& result, 2945e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 2946e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 2947e5c31af7Sopenharmony_ci const tcu::Texture1DArrayView& src, 2948e5c31af7Sopenharmony_ci const float* texCoord, 2949e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 2950e5c31af7Sopenharmony_ci const tcu::TexComparePrecision& comparePrec, 2951e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 2952e5c31af7Sopenharmony_ci const tcu::Vec3& nonShadowThreshold) 2953e5c31af7Sopenharmony_ci{ 2954e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 2955e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 2956e5c31af7Sopenharmony_ci DE_ASSERT(result.getHeight() == 1); 2957e5c31af7Sopenharmony_ci 2958e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]); 2959e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]); 2960e5c31af7Sopenharmony_ci 2961e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), 1); 2962e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 2963e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 2964e5c31af7Sopenharmony_ci const float srcSize = float(src.getWidth()); 2965e5c31af7Sopenharmony_ci 2966e5c31af7Sopenharmony_ci // Coordinates and lod per triangle. 2967e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 2968e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 2969e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 2970e5c31af7Sopenharmony_ci 2971e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 2972e5c31af7Sopenharmony_ci 2973e5c31af7Sopenharmony_ci int numFailed = 0; 2974e5c31af7Sopenharmony_ci 2975e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 2976e5c31af7Sopenharmony_ci { 2977e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 2978e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 2979e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 2980e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 2981e5c31af7Sopenharmony_ci }; 2982e5c31af7Sopenharmony_ci 2983e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 2984e5c31af7Sopenharmony_ci 2985e5c31af7Sopenharmony_ci const int py = 0; 2986e5c31af7Sopenharmony_ci { 2987e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 2988e5c31af7Sopenharmony_ci { 2989e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = result.getPixel(px, py); 2990e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = reference.getPixel(px, py); 2991e5c31af7Sopenharmony_ci 2992e5c31af7Sopenharmony_ci // Other channels should trivially match to reference. 2993e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold))) 2994e5c31af7Sopenharmony_ci { 2995e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 2996e5c31af7Sopenharmony_ci numFailed += 1; 2997e5c31af7Sopenharmony_ci continue; 2998e5c31af7Sopenharmony_ci } 2999e5c31af7Sopenharmony_ci 3000e5c31af7Sopenharmony_ci // Reference result is known to be a valid result, we can 3001e5c31af7Sopenharmony_ci // skip verification if these results are equal 3002e5c31af7Sopenharmony_ci if (resPix.x() != refPix.x()) 3003e5c31af7Sopenharmony_ci { 3004e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 3005e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 3006e5c31af7Sopenharmony_ci const float nx = wx / dstW; 3007e5c31af7Sopenharmony_ci const float ny = wy / dstH; 3008e5c31af7Sopenharmony_ci 3009e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 3010e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 3011e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 3012e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 3013e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 3014e5c31af7Sopenharmony_ci 3015e5c31af7Sopenharmony_ci const tcu::Vec2 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 3016e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy)); 3017e5c31af7Sopenharmony_ci const float coordDx = triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * srcSize; 3018e5c31af7Sopenharmony_ci 3019e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeLodBoundsFromDerivates(coordDx, coordDx, lodPrec); 3020e5c31af7Sopenharmony_ci 3021e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 3022e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 3023e5c31af7Sopenharmony_ci { 3024e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 3025e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 3026e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 3027e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 3028e5c31af7Sopenharmony_ci 3029e5c31af7Sopenharmony_ci const float coordDxo = triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * srcSize; 3030e5c31af7Sopenharmony_ci const float coordDyo = triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * srcSize; 3031e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec); 3032e5c31af7Sopenharmony_ci 3033e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 3034e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 3035e5c31af7Sopenharmony_ci } 3036e5c31af7Sopenharmony_ci 3037e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec); 3038e5c31af7Sopenharmony_ci const bool isOk = tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x()); 3039e5c31af7Sopenharmony_ci 3040e5c31af7Sopenharmony_ci if (!isOk) 3041e5c31af7Sopenharmony_ci { 3042e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 3043e5c31af7Sopenharmony_ci numFailed += 1; 3044e5c31af7Sopenharmony_ci } 3045e5c31af7Sopenharmony_ci } 3046e5c31af7Sopenharmony_ci } 3047e5c31af7Sopenharmony_ci } 3048e5c31af7Sopenharmony_ci 3049e5c31af7Sopenharmony_ci return numFailed; 3050e5c31af7Sopenharmony_ci} 3051e5c31af7Sopenharmony_ci 3052e5c31af7Sopenharmony_ciint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess& result, 3053e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess& reference, 3054e5c31af7Sopenharmony_ci const tcu::PixelBufferAccess& errorMask, 3055e5c31af7Sopenharmony_ci const tcu::TextureCubeArrayView& src, 3056e5c31af7Sopenharmony_ci const float* texCoord, 3057e5c31af7Sopenharmony_ci const ReferenceParams& sampleParams, 3058e5c31af7Sopenharmony_ci const tcu::TexComparePrecision& comparePrec, 3059e5c31af7Sopenharmony_ci const tcu::LodPrecision& lodPrec, 3060e5c31af7Sopenharmony_ci const tcu::Vec3& nonShadowThreshold) 3061e5c31af7Sopenharmony_ci{ 3062e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight()); 3063e5c31af7Sopenharmony_ci DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight()); 3064e5c31af7Sopenharmony_ci 3065e5c31af7Sopenharmony_ci const tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]); 3066e5c31af7Sopenharmony_ci const tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]); 3067e5c31af7Sopenharmony_ci const tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]); 3068e5c31af7Sopenharmony_ci const tcu::Vec4 qq = tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]); 3069e5c31af7Sopenharmony_ci 3070e5c31af7Sopenharmony_ci const tcu::IVec2 dstSize = tcu::IVec2(result.getWidth(), result.getHeight()); 3071e5c31af7Sopenharmony_ci const float dstW = float(dstSize.x()); 3072e5c31af7Sopenharmony_ci const float dstH = float(dstSize.y()); 3073e5c31af7Sopenharmony_ci const int srcSize = src.getSize(); 3074e5c31af7Sopenharmony_ci 3075e5c31af7Sopenharmony_ci // Coordinates per triangle. 3076e5c31af7Sopenharmony_ci const tcu::Vec3 triS[2] = { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) }; 3077e5c31af7Sopenharmony_ci const tcu::Vec3 triT[2] = { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) }; 3078e5c31af7Sopenharmony_ci const tcu::Vec3 triR[2] = { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) }; 3079e5c31af7Sopenharmony_ci const tcu::Vec3 triQ[2] = { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) }; 3080e5c31af7Sopenharmony_ci const tcu::Vec3 triW[2] = { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) }; 3081e5c31af7Sopenharmony_ci 3082e5c31af7Sopenharmony_ci const tcu::Vec2 lodBias ((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f); 3083e5c31af7Sopenharmony_ci 3084e5c31af7Sopenharmony_ci int numFailed = 0; 3085e5c31af7Sopenharmony_ci 3086e5c31af7Sopenharmony_ci const tcu::Vec2 lodOffsets[] = 3087e5c31af7Sopenharmony_ci { 3088e5c31af7Sopenharmony_ci tcu::Vec2(-1, 0), 3089e5c31af7Sopenharmony_ci tcu::Vec2(+1, 0), 3090e5c31af7Sopenharmony_ci tcu::Vec2( 0, -1), 3091e5c31af7Sopenharmony_ci tcu::Vec2( 0, +1), 3092e5c31af7Sopenharmony_ci }; 3093e5c31af7Sopenharmony_ci 3094e5c31af7Sopenharmony_ci tcu::clear(errorMask, tcu::RGBA::green().toVec()); 3095e5c31af7Sopenharmony_ci 3096e5c31af7Sopenharmony_ci for (int py = 0; py < result.getHeight(); py++) 3097e5c31af7Sopenharmony_ci { 3098e5c31af7Sopenharmony_ci for (int px = 0; px < result.getWidth(); px++) 3099e5c31af7Sopenharmony_ci { 3100e5c31af7Sopenharmony_ci const tcu::Vec4 resPix = result.getPixel(px, py); 3101e5c31af7Sopenharmony_ci const tcu::Vec4 refPix = reference.getPixel(px, py); 3102e5c31af7Sopenharmony_ci 3103e5c31af7Sopenharmony_ci // Other channels should trivially match to reference. 3104e5c31af7Sopenharmony_ci if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold))) 3105e5c31af7Sopenharmony_ci { 3106e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 3107e5c31af7Sopenharmony_ci numFailed += 1; 3108e5c31af7Sopenharmony_ci continue; 3109e5c31af7Sopenharmony_ci } 3110e5c31af7Sopenharmony_ci 3111e5c31af7Sopenharmony_ci // Reference result is known to be a valid result, we can 3112e5c31af7Sopenharmony_ci // skip verification if thes results are equal 3113e5c31af7Sopenharmony_ci if (resPix.x() != refPix.x()) 3114e5c31af7Sopenharmony_ci { 3115e5c31af7Sopenharmony_ci const float wx = (float)px + 0.5f; 3116e5c31af7Sopenharmony_ci const float wy = (float)py + 0.5f; 3117e5c31af7Sopenharmony_ci const float nx = wx / dstW; 3118e5c31af7Sopenharmony_ci const float ny = wy / dstH; 3119e5c31af7Sopenharmony_ci 3120e5c31af7Sopenharmony_ci const int triNdx = nx + ny >= 1.0f ? 1 : 0; 3121e5c31af7Sopenharmony_ci const float triWx = triNdx ? dstW - wx : wx; 3122e5c31af7Sopenharmony_ci const float triWy = triNdx ? dstH - wy : wy; 3123e5c31af7Sopenharmony_ci const float triNx = triNdx ? 1.0f - nx : nx; 3124e5c31af7Sopenharmony_ci const float triNy = triNdx ? 1.0f - ny : ny; 3125e5c31af7Sopenharmony_ci 3126e5c31af7Sopenharmony_ci const tcu::Vec4 coord (projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy), 3127e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy), 3128e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy), 3129e5c31af7Sopenharmony_ci projectedTriInterpolate(triQ[triNdx], triW[triNdx], triNx, triNy)); 3130e5c31af7Sopenharmony_ci const tcu::Vec3 coordDx (triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy), 3131e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy), 3132e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)); 3133e5c31af7Sopenharmony_ci const tcu::Vec3 coordDy (triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx), 3134e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx), 3135e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)); 3136e5c31af7Sopenharmony_ci 3137e5c31af7Sopenharmony_ci tcu::Vec2 lodBounds = tcu::computeCubeLodBoundsFromDerivates(coord.swizzle(0,1,2), coordDx, coordDy, srcSize, lodPrec); 3138e5c31af7Sopenharmony_ci 3139e5c31af7Sopenharmony_ci // Compute lod bounds across lodOffsets range. 3140e5c31af7Sopenharmony_ci for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++) 3141e5c31af7Sopenharmony_ci { 3142e5c31af7Sopenharmony_ci const float wxo = triWx + lodOffsets[lodOffsNdx].x(); 3143e5c31af7Sopenharmony_ci const float wyo = triWy + lodOffsets[lodOffsNdx].y(); 3144e5c31af7Sopenharmony_ci const float nxo = wxo/dstW; 3145e5c31af7Sopenharmony_ci const float nyo = wyo/dstH; 3146e5c31af7Sopenharmony_ci 3147e5c31af7Sopenharmony_ci const tcu::Vec3 coordO (projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo), 3148e5c31af7Sopenharmony_ci projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo), 3149e5c31af7Sopenharmony_ci projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo)); 3150e5c31af7Sopenharmony_ci const tcu::Vec3 coordDxo (triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo), 3151e5c31af7Sopenharmony_ci triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo), 3152e5c31af7Sopenharmony_ci triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)); 3153e5c31af7Sopenharmony_ci const tcu::Vec3 coordDyo (triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo), 3154e5c31af7Sopenharmony_ci triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo), 3155e5c31af7Sopenharmony_ci triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)); 3156e5c31af7Sopenharmony_ci const tcu::Vec2 lodO = tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec); 3157e5c31af7Sopenharmony_ci 3158e5c31af7Sopenharmony_ci lodBounds.x() = de::min(lodBounds.x(), lodO.x()); 3159e5c31af7Sopenharmony_ci lodBounds.y() = de::max(lodBounds.y(), lodO.y()); 3160e5c31af7Sopenharmony_ci } 3161e5c31af7Sopenharmony_ci 3162e5c31af7Sopenharmony_ci const tcu::Vec2 clampedLod = tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec); 3163e5c31af7Sopenharmony_ci const bool isOk = tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x()); 3164e5c31af7Sopenharmony_ci 3165e5c31af7Sopenharmony_ci if (!isOk) 3166e5c31af7Sopenharmony_ci { 3167e5c31af7Sopenharmony_ci errorMask.setPixel(tcu::RGBA::red().toVec(), px, py); 3168e5c31af7Sopenharmony_ci numFailed += 1; 3169e5c31af7Sopenharmony_ci } 3170e5c31af7Sopenharmony_ci } 3171e5c31af7Sopenharmony_ci } 3172e5c31af7Sopenharmony_ci } 3173e5c31af7Sopenharmony_ci 3174e5c31af7Sopenharmony_ci return numFailed; 3175e5c31af7Sopenharmony_ci} 3176e5c31af7Sopenharmony_ci 3177e5c31af7Sopenharmony_ci// Mipmap generation comparison. 3178e5c31af7Sopenharmony_ci 3179e5c31af7Sopenharmony_cistatic int compareGenMipmapBilinear (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision) 3180e5c31af7Sopenharmony_ci{ 3181e5c31af7Sopenharmony_ci DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures. 3182e5c31af7Sopenharmony_ci 3183e5c31af7Sopenharmony_ci const float dstW = float(dst.getWidth()); 3184e5c31af7Sopenharmony_ci const float dstH = float(dst.getHeight()); 3185e5c31af7Sopenharmony_ci const float srcW = float(src.getWidth()); 3186e5c31af7Sopenharmony_ci const float srcH = float(src.getHeight()); 3187e5c31af7Sopenharmony_ci int numFailed = 0; 3188e5c31af7Sopenharmony_ci 3189e5c31af7Sopenharmony_ci // Translation to lookup verification parameters. 3190e5c31af7Sopenharmony_ci const tcu::Sampler sampler (tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, 3191e5c31af7Sopenharmony_ci tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, false /* non-normalized coords */); 3192e5c31af7Sopenharmony_ci tcu::LookupPrecision lookupPrec; 3193e5c31af7Sopenharmony_ci 3194e5c31af7Sopenharmony_ci lookupPrec.colorThreshold = precision.colorThreshold; 3195e5c31af7Sopenharmony_ci lookupPrec.colorMask = precision.colorMask; 3196e5c31af7Sopenharmony_ci lookupPrec.coordBits = tcu::IVec3(22); 3197e5c31af7Sopenharmony_ci lookupPrec.uvwBits = precision.filterBits; 3198e5c31af7Sopenharmony_ci 3199e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 3200e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 3201e5c31af7Sopenharmony_ci { 3202e5c31af7Sopenharmony_ci const tcu::Vec4 result = dst.getPixel(x, y); 3203e5c31af7Sopenharmony_ci const float cx = (float(x)+0.5f) / dstW * srcW; 3204e5c31af7Sopenharmony_ci const float cy = (float(y)+0.5f) / dstH * srcH; 3205e5c31af7Sopenharmony_ci const bool isOk = tcu::isLinearSampleResultValid(src, sampler, lookupPrec, tcu::Vec2(cx, cy), 0, result); 3206e5c31af7Sopenharmony_ci 3207e5c31af7Sopenharmony_ci errorMask.setPixel(isOk ? tcu::RGBA::green().toVec() : tcu::RGBA::red().toVec(), x, y); 3208e5c31af7Sopenharmony_ci if (!isOk) 3209e5c31af7Sopenharmony_ci numFailed += 1; 3210e5c31af7Sopenharmony_ci } 3211e5c31af7Sopenharmony_ci 3212e5c31af7Sopenharmony_ci return numFailed; 3213e5c31af7Sopenharmony_ci} 3214e5c31af7Sopenharmony_ci 3215e5c31af7Sopenharmony_cistatic int compareGenMipmapBox (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision) 3216e5c31af7Sopenharmony_ci{ 3217e5c31af7Sopenharmony_ci DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures. 3218e5c31af7Sopenharmony_ci 3219e5c31af7Sopenharmony_ci const float dstW = float(dst.getWidth()); 3220e5c31af7Sopenharmony_ci const float dstH = float(dst.getHeight()); 3221e5c31af7Sopenharmony_ci const float srcW = float(src.getWidth()); 3222e5c31af7Sopenharmony_ci const float srcH = float(src.getHeight()); 3223e5c31af7Sopenharmony_ci int numFailed = 0; 3224e5c31af7Sopenharmony_ci 3225e5c31af7Sopenharmony_ci // Translation to lookup verification parameters. 3226e5c31af7Sopenharmony_ci const tcu::Sampler sampler (tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, 3227e5c31af7Sopenharmony_ci tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, false /* non-normalized coords */); 3228e5c31af7Sopenharmony_ci tcu::LookupPrecision lookupPrec; 3229e5c31af7Sopenharmony_ci 3230e5c31af7Sopenharmony_ci lookupPrec.colorThreshold = precision.colorThreshold; 3231e5c31af7Sopenharmony_ci lookupPrec.colorMask = precision.colorMask; 3232e5c31af7Sopenharmony_ci lookupPrec.coordBits = tcu::IVec3(22); 3233e5c31af7Sopenharmony_ci lookupPrec.uvwBits = precision.filterBits; 3234e5c31af7Sopenharmony_ci 3235e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 3236e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 3237e5c31af7Sopenharmony_ci { 3238e5c31af7Sopenharmony_ci const tcu::Vec4 result = dst.getPixel(x, y); 3239e5c31af7Sopenharmony_ci const float cx = deFloatFloor(float(x) / dstW * srcW) + 1.0f; 3240e5c31af7Sopenharmony_ci const float cy = deFloatFloor(float(y) / dstH * srcH) + 1.0f; 3241e5c31af7Sopenharmony_ci const bool isOk = tcu::isLinearSampleResultValid(src, sampler, lookupPrec, tcu::Vec2(cx, cy), 0, result); 3242e5c31af7Sopenharmony_ci 3243e5c31af7Sopenharmony_ci errorMask.setPixel(isOk ? tcu::RGBA::green().toVec() : tcu::RGBA::red().toVec(), x, y); 3244e5c31af7Sopenharmony_ci if (!isOk) 3245e5c31af7Sopenharmony_ci numFailed += 1; 3246e5c31af7Sopenharmony_ci } 3247e5c31af7Sopenharmony_ci 3248e5c31af7Sopenharmony_ci return numFailed; 3249e5c31af7Sopenharmony_ci} 3250e5c31af7Sopenharmony_ci 3251e5c31af7Sopenharmony_cistatic int compareGenMipmapVeryLenient (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision) 3252e5c31af7Sopenharmony_ci{ 3253e5c31af7Sopenharmony_ci DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures. 3254e5c31af7Sopenharmony_ci DE_UNREF(precision); 3255e5c31af7Sopenharmony_ci 3256e5c31af7Sopenharmony_ci const float dstW = float(dst.getWidth()); 3257e5c31af7Sopenharmony_ci const float dstH = float(dst.getHeight()); 3258e5c31af7Sopenharmony_ci const float srcW = float(src.getWidth()); 3259e5c31af7Sopenharmony_ci const float srcH = float(src.getHeight()); 3260e5c31af7Sopenharmony_ci int numFailed = 0; 3261e5c31af7Sopenharmony_ci 3262e5c31af7Sopenharmony_ci for (int y = 0; y < dst.getHeight(); y++) 3263e5c31af7Sopenharmony_ci for (int x = 0; x < dst.getWidth(); x++) 3264e5c31af7Sopenharmony_ci { 3265e5c31af7Sopenharmony_ci const tcu::Vec4 result = dst.getPixel(x, y); 3266e5c31af7Sopenharmony_ci const int minX = deFloorFloatToInt32(((float)x-0.5f) / dstW * srcW); 3267e5c31af7Sopenharmony_ci const int minY = deFloorFloatToInt32(((float)y-0.5f) / dstH * srcH); 3268e5c31af7Sopenharmony_ci const int maxX = deCeilFloatToInt32(((float)x+1.5f) / dstW * srcW); 3269e5c31af7Sopenharmony_ci const int maxY = deCeilFloatToInt32(((float)y+1.5f) / dstH * srcH); 3270e5c31af7Sopenharmony_ci tcu::Vec4 minVal, maxVal; 3271e5c31af7Sopenharmony_ci bool isOk; 3272e5c31af7Sopenharmony_ci 3273e5c31af7Sopenharmony_ci DE_ASSERT(minX < maxX && minY < maxY); 3274e5c31af7Sopenharmony_ci 3275e5c31af7Sopenharmony_ci for (int ky = minY; ky <= maxY; ky++) 3276e5c31af7Sopenharmony_ci { 3277e5c31af7Sopenharmony_ci for (int kx = minX; kx <= maxX; kx++) 3278e5c31af7Sopenharmony_ci { 3279e5c31af7Sopenharmony_ci const int sx = de::clamp(kx, 0, src.getWidth()-1); 3280e5c31af7Sopenharmony_ci const int sy = de::clamp(ky, 0, src.getHeight()-1); 3281e5c31af7Sopenharmony_ci const tcu::Vec4 sample = src.getPixel(sx, sy); 3282e5c31af7Sopenharmony_ci 3283e5c31af7Sopenharmony_ci if (ky == minY && kx == minX) 3284e5c31af7Sopenharmony_ci { 3285e5c31af7Sopenharmony_ci minVal = sample; 3286e5c31af7Sopenharmony_ci maxVal = sample; 3287e5c31af7Sopenharmony_ci } 3288e5c31af7Sopenharmony_ci else 3289e5c31af7Sopenharmony_ci { 3290e5c31af7Sopenharmony_ci minVal = min(sample, minVal); 3291e5c31af7Sopenharmony_ci maxVal = max(sample, maxVal); 3292e5c31af7Sopenharmony_ci } 3293e5c31af7Sopenharmony_ci } 3294e5c31af7Sopenharmony_ci } 3295e5c31af7Sopenharmony_ci 3296e5c31af7Sopenharmony_ci isOk = boolAll(logicalAnd(lessThanEqual(minVal, result), lessThanEqual(result, maxVal))); 3297e5c31af7Sopenharmony_ci 3298e5c31af7Sopenharmony_ci errorMask.setPixel(isOk ? tcu::RGBA::green().toVec() : tcu::RGBA::red().toVec(), x, y); 3299e5c31af7Sopenharmony_ci if (!isOk) 3300e5c31af7Sopenharmony_ci numFailed += 1; 3301e5c31af7Sopenharmony_ci } 3302e5c31af7Sopenharmony_ci 3303e5c31af7Sopenharmony_ci return numFailed; 3304e5c31af7Sopenharmony_ci} 3305e5c31af7Sopenharmony_ci 3306e5c31af7Sopenharmony_ciqpTestResult compareGenMipmapResult (tcu::TestLog& log, const tcu::Texture2D& resultTexture, const tcu::Texture2D& level0Reference, const GenMipmapPrecision& precision) 3307e5c31af7Sopenharmony_ci{ 3308e5c31af7Sopenharmony_ci qpTestResult result = QP_TEST_RESULT_PASS; 3309e5c31af7Sopenharmony_ci 3310e5c31af7Sopenharmony_ci // Special comparison for level 0. 3311e5c31af7Sopenharmony_ci { 3312e5c31af7Sopenharmony_ci const tcu::Vec4 threshold = select(precision.colorThreshold, tcu::Vec4(1.0f), precision.colorMask); 3313e5c31af7Sopenharmony_ci const bool level0Ok = tcu::floatThresholdCompare(log, "Level0", "Level 0", level0Reference.getLevel(0), resultTexture.getLevel(0), threshold, tcu::COMPARE_LOG_RESULT); 3314e5c31af7Sopenharmony_ci 3315e5c31af7Sopenharmony_ci if (!level0Ok) 3316e5c31af7Sopenharmony_ci { 3317e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Level 0 comparison failed!" << tcu::TestLog::EndMessage; 3318e5c31af7Sopenharmony_ci result = QP_TEST_RESULT_FAIL; 3319e5c31af7Sopenharmony_ci } 3320e5c31af7Sopenharmony_ci } 3321e5c31af7Sopenharmony_ci 3322e5c31af7Sopenharmony_ci for (int levelNdx = 1; levelNdx < resultTexture.getNumLevels(); levelNdx++) 3323e5c31af7Sopenharmony_ci { 3324e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess src = resultTexture.getLevel(levelNdx-1); 3325e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess dst = resultTexture.getLevel(levelNdx); 3326e5c31af7Sopenharmony_ci tcu::Surface errorMask (dst.getWidth(), dst.getHeight()); 3327e5c31af7Sopenharmony_ci bool levelOk = false; 3328e5c31af7Sopenharmony_ci 3329e5c31af7Sopenharmony_ci // Try different comparisons in quality order. 3330e5c31af7Sopenharmony_ci 3331e5c31af7Sopenharmony_ci if (!levelOk) 3332e5c31af7Sopenharmony_ci { 3333e5c31af7Sopenharmony_ci const int numFailed = compareGenMipmapBilinear(dst, src, errorMask.getAccess(), precision); 3334e5c31af7Sopenharmony_ci if (numFailed == 0) 3335e5c31af7Sopenharmony_ci levelOk = true; 3336e5c31af7Sopenharmony_ci else 3337e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "WARNING: Level " << levelNdx << " comparison to bilinear method failed, found " << numFailed << " invalid pixels." << tcu::TestLog::EndMessage; 3338e5c31af7Sopenharmony_ci } 3339e5c31af7Sopenharmony_ci 3340e5c31af7Sopenharmony_ci if (!levelOk) 3341e5c31af7Sopenharmony_ci { 3342e5c31af7Sopenharmony_ci const int numFailed = compareGenMipmapBox(dst, src, errorMask.getAccess(), precision); 3343e5c31af7Sopenharmony_ci if (numFailed == 0) 3344e5c31af7Sopenharmony_ci levelOk = true; 3345e5c31af7Sopenharmony_ci else 3346e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "WARNING: Level " << levelNdx << " comparison to box method failed, found " << numFailed << " invalid pixels." << tcu::TestLog::EndMessage; 3347e5c31af7Sopenharmony_ci } 3348e5c31af7Sopenharmony_ci 3349e5c31af7Sopenharmony_ci // At this point all high-quality methods have been used. 3350e5c31af7Sopenharmony_ci if (!levelOk && result == QP_TEST_RESULT_PASS) 3351e5c31af7Sopenharmony_ci result = QP_TEST_RESULT_QUALITY_WARNING; 3352e5c31af7Sopenharmony_ci 3353e5c31af7Sopenharmony_ci if (!levelOk) 3354e5c31af7Sopenharmony_ci { 3355e5c31af7Sopenharmony_ci const int numFailed = compareGenMipmapVeryLenient(dst, src, errorMask.getAccess(), precision); 3356e5c31af7Sopenharmony_ci if (numFailed == 0) 3357e5c31af7Sopenharmony_ci levelOk = true; 3358e5c31af7Sopenharmony_ci else 3359e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Level " << levelNdx << " appears to contain " << numFailed << " completely wrong pixels, failing case!" << tcu::TestLog::EndMessage; 3360e5c31af7Sopenharmony_ci } 3361e5c31af7Sopenharmony_ci 3362e5c31af7Sopenharmony_ci if (!levelOk) 3363e5c31af7Sopenharmony_ci result = QP_TEST_RESULT_FAIL; 3364e5c31af7Sopenharmony_ci 3365e5c31af7Sopenharmony_ci log << tcu::TestLog::ImageSet(string("Level") + de::toString(levelNdx), string("Level ") + de::toString(levelNdx) + " result") 3366e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Result", "Result", dst); 3367e5c31af7Sopenharmony_ci 3368e5c31af7Sopenharmony_ci if (!levelOk) 3369e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 3370e5c31af7Sopenharmony_ci 3371e5c31af7Sopenharmony_ci log << tcu::TestLog::EndImageSet; 3372e5c31af7Sopenharmony_ci } 3373e5c31af7Sopenharmony_ci 3374e5c31af7Sopenharmony_ci return result; 3375e5c31af7Sopenharmony_ci} 3376e5c31af7Sopenharmony_ci 3377e5c31af7Sopenharmony_ciqpTestResult compareGenMipmapResult (tcu::TestLog& log, const tcu::TextureCube& resultTexture, const tcu::TextureCube& level0Reference, const GenMipmapPrecision& precision) 3378e5c31af7Sopenharmony_ci{ 3379e5c31af7Sopenharmony_ci qpTestResult result = QP_TEST_RESULT_PASS; 3380e5c31af7Sopenharmony_ci 3381e5c31af7Sopenharmony_ci static const char* s_faceNames[] = { "-X", "+X", "-Y", "+Y", "-Z", "+Z" }; 3382e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_faceNames) == tcu::CUBEFACE_LAST); 3383e5c31af7Sopenharmony_ci 3384e5c31af7Sopenharmony_ci // Special comparison for level 0. 3385e5c31af7Sopenharmony_ci for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 3386e5c31af7Sopenharmony_ci { 3387e5c31af7Sopenharmony_ci const tcu::CubeFace face = tcu::CubeFace(faceNdx); 3388e5c31af7Sopenharmony_ci const tcu::Vec4 threshold = select(precision.colorThreshold, tcu::Vec4(1.0f), precision.colorMask); 3389e5c31af7Sopenharmony_ci const bool level0Ok = tcu::floatThresholdCompare(log, 3390e5c31af7Sopenharmony_ci ("Level0Face" + de::toString(faceNdx)).c_str(), 3391e5c31af7Sopenharmony_ci (string("Level 0, face ") + s_faceNames[face]).c_str(), 3392e5c31af7Sopenharmony_ci level0Reference.getLevelFace(0, face), 3393e5c31af7Sopenharmony_ci resultTexture.getLevelFace(0, face), 3394e5c31af7Sopenharmony_ci threshold, tcu::COMPARE_LOG_RESULT); 3395e5c31af7Sopenharmony_ci 3396e5c31af7Sopenharmony_ci if (!level0Ok) 3397e5c31af7Sopenharmony_ci { 3398e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Level 0, face " << s_faceNames[face] << " comparison failed!" << tcu::TestLog::EndMessage; 3399e5c31af7Sopenharmony_ci result = QP_TEST_RESULT_FAIL; 3400e5c31af7Sopenharmony_ci } 3401e5c31af7Sopenharmony_ci } 3402e5c31af7Sopenharmony_ci 3403e5c31af7Sopenharmony_ci for (int levelNdx = 1; levelNdx < resultTexture.getNumLevels(); levelNdx++) 3404e5c31af7Sopenharmony_ci { 3405e5c31af7Sopenharmony_ci for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++) 3406e5c31af7Sopenharmony_ci { 3407e5c31af7Sopenharmony_ci const tcu::CubeFace face = tcu::CubeFace(faceNdx); 3408e5c31af7Sopenharmony_ci const char* faceName = s_faceNames[face]; 3409e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess src = resultTexture.getLevelFace(levelNdx-1, face); 3410e5c31af7Sopenharmony_ci const tcu::ConstPixelBufferAccess dst = resultTexture.getLevelFace(levelNdx, face); 3411e5c31af7Sopenharmony_ci tcu::Surface errorMask (dst.getWidth(), dst.getHeight()); 3412e5c31af7Sopenharmony_ci bool levelOk = false; 3413e5c31af7Sopenharmony_ci 3414e5c31af7Sopenharmony_ci // Try different comparisons in quality order. 3415e5c31af7Sopenharmony_ci 3416e5c31af7Sopenharmony_ci if (!levelOk) 3417e5c31af7Sopenharmony_ci { 3418e5c31af7Sopenharmony_ci const int numFailed = compareGenMipmapBilinear(dst, src, errorMask.getAccess(), precision); 3419e5c31af7Sopenharmony_ci if (numFailed == 0) 3420e5c31af7Sopenharmony_ci levelOk = true; 3421e5c31af7Sopenharmony_ci else 3422e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "WARNING: Level " << levelNdx << ", face " << faceName << " comparison to bilinear method failed, found " << numFailed << " invalid pixels." << tcu::TestLog::EndMessage; 3423e5c31af7Sopenharmony_ci } 3424e5c31af7Sopenharmony_ci 3425e5c31af7Sopenharmony_ci if (!levelOk) 3426e5c31af7Sopenharmony_ci { 3427e5c31af7Sopenharmony_ci const int numFailed = compareGenMipmapBox(dst, src, errorMask.getAccess(), precision); 3428e5c31af7Sopenharmony_ci if (numFailed == 0) 3429e5c31af7Sopenharmony_ci levelOk = true; 3430e5c31af7Sopenharmony_ci else 3431e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "WARNING: Level " << levelNdx << ", face " << faceName <<" comparison to box method failed, found " << numFailed << " invalid pixels." << tcu::TestLog::EndMessage; 3432e5c31af7Sopenharmony_ci } 3433e5c31af7Sopenharmony_ci 3434e5c31af7Sopenharmony_ci // At this point all high-quality methods have been used. 3435e5c31af7Sopenharmony_ci if (!levelOk && result == QP_TEST_RESULT_PASS) 3436e5c31af7Sopenharmony_ci result = QP_TEST_RESULT_QUALITY_WARNING; 3437e5c31af7Sopenharmony_ci 3438e5c31af7Sopenharmony_ci if (!levelOk) 3439e5c31af7Sopenharmony_ci { 3440e5c31af7Sopenharmony_ci const int numFailed = compareGenMipmapVeryLenient(dst, src, errorMask.getAccess(), precision); 3441e5c31af7Sopenharmony_ci if (numFailed == 0) 3442e5c31af7Sopenharmony_ci levelOk = true; 3443e5c31af7Sopenharmony_ci else 3444e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "ERROR: Level " << levelNdx << ", face " << faceName << " appears to contain " << numFailed << " completely wrong pixels, failing case!" << tcu::TestLog::EndMessage; 3445e5c31af7Sopenharmony_ci } 3446e5c31af7Sopenharmony_ci 3447e5c31af7Sopenharmony_ci if (!levelOk) 3448e5c31af7Sopenharmony_ci result = QP_TEST_RESULT_FAIL; 3449e5c31af7Sopenharmony_ci 3450e5c31af7Sopenharmony_ci log << tcu::TestLog::ImageSet(string("Level") + de::toString(levelNdx) + "Face" + de::toString(faceNdx), string("Level ") + de::toString(levelNdx) + ", face " + string(faceName) + " result") 3451e5c31af7Sopenharmony_ci << tcu::TestLog::Image("Result", "Result", dst); 3452e5c31af7Sopenharmony_ci 3453e5c31af7Sopenharmony_ci if (!levelOk) 3454e5c31af7Sopenharmony_ci log << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 3455e5c31af7Sopenharmony_ci 3456e5c31af7Sopenharmony_ci log << tcu::TestLog::EndImageSet; 3457e5c31af7Sopenharmony_ci } 3458e5c31af7Sopenharmony_ci } 3459e5c31af7Sopenharmony_ci 3460e5c31af7Sopenharmony_ci return result; 3461e5c31af7Sopenharmony_ci} 3462e5c31af7Sopenharmony_ci 3463e5c31af7Sopenharmony_ci// Logging utilities. 3464e5c31af7Sopenharmony_ci 3465e5c31af7Sopenharmony_cistd::ostream& operator<< (std::ostream& str, const LogGradientFmt& fmt) 3466e5c31af7Sopenharmony_ci{ 3467e5c31af7Sopenharmony_ci return str << "(R: " << fmt.valueMin->x() << " -> " << fmt.valueMax->x() << ", " 3468e5c31af7Sopenharmony_ci << "G: " << fmt.valueMin->y() << " -> " << fmt.valueMax->y() << ", " 3469e5c31af7Sopenharmony_ci << "B: " << fmt.valueMin->z() << " -> " << fmt.valueMax->z() << ", " 3470e5c31af7Sopenharmony_ci << "A: " << fmt.valueMin->w() << " -> " << fmt.valueMax->w() << ")"; 3471e5c31af7Sopenharmony_ci} 3472e5c31af7Sopenharmony_ci 3473e5c31af7Sopenharmony_ci} // TextureTestUtil 3474e5c31af7Sopenharmony_ci} // glu 3475