1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program Tester Core 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 Image comparison utilities. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp" 25e5c31af7Sopenharmony_ci#include "tcuSurface.hpp" 26e5c31af7Sopenharmony_ci#include "tcuFuzzyImageCompare.hpp" 27e5c31af7Sopenharmony_ci#include "tcuBilinearImageCompare.hpp" 28e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 29e5c31af7Sopenharmony_ci#include "tcuVector.hpp" 30e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp" 31e5c31af7Sopenharmony_ci#include "tcuRGBA.hpp" 32e5c31af7Sopenharmony_ci#include "tcuTexture.hpp" 33e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp" 34e5c31af7Sopenharmony_ci#include "tcuFloat.hpp" 35e5c31af7Sopenharmony_ci 36e5c31af7Sopenharmony_ci#include <string.h> 37e5c31af7Sopenharmony_ci 38e5c31af7Sopenharmony_cinamespace tcu 39e5c31af7Sopenharmony_ci{ 40e5c31af7Sopenharmony_ci 41e5c31af7Sopenharmony_cinamespace 42e5c31af7Sopenharmony_ci{ 43e5c31af7Sopenharmony_ci 44e5c31af7Sopenharmony_civoid computeScaleAndBias (const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, tcu::Vec4& scale, tcu::Vec4& bias) 45e5c31af7Sopenharmony_ci{ 46e5c31af7Sopenharmony_ci Vec4 minVal; 47e5c31af7Sopenharmony_ci Vec4 maxVal; 48e5c31af7Sopenharmony_ci const float eps = 0.0001f; 49e5c31af7Sopenharmony_ci 50e5c31af7Sopenharmony_ci { 51e5c31af7Sopenharmony_ci Vec4 refMin; 52e5c31af7Sopenharmony_ci Vec4 refMax; 53e5c31af7Sopenharmony_ci estimatePixelValueRange(reference, refMin, refMax); 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_ci minVal = refMin; 56e5c31af7Sopenharmony_ci maxVal = refMax; 57e5c31af7Sopenharmony_ci } 58e5c31af7Sopenharmony_ci 59e5c31af7Sopenharmony_ci { 60e5c31af7Sopenharmony_ci Vec4 resMin; 61e5c31af7Sopenharmony_ci Vec4 resMax; 62e5c31af7Sopenharmony_ci 63e5c31af7Sopenharmony_ci estimatePixelValueRange(result, resMin, resMax); 64e5c31af7Sopenharmony_ci 65e5c31af7Sopenharmony_ci minVal[0] = de::min(minVal[0], resMin[0]); 66e5c31af7Sopenharmony_ci minVal[1] = de::min(minVal[1], resMin[1]); 67e5c31af7Sopenharmony_ci minVal[2] = de::min(minVal[2], resMin[2]); 68e5c31af7Sopenharmony_ci minVal[3] = de::min(minVal[3], resMin[3]); 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_ci maxVal[0] = de::max(maxVal[0], resMax[0]); 71e5c31af7Sopenharmony_ci maxVal[1] = de::max(maxVal[1], resMax[1]); 72e5c31af7Sopenharmony_ci maxVal[2] = de::max(maxVal[2], resMax[2]); 73e5c31af7Sopenharmony_ci maxVal[3] = de::max(maxVal[3], resMax[3]); 74e5c31af7Sopenharmony_ci } 75e5c31af7Sopenharmony_ci 76e5c31af7Sopenharmony_ci for (int c = 0; c < 4; c++) 77e5c31af7Sopenharmony_ci { 78e5c31af7Sopenharmony_ci if (maxVal[c] - minVal[c] < eps) 79e5c31af7Sopenharmony_ci { 80e5c31af7Sopenharmony_ci scale[c] = (maxVal[c] < eps) ? 1.0f : (1.0f / maxVal[c]); 81e5c31af7Sopenharmony_ci bias[c] = (c == 3) ? (1.0f - maxVal[c]*scale[c]) : (0.0f - minVal[c]*scale[c]); 82e5c31af7Sopenharmony_ci } 83e5c31af7Sopenharmony_ci else 84e5c31af7Sopenharmony_ci { 85e5c31af7Sopenharmony_ci scale[c] = 1.0f / (maxVal[c] - minVal[c]); 86e5c31af7Sopenharmony_ci bias[c] = 0.0f - minVal[c]*scale[c]; 87e5c31af7Sopenharmony_ci } 88e5c31af7Sopenharmony_ci } 89e5c31af7Sopenharmony_ci} 90e5c31af7Sopenharmony_ci 91e5c31af7Sopenharmony_cistatic int findNumPositionDeviationFailingPixels (const PixelBufferAccess& errorMask, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, const tcu::IVec3& maxPositionDeviation, bool acceptOutOfBoundsAsAnyValue) 92e5c31af7Sopenharmony_ci{ 93e5c31af7Sopenharmony_ci const tcu::IVec4 okColor (0, 255, 0, 255); 94e5c31af7Sopenharmony_ci const tcu::IVec4 errorColor (255, 0, 0, 255); 95e5c31af7Sopenharmony_ci const int width = reference.getWidth(); 96e5c31af7Sopenharmony_ci const int height = reference.getHeight(); 97e5c31af7Sopenharmony_ci const int depth = reference.getDepth(); 98e5c31af7Sopenharmony_ci int numFailingPixels = 0; 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_ci // Accept pixels "sampling" over the image bounds pixels since "taps" could be anything 101e5c31af7Sopenharmony_ci const int beginX = (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.x()) : (0); 102e5c31af7Sopenharmony_ci const int beginY = (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.y()) : (0); 103e5c31af7Sopenharmony_ci const int beginZ = (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.z()) : (0); 104e5c31af7Sopenharmony_ci const int endX = (acceptOutOfBoundsAsAnyValue) ? (width - maxPositionDeviation.x()) : (width); 105e5c31af7Sopenharmony_ci const int endY = (acceptOutOfBoundsAsAnyValue) ? (height - maxPositionDeviation.y()) : (height); 106e5c31af7Sopenharmony_ci const int endZ = (acceptOutOfBoundsAsAnyValue) ? (depth - maxPositionDeviation.z()) : (depth); 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 109e5c31af7Sopenharmony_ci DE_ASSERT(endX > 0 && endY > 0 && endZ > 0); // most likely a bug 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci tcu::clear(errorMask, okColor); 112e5c31af7Sopenharmony_ci 113e5c31af7Sopenharmony_ci for (int z = beginZ; z < endZ; z++) 114e5c31af7Sopenharmony_ci { 115e5c31af7Sopenharmony_ci for (int y = beginY; y < endY; y++) 116e5c31af7Sopenharmony_ci { 117e5c31af7Sopenharmony_ci for (int x = beginX; x < endX; x++) 118e5c31af7Sopenharmony_ci { 119e5c31af7Sopenharmony_ci const IVec4 refPix = reference.getPixelInt(x, y, z); 120e5c31af7Sopenharmony_ci const IVec4 cmpPix = result.getPixelInt(x, y, z); 121e5c31af7Sopenharmony_ci 122e5c31af7Sopenharmony_ci // Exact match 123e5c31af7Sopenharmony_ci { 124e5c31af7Sopenharmony_ci const UVec4 diff = abs(refPix - cmpPix).cast<deUint32>(); 125e5c31af7Sopenharmony_ci const bool isOk = boolAll(lessThanEqual(diff, threshold)); 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci if (isOk) 128e5c31af7Sopenharmony_ci continue; 129e5c31af7Sopenharmony_ci } 130e5c31af7Sopenharmony_ci 131e5c31af7Sopenharmony_ci // Find matching pixels for both result and reference pixel 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ci { 134e5c31af7Sopenharmony_ci bool pixelFoundForReference = false; 135e5c31af7Sopenharmony_ci 136e5c31af7Sopenharmony_ci // Find deviated result pixel for reference 137e5c31af7Sopenharmony_ci 138e5c31af7Sopenharmony_ci for (int sz = de::max(0, z - maxPositionDeviation.z()); sz <= de::min(depth - 1, z + maxPositionDeviation.z()) && !pixelFoundForReference; ++sz) 139e5c31af7Sopenharmony_ci for (int sy = de::max(0, y - maxPositionDeviation.y()); sy <= de::min(height - 1, y + maxPositionDeviation.y()) && !pixelFoundForReference; ++sy) 140e5c31af7Sopenharmony_ci for (int sx = de::max(0, x - maxPositionDeviation.x()); sx <= de::min(width - 1, x + maxPositionDeviation.x()) && !pixelFoundForReference; ++sx) 141e5c31af7Sopenharmony_ci { 142e5c31af7Sopenharmony_ci const IVec4 deviatedCmpPix = result.getPixelInt(sx, sy, sz); 143e5c31af7Sopenharmony_ci const UVec4 diff = abs(refPix - deviatedCmpPix).cast<deUint32>(); 144e5c31af7Sopenharmony_ci const bool isOk = boolAll(lessThanEqual(diff, threshold)); 145e5c31af7Sopenharmony_ci 146e5c31af7Sopenharmony_ci pixelFoundForReference = isOk; 147e5c31af7Sopenharmony_ci } 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_ci if (!pixelFoundForReference) 150e5c31af7Sopenharmony_ci { 151e5c31af7Sopenharmony_ci errorMask.setPixel(errorColor, x, y, z); 152e5c31af7Sopenharmony_ci ++numFailingPixels; 153e5c31af7Sopenharmony_ci continue; 154e5c31af7Sopenharmony_ci } 155e5c31af7Sopenharmony_ci } 156e5c31af7Sopenharmony_ci { 157e5c31af7Sopenharmony_ci bool pixelFoundForResult = false; 158e5c31af7Sopenharmony_ci 159e5c31af7Sopenharmony_ci // Find deviated reference pixel for result 160e5c31af7Sopenharmony_ci 161e5c31af7Sopenharmony_ci for (int sz = de::max(0, z - maxPositionDeviation.z()); sz <= de::min(depth - 1, z + maxPositionDeviation.z()) && !pixelFoundForResult; ++sz) 162e5c31af7Sopenharmony_ci for (int sy = de::max(0, y - maxPositionDeviation.y()); sy <= de::min(height - 1, y + maxPositionDeviation.y()) && !pixelFoundForResult; ++sy) 163e5c31af7Sopenharmony_ci for (int sx = de::max(0, x - maxPositionDeviation.x()); sx <= de::min(width - 1, x + maxPositionDeviation.x()) && !pixelFoundForResult; ++sx) 164e5c31af7Sopenharmony_ci { 165e5c31af7Sopenharmony_ci const IVec4 deviatedRefPix = reference.getPixelInt(sx, sy, sz); 166e5c31af7Sopenharmony_ci const UVec4 diff = abs(cmpPix - deviatedRefPix).cast<deUint32>(); 167e5c31af7Sopenharmony_ci const bool isOk = boolAll(lessThanEqual(diff, threshold)); 168e5c31af7Sopenharmony_ci 169e5c31af7Sopenharmony_ci pixelFoundForResult = isOk; 170e5c31af7Sopenharmony_ci } 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_ci if (!pixelFoundForResult) 173e5c31af7Sopenharmony_ci { 174e5c31af7Sopenharmony_ci errorMask.setPixel(errorColor, x, y, z); 175e5c31af7Sopenharmony_ci ++numFailingPixels; 176e5c31af7Sopenharmony_ci continue; 177e5c31af7Sopenharmony_ci } 178e5c31af7Sopenharmony_ci } 179e5c31af7Sopenharmony_ci } 180e5c31af7Sopenharmony_ci } 181e5c31af7Sopenharmony_ci } 182e5c31af7Sopenharmony_ci 183e5c31af7Sopenharmony_ci return numFailingPixels; 184e5c31af7Sopenharmony_ci} 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci} // anonymous 187e5c31af7Sopenharmony_ci 188e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 189e5c31af7Sopenharmony_ci * \brief Fuzzy image comparison 190e5c31af7Sopenharmony_ci * 191e5c31af7Sopenharmony_ci * This image comparison is designed for comparing images rendered by 3D 192e5c31af7Sopenharmony_ci * graphics APIs such as OpenGL. The comparison allows small local differences 193e5c31af7Sopenharmony_ci * and compensates for aliasing. 194e5c31af7Sopenharmony_ci * 195e5c31af7Sopenharmony_ci * The algorithm first performs light blurring on both images and then 196e5c31af7Sopenharmony_ci * does per-pixel analysis. Pixels are compared to 3x3 bilinear surface 197e5c31af7Sopenharmony_ci * defined by adjecent pixels. This compensates for both 1-pixel deviations 198e5c31af7Sopenharmony_ci * in geometry and aliasing in texture data. 199e5c31af7Sopenharmony_ci * 200e5c31af7Sopenharmony_ci * Error metric is computed based on the differences. On valid images the 201e5c31af7Sopenharmony_ci * metric is usually <0.01. Thus good threshold values are in range 0.02 to 202e5c31af7Sopenharmony_ci * 0.05. 203e5c31af7Sopenharmony_ci * 204e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 205e5c31af7Sopenharmony_ci * are. 206e5c31af7Sopenharmony_ci * 207e5c31af7Sopenharmony_ci * \note Currently supports only UNORM_INT8 formats 208e5c31af7Sopenharmony_ci * \param log Test log for results 209e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 210e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 211e5c31af7Sopenharmony_ci * \param reference Reference image 212e5c31af7Sopenharmony_ci * \param result Result image 213e5c31af7Sopenharmony_ci * \param threshold Error metric threshold (good values are 0.02-0.05) 214e5c31af7Sopenharmony_ci * \param logMode Logging mode 215e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 216e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 217e5c31af7Sopenharmony_cibool fuzzyCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, float threshold, CompareLogMode logMode) 218e5c31af7Sopenharmony_ci{ 219e5c31af7Sopenharmony_ci FuzzyCompareParams params; // Use defaults. 220e5c31af7Sopenharmony_ci TextureLevel errorMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight()); 221e5c31af7Sopenharmony_ci float difference = fuzzyCompare(params, reference, result, errorMask.getAccess()); 222e5c31af7Sopenharmony_ci bool isOk = difference <= threshold; 223e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 224e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 225e5c31af7Sopenharmony_ci 226e5c31af7Sopenharmony_ci if (!isOk || logMode == COMPARE_LOG_EVERYTHING) 227e5c31af7Sopenharmony_ci { 228e5c31af7Sopenharmony_ci // Generate more accurate error mask. 229e5c31af7Sopenharmony_ci params.maxSampleSkip = 0; 230e5c31af7Sopenharmony_ci fuzzyCompare(params, reference, result, errorMask.getAccess()); 231e5c31af7Sopenharmony_ci 232e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 233e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 234e5c31af7Sopenharmony_ci 235e5c31af7Sopenharmony_ci if (!isOk) 236e5c31af7Sopenharmony_ci log << TestLog::Message << "Image comparison failed: difference = " << difference << ", threshold = " << threshold << TestLog::EndMessage; 237e5c31af7Sopenharmony_ci 238e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 239e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 240e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 241e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 242e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 243e5c31af7Sopenharmony_ci } 244e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 245e5c31af7Sopenharmony_ci { 246e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 247e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 248e5c31af7Sopenharmony_ci 249e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 250e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 251e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 252e5c31af7Sopenharmony_ci } 253e5c31af7Sopenharmony_ci 254e5c31af7Sopenharmony_ci return isOk; 255e5c31af7Sopenharmony_ci} 256e5c31af7Sopenharmony_ci 257e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 258e5c31af7Sopenharmony_ci * \brief Per-pixel bitwise comparison 259e5c31af7Sopenharmony_ci * 260e5c31af7Sopenharmony_ci * This compare expects bit precision between result and reference image. 261e5c31af7Sopenharmony_ci * Comparison fails if any pixels do not match bitwise. 262e5c31af7Sopenharmony_ci * Reference and result format must match. 263e5c31af7Sopenharmony_ci * 264e5c31af7Sopenharmony_ci * This comparison can be used for any type texture formats since it does 265e5c31af7Sopenharmony_ci * not care about types. 266e5c31af7Sopenharmony_ci * 267e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 268e5c31af7Sopenharmony_ci * are. 269e5c31af7Sopenharmony_ci * 270e5c31af7Sopenharmony_ci * \param log Test log for results 271e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 272e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 273e5c31af7Sopenharmony_ci * \param reference Reference image 274e5c31af7Sopenharmony_ci * \param result Result image 275e5c31af7Sopenharmony_ci * \param logMode Logging mode 276e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 277e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 278e5c31af7Sopenharmony_cibool bitwiseCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, CompareLogMode logMode) 279e5c31af7Sopenharmony_ci{ 280e5c31af7Sopenharmony_ci int width = reference.getWidth(); 281e5c31af7Sopenharmony_ci int height = reference.getHeight(); 282e5c31af7Sopenharmony_ci int depth = reference.getDepth(); 283e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 284e5c31af7Sopenharmony_ci 285e5c31af7Sopenharmony_ci // Enforce texture has same channel count and channel size 286e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(reference.getFormat() == result.getFormat()); result.getPixelPitch(); 287e5c31af7Sopenharmony_ci 288e5c31af7Sopenharmony_ci TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 289e5c31af7Sopenharmony_ci PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 290e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 291e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 292e5c31af7Sopenharmony_ci bool compareOk = true; 293e5c31af7Sopenharmony_ci 294e5c31af7Sopenharmony_ci for (int z = 0; z < depth; z++) 295e5c31af7Sopenharmony_ci { 296e5c31af7Sopenharmony_ci for (int y = 0; y < height; y++) 297e5c31af7Sopenharmony_ci { 298e5c31af7Sopenharmony_ci for (int x = 0; x < width; x++) 299e5c31af7Sopenharmony_ci { 300e5c31af7Sopenharmony_ci const U64Vec4 refPix = reference.getPixelBitsAsUint64(x, y, z); 301e5c31af7Sopenharmony_ci const U64Vec4 cmpPix = result.getPixelBitsAsUint64(x, y, z); 302e5c31af7Sopenharmony_ci const bool isOk = (refPix == cmpPix); 303e5c31af7Sopenharmony_ci 304e5c31af7Sopenharmony_ci errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z); 305e5c31af7Sopenharmony_ci compareOk &= isOk; 306e5c31af7Sopenharmony_ci } 307e5c31af7Sopenharmony_ci } 308e5c31af7Sopenharmony_ci } 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 311e5c31af7Sopenharmony_ci { 312e5c31af7Sopenharmony_ci { 313e5c31af7Sopenharmony_ci const auto refChannelClass = tcu::getTextureChannelClass(reference.getFormat().type); 314e5c31af7Sopenharmony_ci const auto resChannelClass = tcu::getTextureChannelClass(result.getFormat().type); 315e5c31af7Sopenharmony_ci 316e5c31af7Sopenharmony_ci const bool refIsUint8 = (reference.getFormat().type == TextureFormat::UNSIGNED_INT8); 317e5c31af7Sopenharmony_ci const bool resIsUint8 = (result.getFormat().type == TextureFormat::UNSIGNED_INT8); 318e5c31af7Sopenharmony_ci 319e5c31af7Sopenharmony_ci const bool calcScaleBias = ((refChannelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT && !refIsUint8) || 320e5c31af7Sopenharmony_ci (resChannelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT && !resIsUint8)); 321e5c31af7Sopenharmony_ci 322e5c31af7Sopenharmony_ci // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 323e5c31af7Sopenharmony_ci if (calcScaleBias) 324e5c31af7Sopenharmony_ci { 325e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 326e5c31af7Sopenharmony_ci log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 327e5c31af7Sopenharmony_ci } 328e5c31af7Sopenharmony_ci } 329e5c31af7Sopenharmony_ci 330e5c31af7Sopenharmony_ci if (!compareOk) 331e5c31af7Sopenharmony_ci log << TestLog::Message << "Image comparison failed: Pixels with different values were found when bitwise precision is expected" << TestLog::EndMessage; 332e5c31af7Sopenharmony_ci 333e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 334e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 335e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 336e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 337e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 338e5c31af7Sopenharmony_ci } 339e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 340e5c31af7Sopenharmony_ci { 341e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 342e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 343e5c31af7Sopenharmony_ci 344e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 345e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 346e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 347e5c31af7Sopenharmony_ci } 348e5c31af7Sopenharmony_ci 349e5c31af7Sopenharmony_ci return compareOk; 350e5c31af7Sopenharmony_ci} 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 353e5c31af7Sopenharmony_ci * \brief Fuzzy image comparison 354e5c31af7Sopenharmony_ci * 355e5c31af7Sopenharmony_ci * This image comparison is designed for comparing images rendered by 3D 356e5c31af7Sopenharmony_ci * graphics APIs such as OpenGL. The comparison allows small local differences 357e5c31af7Sopenharmony_ci * and compensates for aliasing. 358e5c31af7Sopenharmony_ci * 359e5c31af7Sopenharmony_ci * The algorithm first performs light blurring on both images and then 360e5c31af7Sopenharmony_ci * does per-pixel analysis. Pixels are compared to 3x3 bilinear surface 361e5c31af7Sopenharmony_ci * defined by adjecent pixels. This compensates for both 1-pixel deviations 362e5c31af7Sopenharmony_ci * in geometry and aliasing in texture data. 363e5c31af7Sopenharmony_ci * 364e5c31af7Sopenharmony_ci * Error metric is computed based on the differences. On valid images the 365e5c31af7Sopenharmony_ci * metric is usually <0.01. Thus good threshold values are in range 0.02 to 366e5c31af7Sopenharmony_ci * 0.05. 367e5c31af7Sopenharmony_ci * 368e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 369e5c31af7Sopenharmony_ci * are. 370e5c31af7Sopenharmony_ci * 371e5c31af7Sopenharmony_ci * \note Currently supports only UNORM_INT8 formats 372e5c31af7Sopenharmony_ci * \param log Test log for results 373e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 374e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 375e5c31af7Sopenharmony_ci * \param reference Reference image 376e5c31af7Sopenharmony_ci * \param result Result image 377e5c31af7Sopenharmony_ci * \param threshold Error metric threshold (good values are 0.02-0.05) 378e5c31af7Sopenharmony_ci * \param logMode Logging mode 379e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 380e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 381e5c31af7Sopenharmony_cibool fuzzyCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, float threshold, CompareLogMode logMode) 382e5c31af7Sopenharmony_ci{ 383e5c31af7Sopenharmony_ci return fuzzyCompare(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold, logMode); 384e5c31af7Sopenharmony_ci} 385e5c31af7Sopenharmony_ci 386e5c31af7Sopenharmony_cistatic deInt64 computeSquaredDiffSum (const ConstPixelBufferAccess& ref, const ConstPixelBufferAccess& cmp, const PixelBufferAccess& diffMask, int diffFactor) 387e5c31af7Sopenharmony_ci{ 388e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(ref.getFormat().type == TextureFormat::UNORM_INT8 && cmp.getFormat().type == TextureFormat::UNORM_INT8); 389e5c31af7Sopenharmony_ci DE_ASSERT(ref.getWidth() == cmp.getWidth() && ref.getWidth() == diffMask.getWidth()); 390e5c31af7Sopenharmony_ci DE_ASSERT(ref.getHeight() == cmp.getHeight() && ref.getHeight() == diffMask.getHeight()); 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_ci deInt64 diffSum = 0; 393e5c31af7Sopenharmony_ci 394e5c31af7Sopenharmony_ci for (int y = 0; y < cmp.getHeight(); y++) 395e5c31af7Sopenharmony_ci { 396e5c31af7Sopenharmony_ci for (int x = 0; x < cmp.getWidth(); x++) 397e5c31af7Sopenharmony_ci { 398e5c31af7Sopenharmony_ci IVec4 a = ref.getPixelInt(x, y); 399e5c31af7Sopenharmony_ci IVec4 b = cmp.getPixelInt(x, y); 400e5c31af7Sopenharmony_ci IVec4 diff = abs(a - b); 401e5c31af7Sopenharmony_ci int sum = diff.x() + diff.y() + diff.z() + diff.w(); 402e5c31af7Sopenharmony_ci int sqSum = diff.x()*diff.x() + diff.y()*diff.y() + diff.z()*diff.z() + diff.w()*diff.w(); 403e5c31af7Sopenharmony_ci 404e5c31af7Sopenharmony_ci diffMask.setPixel(tcu::RGBA(deClamp32(sum*diffFactor, 0, 255), deClamp32(255-sum*diffFactor, 0, 255), 0, 255).toVec(), x, y); 405e5c31af7Sopenharmony_ci 406e5c31af7Sopenharmony_ci diffSum += (deInt64)sqSum; 407e5c31af7Sopenharmony_ci } 408e5c31af7Sopenharmony_ci } 409e5c31af7Sopenharmony_ci 410e5c31af7Sopenharmony_ci return diffSum; 411e5c31af7Sopenharmony_ci} 412e5c31af7Sopenharmony_ci 413e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 414e5c31af7Sopenharmony_ci * \brief Per-pixel difference accuracy metric 415e5c31af7Sopenharmony_ci * 416e5c31af7Sopenharmony_ci * Computes accuracy metric using per-pixel differences between reference 417e5c31af7Sopenharmony_ci * and result images. 418e5c31af7Sopenharmony_ci * 419e5c31af7Sopenharmony_ci * \note Supports only integer- and fixed-point formats 420e5c31af7Sopenharmony_ci * \param log Test log for results 421e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 422e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 423e5c31af7Sopenharmony_ci * \param reference Reference image 424e5c31af7Sopenharmony_ci * \param result Result image 425e5c31af7Sopenharmony_ci * \param bestScoreDiff Scaling factor 426e5c31af7Sopenharmony_ci * \param worstScoreDiff Scaling factor 427e5c31af7Sopenharmony_ci * \param logMode Logging mode 428e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 429e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 430e5c31af7Sopenharmony_ciint measurePixelDiffAccuracy (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, int bestScoreDiff, int worstScoreDiff, CompareLogMode logMode) 431e5c31af7Sopenharmony_ci{ 432e5c31af7Sopenharmony_ci TextureLevel diffMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight()); 433e5c31af7Sopenharmony_ci int diffFactor = 8; 434e5c31af7Sopenharmony_ci deInt64 squaredSum = computeSquaredDiffSum(reference, result, diffMask.getAccess(), diffFactor); 435e5c31af7Sopenharmony_ci float sum = deFloatSqrt((float)squaredSum); 436e5c31af7Sopenharmony_ci int score = deClamp32(deFloorFloatToInt32(100.0f - (de::max(sum-(float)bestScoreDiff, 0.0f) / (float)(worstScoreDiff-bestScoreDiff))*100.0f), 0, 100); 437e5c31af7Sopenharmony_ci const int failThreshold = 10; 438e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 439e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 440e5c31af7Sopenharmony_ci 441e5c31af7Sopenharmony_ci if (logMode == COMPARE_LOG_EVERYTHING || score <= failThreshold) 442e5c31af7Sopenharmony_ci { 443e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 444e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 445e5c31af7Sopenharmony_ci 446e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 447e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 448e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 449e5c31af7Sopenharmony_ci << TestLog::Image("DiffMask", "Difference", diffMask) 450e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 451e5c31af7Sopenharmony_ci } 452e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 453e5c31af7Sopenharmony_ci { 454e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 455e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 456e5c31af7Sopenharmony_ci 457e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 458e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 459e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 460e5c31af7Sopenharmony_ci } 461e5c31af7Sopenharmony_ci 462e5c31af7Sopenharmony_ci if (logMode != COMPARE_LOG_ON_ERROR || score <= failThreshold) 463e5c31af7Sopenharmony_ci log << TestLog::Integer("DiffSum", "Squared difference sum", "", QP_KEY_TAG_NONE, squaredSum) 464e5c31af7Sopenharmony_ci << TestLog::Integer("Score", "Score", "", QP_KEY_TAG_QUALITY, score); 465e5c31af7Sopenharmony_ci 466e5c31af7Sopenharmony_ci return score; 467e5c31af7Sopenharmony_ci} 468e5c31af7Sopenharmony_ci 469e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 470e5c31af7Sopenharmony_ci * \brief Per-pixel difference accuracy metric 471e5c31af7Sopenharmony_ci * 472e5c31af7Sopenharmony_ci * Computes accuracy metric using per-pixel differences between reference 473e5c31af7Sopenharmony_ci * and result images. 474e5c31af7Sopenharmony_ci * 475e5c31af7Sopenharmony_ci * \note Supports only integer- and fixed-point formats 476e5c31af7Sopenharmony_ci * \param log Test log for results 477e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 478e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 479e5c31af7Sopenharmony_ci * \param reference Reference image 480e5c31af7Sopenharmony_ci * \param result Result image 481e5c31af7Sopenharmony_ci * \param bestScoreDiff Scaling factor 482e5c31af7Sopenharmony_ci * \param worstScoreDiff Scaling factor 483e5c31af7Sopenharmony_ci * \param logMode Logging mode 484e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 485e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 486e5c31af7Sopenharmony_ciint measurePixelDiffAccuracy (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, int bestScoreDiff, int worstScoreDiff, CompareLogMode logMode) 487e5c31af7Sopenharmony_ci{ 488e5c31af7Sopenharmony_ci return measurePixelDiffAccuracy(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), bestScoreDiff, worstScoreDiff, logMode); 489e5c31af7Sopenharmony_ci} 490e5c31af7Sopenharmony_ci 491e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 492e5c31af7Sopenharmony_ci * Returns the index of float in a float space without denormals 493e5c31af7Sopenharmony_ci * so that: 494e5c31af7Sopenharmony_ci * 1) f(0.0) = 0 495e5c31af7Sopenharmony_ci * 2) f(-0.0) = 0 496e5c31af7Sopenharmony_ci * 3) f(b) = f(a) + 1 <==> b = nextAfter(a) 497e5c31af7Sopenharmony_ci * 498e5c31af7Sopenharmony_ci * See computeFloatFlushRelaxedULPDiff for details 499e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 500e5c31af7Sopenharmony_cistatic deInt32 getPositionOfIEEEFloatWithoutDenormals (float x) 501e5c31af7Sopenharmony_ci{ 502e5c31af7Sopenharmony_ci DE_ASSERT(!deIsNaN(x)); // not sane 503e5c31af7Sopenharmony_ci 504e5c31af7Sopenharmony_ci if (x == 0.0f) 505e5c31af7Sopenharmony_ci return 0; 506e5c31af7Sopenharmony_ci else if (x < 0.0f) 507e5c31af7Sopenharmony_ci return -getPositionOfIEEEFloatWithoutDenormals(-x); 508e5c31af7Sopenharmony_ci else 509e5c31af7Sopenharmony_ci { 510e5c31af7Sopenharmony_ci DE_ASSERT(x > 0.0f); 511e5c31af7Sopenharmony_ci 512e5c31af7Sopenharmony_ci const tcu::Float32 f(x); 513e5c31af7Sopenharmony_ci 514e5c31af7Sopenharmony_ci if (f.isDenorm()) 515e5c31af7Sopenharmony_ci { 516e5c31af7Sopenharmony_ci // Denorms are flushed to zero 517e5c31af7Sopenharmony_ci return 0; 518e5c31af7Sopenharmony_ci } 519e5c31af7Sopenharmony_ci else 520e5c31af7Sopenharmony_ci { 521e5c31af7Sopenharmony_ci // sign is 0, and it's a normal number. Natural position is its bit 522e5c31af7Sopenharmony_ci // pattern but since we've collapsed the denorms, we must remove 523e5c31af7Sopenharmony_ci // the gap here too to keep the float enumeration continuous. 524e5c31af7Sopenharmony_ci // 525e5c31af7Sopenharmony_ci // Denormals occupy one exponent pattern. Removing one from 526e5c31af7Sopenharmony_ci // exponent should to the trick. Add one since the removed range 527e5c31af7Sopenharmony_ci // contained one representable value, 0. 528e5c31af7Sopenharmony_ci return (deInt32)(f.bits() - (1u << 23u) + 1u); 529e5c31af7Sopenharmony_ci } 530e5c31af7Sopenharmony_ci } 531e5c31af7Sopenharmony_ci} 532e5c31af7Sopenharmony_ci 533e5c31af7Sopenharmony_cistatic deUint32 computeFloatFlushRelaxedULPDiff (float a, float b) 534e5c31af7Sopenharmony_ci{ 535e5c31af7Sopenharmony_ci if (deIsNaN(a) && deIsNaN(b)) 536e5c31af7Sopenharmony_ci return 0; 537e5c31af7Sopenharmony_ci else if (deIsNaN(a) || deIsNaN(b)) 538e5c31af7Sopenharmony_ci { 539e5c31af7Sopenharmony_ci return 0xFFFFFFFFu; 540e5c31af7Sopenharmony_ci } 541e5c31af7Sopenharmony_ci else 542e5c31af7Sopenharmony_ci { 543e5c31af7Sopenharmony_ci // Using the "definition 5" in Muller, Jean-Michel. "On the definition of ulp (x)" (2005) 544e5c31af7Sopenharmony_ci // assuming a floating point space is IEEE single precision floating point space without 545e5c31af7Sopenharmony_ci // denormals (and signed zeros). 546e5c31af7Sopenharmony_ci const deInt32 aIndex = getPositionOfIEEEFloatWithoutDenormals(a); 547e5c31af7Sopenharmony_ci const deInt32 bIndex = getPositionOfIEEEFloatWithoutDenormals(b); 548e5c31af7Sopenharmony_ci return (deUint32)de::abs(aIndex - bIndex); 549e5c31af7Sopenharmony_ci } 550e5c31af7Sopenharmony_ci} 551e5c31af7Sopenharmony_ci 552e5c31af7Sopenharmony_cistatic tcu::UVec4 computeFlushRelaxedULPDiff (const tcu::Vec4& a, const tcu::Vec4& b) 553e5c31af7Sopenharmony_ci{ 554e5c31af7Sopenharmony_ci return tcu::UVec4(computeFloatFlushRelaxedULPDiff(a.x(), b.x()), 555e5c31af7Sopenharmony_ci computeFloatFlushRelaxedULPDiff(a.y(), b.y()), 556e5c31af7Sopenharmony_ci computeFloatFlushRelaxedULPDiff(a.z(), b.z()), 557e5c31af7Sopenharmony_ci computeFloatFlushRelaxedULPDiff(a.w(), b.w())); 558e5c31af7Sopenharmony_ci} 559e5c31af7Sopenharmony_ci 560e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 561e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison 562e5c31af7Sopenharmony_ci * 563e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference 564e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value. 565e5c31af7Sopenharmony_ci * 566e5c31af7Sopenharmony_ci * This comparison uses ULP (units in last place) metric for computing the 567e5c31af7Sopenharmony_ci * difference between floating-point values and thus this function can 568e5c31af7Sopenharmony_ci * be used only for comparing floating-point texture data. In ULP calculation 569e5c31af7Sopenharmony_ci * the denormal numbers are allowed to be flushed to zero. 570e5c31af7Sopenharmony_ci * 571e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 572e5c31af7Sopenharmony_ci * are. 573e5c31af7Sopenharmony_ci * 574e5c31af7Sopenharmony_ci * \param log Test log for results 575e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 576e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 577e5c31af7Sopenharmony_ci * \param reference Reference image 578e5c31af7Sopenharmony_ci * \param result Result image 579e5c31af7Sopenharmony_ci * \param threshold Maximum allowed difference 580e5c31af7Sopenharmony_ci * \param logMode Logging mode 581e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 582e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 583e5c31af7Sopenharmony_cibool floatUlpThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode) 584e5c31af7Sopenharmony_ci{ 585e5c31af7Sopenharmony_ci int width = reference.getWidth(); 586e5c31af7Sopenharmony_ci int height = reference.getHeight(); 587e5c31af7Sopenharmony_ci int depth = reference.getDepth(); 588e5c31af7Sopenharmony_ci TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 589e5c31af7Sopenharmony_ci PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 590e5c31af7Sopenharmony_ci UVec4 maxDiff (0, 0, 0, 0); 591e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 592e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 593e5c31af7Sopenharmony_ci 594e5c31af7Sopenharmony_ci TCU_CHECK(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 595e5c31af7Sopenharmony_ci 596e5c31af7Sopenharmony_ci for (int z = 0; z < depth; z++) 597e5c31af7Sopenharmony_ci { 598e5c31af7Sopenharmony_ci for (int y = 0; y < height; y++) 599e5c31af7Sopenharmony_ci { 600e5c31af7Sopenharmony_ci for (int x = 0; x < width; x++) 601e5c31af7Sopenharmony_ci { 602e5c31af7Sopenharmony_ci const Vec4 refPix = reference.getPixel(x, y, z); 603e5c31af7Sopenharmony_ci const Vec4 cmpPix = result.getPixel(x, y, z); 604e5c31af7Sopenharmony_ci const UVec4 diff = computeFlushRelaxedULPDiff(refPix, cmpPix); 605e5c31af7Sopenharmony_ci const bool isOk = boolAll(lessThanEqual(diff, threshold)); 606e5c31af7Sopenharmony_ci 607e5c31af7Sopenharmony_ci maxDiff = max(maxDiff, diff); 608e5c31af7Sopenharmony_ci 609e5c31af7Sopenharmony_ci errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 610e5c31af7Sopenharmony_ci } 611e5c31af7Sopenharmony_ci } 612e5c31af7Sopenharmony_ci } 613e5c31af7Sopenharmony_ci 614e5c31af7Sopenharmony_ci bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 617e5c31af7Sopenharmony_ci { 618e5c31af7Sopenharmony_ci // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 619e5c31af7Sopenharmony_ci if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 620e5c31af7Sopenharmony_ci tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 621e5c31af7Sopenharmony_ci { 622e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 623e5c31af7Sopenharmony_ci log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 624e5c31af7Sopenharmony_ci } 625e5c31af7Sopenharmony_ci 626e5c31af7Sopenharmony_ci if (!compareOk) 627e5c31af7Sopenharmony_ci log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 628e5c31af7Sopenharmony_ci 629e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 630e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 631e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 632e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 633e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 634e5c31af7Sopenharmony_ci } 635e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 636e5c31af7Sopenharmony_ci { 637e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 638e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 639e5c31af7Sopenharmony_ci 640e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 641e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 642e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 643e5c31af7Sopenharmony_ci } 644e5c31af7Sopenharmony_ci 645e5c31af7Sopenharmony_ci return compareOk; 646e5c31af7Sopenharmony_ci} 647e5c31af7Sopenharmony_ci 648e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 649e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison 650e5c31af7Sopenharmony_ci * 651e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference 652e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value. 653e5c31af7Sopenharmony_ci * 654e5c31af7Sopenharmony_ci * This comparison can be used for floating-point and fixed-point formats. 655e5c31af7Sopenharmony_ci * Difference is computed in floating-point space. 656e5c31af7Sopenharmony_ci * 657e5c31af7Sopenharmony_ci * On failure an error image is generated that shows where the failing 658e5c31af7Sopenharmony_ci * pixels are. 659e5c31af7Sopenharmony_ci * 660e5c31af7Sopenharmony_ci * \param log Test log for results 661e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 662e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 663e5c31af7Sopenharmony_ci * \param reference Reference image 664e5c31af7Sopenharmony_ci * \param result Result image 665e5c31af7Sopenharmony_ci * \param threshold Maximum allowed difference 666e5c31af7Sopenharmony_ci * \param logMode Logging mode 667e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 668e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 669e5c31af7Sopenharmony_cibool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode) 670e5c31af7Sopenharmony_ci{ 671e5c31af7Sopenharmony_ci int width = reference.getWidth(); 672e5c31af7Sopenharmony_ci int height = reference.getHeight(); 673e5c31af7Sopenharmony_ci int depth = reference.getDepth(); 674e5c31af7Sopenharmony_ci TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 675e5c31af7Sopenharmony_ci PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 676e5c31af7Sopenharmony_ci Vec4 maxDiff (0.0f, 0.0f, 0.0f, 0.0f); 677e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 678e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 679e5c31af7Sopenharmony_ci 680e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 681e5c31af7Sopenharmony_ci 682e5c31af7Sopenharmony_ci for (int z = 0; z < depth; z++) 683e5c31af7Sopenharmony_ci { 684e5c31af7Sopenharmony_ci for (int y = 0; y < height; y++) 685e5c31af7Sopenharmony_ci { 686e5c31af7Sopenharmony_ci for (int x = 0; x < width; x++) 687e5c31af7Sopenharmony_ci { 688e5c31af7Sopenharmony_ci Vec4 refPix = reference.getPixel(x, y, z); 689e5c31af7Sopenharmony_ci Vec4 cmpPix = result.getPixel(x, y, z); 690e5c31af7Sopenharmony_ci 691e5c31af7Sopenharmony_ci Vec4 diff = abs(refPix - cmpPix); 692e5c31af7Sopenharmony_ci bool isOk = boolAll(lessThanEqual(diff, threshold)); 693e5c31af7Sopenharmony_ci 694e5c31af7Sopenharmony_ci maxDiff = max(maxDiff, diff); 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 697e5c31af7Sopenharmony_ci } 698e5c31af7Sopenharmony_ci } 699e5c31af7Sopenharmony_ci } 700e5c31af7Sopenharmony_ci 701e5c31af7Sopenharmony_ci bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 702e5c31af7Sopenharmony_ci 703e5c31af7Sopenharmony_ci if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 704e5c31af7Sopenharmony_ci { 705e5c31af7Sopenharmony_ci // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 706e5c31af7Sopenharmony_ci if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 707e5c31af7Sopenharmony_ci tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 708e5c31af7Sopenharmony_ci { 709e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 710e5c31af7Sopenharmony_ci log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 711e5c31af7Sopenharmony_ci } 712e5c31af7Sopenharmony_ci 713e5c31af7Sopenharmony_ci if (!compareOk) 714e5c31af7Sopenharmony_ci log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 715e5c31af7Sopenharmony_ci 716e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 717e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 718e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 719e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 720e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 721e5c31af7Sopenharmony_ci } 722e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 723e5c31af7Sopenharmony_ci { 724e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 725e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 726e5c31af7Sopenharmony_ci 727e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 728e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 729e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 730e5c31af7Sopenharmony_ci } 731e5c31af7Sopenharmony_ci 732e5c31af7Sopenharmony_ci return compareOk; 733e5c31af7Sopenharmony_ci} 734e5c31af7Sopenharmony_ci 735e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 736e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison with ignore key 737e5c31af7Sopenharmony_ci * 738e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference 739e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value. 740e5c31af7Sopenharmony_ci * 741e5c31af7Sopenharmony_ci * Any pixels in reference that match the ignore key are ignored. 742e5c31af7Sopenharmony_ci * 743e5c31af7Sopenharmony_ci * This comparison can be used for floating-point and fixed-point formats. 744e5c31af7Sopenharmony_ci * Difference is computed in floating-point space. 745e5c31af7Sopenharmony_ci * 746e5c31af7Sopenharmony_ci * On failure an error image is generated that shows where the failing 747e5c31af7Sopenharmony_ci * pixels are. 748e5c31af7Sopenharmony_ci * 749e5c31af7Sopenharmony_ci * \param log Test log for results 750e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 751e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 752e5c31af7Sopenharmony_ci * \param reference Reference image 753e5c31af7Sopenharmony_ci * \param result Result image 754e5c31af7Sopenharmony_ci * \param ignorekey Ignore key 755e5c31af7Sopenharmony_ci * \param threshold Maximum allowed difference 756e5c31af7Sopenharmony_ci * \param logMode Logging mode 757e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 758e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 759e5c31af7Sopenharmony_cibool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const Vec4& ignorekey, const Vec4& threshold, CompareLogMode logMode) 760e5c31af7Sopenharmony_ci{ 761e5c31af7Sopenharmony_ci int width = reference.getWidth(); 762e5c31af7Sopenharmony_ci int height = reference.getHeight(); 763e5c31af7Sopenharmony_ci int depth = reference.getDepth(); 764e5c31af7Sopenharmony_ci TextureLevel errorMaskStorage(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 765e5c31af7Sopenharmony_ci PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 766e5c31af7Sopenharmony_ci Vec4 maxDiff(0.0f, 0.0f, 0.0f, 0.0f); 767e5c31af7Sopenharmony_ci Vec4 pixelBias(0.0f, 0.0f, 0.0f, 0.0f); 768e5c31af7Sopenharmony_ci Vec4 pixelScale(1.0f, 1.0f, 1.0f, 1.0f); 769e5c31af7Sopenharmony_ci 770e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 771e5c31af7Sopenharmony_ci 772e5c31af7Sopenharmony_ci for (int z = 0; z < depth; z++) 773e5c31af7Sopenharmony_ci { 774e5c31af7Sopenharmony_ci for (int y = 0; y < height; y++) 775e5c31af7Sopenharmony_ci { 776e5c31af7Sopenharmony_ci for (int x = 0; x < width; x++) 777e5c31af7Sopenharmony_ci { 778e5c31af7Sopenharmony_ci Vec4 refPix = reference.getPixel(x, y, z); 779e5c31af7Sopenharmony_ci Vec4 cmpPix = result.getPixel(x, y, z); 780e5c31af7Sopenharmony_ci 781e5c31af7Sopenharmony_ci if (refPix != ignorekey) 782e5c31af7Sopenharmony_ci { 783e5c31af7Sopenharmony_ci 784e5c31af7Sopenharmony_ci Vec4 diff = abs(refPix - cmpPix); 785e5c31af7Sopenharmony_ci bool isOk = boolAll(lessThanEqual(diff, threshold)); 786e5c31af7Sopenharmony_ci 787e5c31af7Sopenharmony_ci maxDiff = max(maxDiff, diff); 788e5c31af7Sopenharmony_ci 789e5c31af7Sopenharmony_ci errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 790e5c31af7Sopenharmony_ci } 791e5c31af7Sopenharmony_ci } 792e5c31af7Sopenharmony_ci } 793e5c31af7Sopenharmony_ci } 794e5c31af7Sopenharmony_ci 795e5c31af7Sopenharmony_ci bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 796e5c31af7Sopenharmony_ci 797e5c31af7Sopenharmony_ci if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 798e5c31af7Sopenharmony_ci { 799e5c31af7Sopenharmony_ci // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 800e5c31af7Sopenharmony_ci if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 801e5c31af7Sopenharmony_ci tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 802e5c31af7Sopenharmony_ci { 803e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 804e5c31af7Sopenharmony_ci log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 805e5c31af7Sopenharmony_ci } 806e5c31af7Sopenharmony_ci 807e5c31af7Sopenharmony_ci if (!compareOk) 808e5c31af7Sopenharmony_ci log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 809e5c31af7Sopenharmony_ci 810e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 811e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 812e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 813e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 814e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 815e5c31af7Sopenharmony_ci } 816e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 817e5c31af7Sopenharmony_ci { 818e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 819e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 820e5c31af7Sopenharmony_ci 821e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 822e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 823e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 824e5c31af7Sopenharmony_ci } 825e5c31af7Sopenharmony_ci 826e5c31af7Sopenharmony_ci return compareOk; 827e5c31af7Sopenharmony_ci} 828e5c31af7Sopenharmony_ci 829e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 830e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison 831e5c31af7Sopenharmony_ci * 832e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference 833e5c31af7Sopenharmony_ci * color. Comparison fails if any pixels exceed the given threshold value. 834e5c31af7Sopenharmony_ci * 835e5c31af7Sopenharmony_ci * This comparison can be used for floating-point and fixed-point formats. 836e5c31af7Sopenharmony_ci * Difference is computed in floating-point space. 837e5c31af7Sopenharmony_ci * 838e5c31af7Sopenharmony_ci * On failure an error image is generated that shows where the failing 839e5c31af7Sopenharmony_ci * pixels are. 840e5c31af7Sopenharmony_ci * 841e5c31af7Sopenharmony_ci * \param log Test log for results 842e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 843e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 844e5c31af7Sopenharmony_ci * \param reference Reference color 845e5c31af7Sopenharmony_ci * \param result Result image 846e5c31af7Sopenharmony_ci * \param threshold Maximum allowed difference 847e5c31af7Sopenharmony_ci * \param logMode Logging mode 848e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 849e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 850e5c31af7Sopenharmony_cibool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Vec4& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode) 851e5c31af7Sopenharmony_ci{ 852e5c31af7Sopenharmony_ci const int width = result.getWidth(); 853e5c31af7Sopenharmony_ci const int height = result.getHeight(); 854e5c31af7Sopenharmony_ci const int depth = result.getDepth(); 855e5c31af7Sopenharmony_ci 856e5c31af7Sopenharmony_ci TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 857e5c31af7Sopenharmony_ci PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 858e5c31af7Sopenharmony_ci Vec4 maxDiff (0.0f, 0.0f, 0.0f, 0.0f); 859e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 860e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 861e5c31af7Sopenharmony_ci 862e5c31af7Sopenharmony_ci for (int z = 0; z < depth; z++) 863e5c31af7Sopenharmony_ci { 864e5c31af7Sopenharmony_ci for (int y = 0; y < height; y++) 865e5c31af7Sopenharmony_ci { 866e5c31af7Sopenharmony_ci for (int x = 0; x < width; x++) 867e5c31af7Sopenharmony_ci { 868e5c31af7Sopenharmony_ci const Vec4 cmpPix = result.getPixel(x, y, z); 869e5c31af7Sopenharmony_ci const Vec4 diff = abs(reference - cmpPix); 870e5c31af7Sopenharmony_ci const bool isOk = boolAll(lessThanEqual(diff, threshold)); 871e5c31af7Sopenharmony_ci 872e5c31af7Sopenharmony_ci maxDiff = max(maxDiff, diff); 873e5c31af7Sopenharmony_ci 874e5c31af7Sopenharmony_ci if (isOk) 875e5c31af7Sopenharmony_ci errorMask.setPixel(Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y, z); 876e5c31af7Sopenharmony_ci else 877e5c31af7Sopenharmony_ci errorMask.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 878e5c31af7Sopenharmony_ci } 879e5c31af7Sopenharmony_ci } 880e5c31af7Sopenharmony_ci } 881e5c31af7Sopenharmony_ci 882e5c31af7Sopenharmony_ci bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 883e5c31af7Sopenharmony_ci 884e5c31af7Sopenharmony_ci if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 885e5c31af7Sopenharmony_ci { 886e5c31af7Sopenharmony_ci // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 887e5c31af7Sopenharmony_ci if (tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 888e5c31af7Sopenharmony_ci { 889e5c31af7Sopenharmony_ci computeScaleAndBias(result, result, pixelScale, pixelBias); 890e5c31af7Sopenharmony_ci log << TestLog::Message << "Result image is normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 891e5c31af7Sopenharmony_ci } 892e5c31af7Sopenharmony_ci 893e5c31af7Sopenharmony_ci if (!compareOk) 894e5c31af7Sopenharmony_ci log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << ", reference = " << reference << TestLog::EndMessage; 895e5c31af7Sopenharmony_ci 896e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 897e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 898e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 899e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 900e5c31af7Sopenharmony_ci } 901e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 902e5c31af7Sopenharmony_ci { 903e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 904e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 905e5c31af7Sopenharmony_ci 906e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 907e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 908e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 909e5c31af7Sopenharmony_ci } 910e5c31af7Sopenharmony_ci 911e5c31af7Sopenharmony_ci return compareOk; 912e5c31af7Sopenharmony_ci} 913e5c31af7Sopenharmony_ci 914e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 915e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison 916e5c31af7Sopenharmony_ci * 917e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference 918e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value. 919e5c31af7Sopenharmony_ci * 920e5c31af7Sopenharmony_ci * This comparison can be used for integer- and fixed-point texture formats. 921e5c31af7Sopenharmony_ci * Difference is computed in integer space. 922e5c31af7Sopenharmony_ci * 923e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 924e5c31af7Sopenharmony_ci * are. 925e5c31af7Sopenharmony_ci * 926e5c31af7Sopenharmony_ci * \param log Test log for results 927e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 928e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 929e5c31af7Sopenharmony_ci * \param reference Reference image 930e5c31af7Sopenharmony_ci * \param result Result image 931e5c31af7Sopenharmony_ci * \param threshold Maximum allowed difference 932e5c31af7Sopenharmony_ci * \param logMode Logging mode 933e5c31af7Sopenharmony_ci * \param use64Bits Use 64-bit components when reading image data. 934e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 935e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 936e5c31af7Sopenharmony_cibool intThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode, bool use64Bits) 937e5c31af7Sopenharmony_ci{ 938e5c31af7Sopenharmony_ci int width = reference.getWidth(); 939e5c31af7Sopenharmony_ci int height = reference.getHeight(); 940e5c31af7Sopenharmony_ci int depth = reference.getDepth(); 941e5c31af7Sopenharmony_ci TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 942e5c31af7Sopenharmony_ci PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 943e5c31af7Sopenharmony_ci U64Vec4 maxDiff (0u, 0u, 0u, 0u); 944e5c31af7Sopenharmony_ci U64Vec4 diff (0u, 0u, 0u, 0u); 945e5c31af7Sopenharmony_ci const U64Vec4 threshold64 = threshold.cast<deUint64>(); 946e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 947e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 948e5c31af7Sopenharmony_ci 949e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 950e5c31af7Sopenharmony_ci 951e5c31af7Sopenharmony_ci for (int z = 0; z < depth; z++) 952e5c31af7Sopenharmony_ci { 953e5c31af7Sopenharmony_ci for (int y = 0; y < height; y++) 954e5c31af7Sopenharmony_ci { 955e5c31af7Sopenharmony_ci for (int x = 0; x < width; x++) 956e5c31af7Sopenharmony_ci { 957e5c31af7Sopenharmony_ci if (use64Bits) 958e5c31af7Sopenharmony_ci { 959e5c31af7Sopenharmony_ci I64Vec4 refPix = reference.getPixelInt64(x, y, z); 960e5c31af7Sopenharmony_ci I64Vec4 cmpPix = result.getPixelInt64(x, y, z); 961e5c31af7Sopenharmony_ci diff = abs(refPix - cmpPix).cast<deUint64>(); 962e5c31af7Sopenharmony_ci } 963e5c31af7Sopenharmony_ci else 964e5c31af7Sopenharmony_ci { 965e5c31af7Sopenharmony_ci IVec4 refPix = reference.getPixelInt(x, y, z); 966e5c31af7Sopenharmony_ci IVec4 cmpPix = result.getPixelInt(x, y, z); 967e5c31af7Sopenharmony_ci diff = abs(refPix - cmpPix).cast<deUint64>(); 968e5c31af7Sopenharmony_ci } 969e5c31af7Sopenharmony_ci 970e5c31af7Sopenharmony_ci maxDiff = max(maxDiff, diff); 971e5c31af7Sopenharmony_ci 972e5c31af7Sopenharmony_ci const bool isOk = boolAll(lessThanEqual(diff, threshold64)); 973e5c31af7Sopenharmony_ci errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z); 974e5c31af7Sopenharmony_ci } 975e5c31af7Sopenharmony_ci } 976e5c31af7Sopenharmony_ci } 977e5c31af7Sopenharmony_ci 978e5c31af7Sopenharmony_ci bool compareOk = boolAll(lessThanEqual(maxDiff, threshold64)); 979e5c31af7Sopenharmony_ci 980e5c31af7Sopenharmony_ci if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 981e5c31af7Sopenharmony_ci { 982e5c31af7Sopenharmony_ci { 983e5c31af7Sopenharmony_ci const auto refChannelClass = tcu::getTextureChannelClass(reference.getFormat().type); 984e5c31af7Sopenharmony_ci const auto resChannelClass = tcu::getTextureChannelClass(result.getFormat().type); 985e5c31af7Sopenharmony_ci 986e5c31af7Sopenharmony_ci const bool refIsUint8 = (reference.getFormat().type == TextureFormat::UNSIGNED_INT8); 987e5c31af7Sopenharmony_ci const bool resIsUint8 = (result.getFormat().type == TextureFormat::UNSIGNED_INT8); 988e5c31af7Sopenharmony_ci 989e5c31af7Sopenharmony_ci const bool calcScaleBias = ((refChannelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT && !refIsUint8) || 990e5c31af7Sopenharmony_ci (resChannelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT && !resIsUint8)); 991e5c31af7Sopenharmony_ci 992e5c31af7Sopenharmony_ci // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 993e5c31af7Sopenharmony_ci if (calcScaleBias) 994e5c31af7Sopenharmony_ci { 995e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 996e5c31af7Sopenharmony_ci log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 997e5c31af7Sopenharmony_ci } 998e5c31af7Sopenharmony_ci } 999e5c31af7Sopenharmony_ci 1000e5c31af7Sopenharmony_ci if (!compareOk) 1001e5c31af7Sopenharmony_ci log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 1002e5c31af7Sopenharmony_ci 1003e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1004e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1005e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 1006e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 1007e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1008e5c31af7Sopenharmony_ci } 1009e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 1010e5c31af7Sopenharmony_ci { 1011e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1012e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 1013e5c31af7Sopenharmony_ci 1014e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1015e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1016e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1017e5c31af7Sopenharmony_ci } 1018e5c31af7Sopenharmony_ci 1019e5c31af7Sopenharmony_ci return compareOk; 1020e5c31af7Sopenharmony_ci} 1021e5c31af7Sopenharmony_ci 1022e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 1023e5c31af7Sopenharmony_ci * \brief Per-pixel depth/stencil threshold-based comparison 1024e5c31af7Sopenharmony_ci * 1025e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference 1026e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value. 1027e5c31af7Sopenharmony_ci * 1028e5c31af7Sopenharmony_ci * This comparison can be used for depth and depth/stencil images. 1029e5c31af7Sopenharmony_ci * Difference is computed in integer space. 1030e5c31af7Sopenharmony_ci * 1031e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 1032e5c31af7Sopenharmony_ci * are. 1033e5c31af7Sopenharmony_ci * 1034e5c31af7Sopenharmony_ci * \param log Test log for results 1035e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 1036e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 1037e5c31af7Sopenharmony_ci * \param reference Reference image 1038e5c31af7Sopenharmony_ci * \param result Result image 1039e5c31af7Sopenharmony_ci * \param threshold Maximum allowed depth difference (stencil must be exact) 1040e5c31af7Sopenharmony_ci * \param logMode Logging mode 1041e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 1042e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 1043e5c31af7Sopenharmony_cibool dsThresholdCompare(TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const float threshold, CompareLogMode logMode) 1044e5c31af7Sopenharmony_ci{ 1045e5c31af7Sopenharmony_ci int width = reference.getWidth(); 1046e5c31af7Sopenharmony_ci int height = reference.getHeight(); 1047e5c31af7Sopenharmony_ci int depth = reference.getDepth(); 1048e5c31af7Sopenharmony_ci TextureLevel errorMaskStorage(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 1049e5c31af7Sopenharmony_ci PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 1050e5c31af7Sopenharmony_ci float maxDiff = 0.0; 1051e5c31af7Sopenharmony_ci bool allStencilOk = true; 1052e5c31af7Sopenharmony_ci bool hasDepth = tcu::hasDepthComponent(result.getFormat().order); 1053e5c31af7Sopenharmony_ci bool hasStencil = tcu::hasStencilComponent(result.getFormat().order); 1054e5c31af7Sopenharmony_ci 1055e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 1056e5c31af7Sopenharmony_ci 1057e5c31af7Sopenharmony_ci for (int z = 0; z < depth; z++) 1058e5c31af7Sopenharmony_ci { 1059e5c31af7Sopenharmony_ci for (int y = 0; y < height; y++) 1060e5c31af7Sopenharmony_ci { 1061e5c31af7Sopenharmony_ci for (int x = 0; x < width; x++) 1062e5c31af7Sopenharmony_ci { 1063e5c31af7Sopenharmony_ci bool isOk = true; 1064e5c31af7Sopenharmony_ci 1065e5c31af7Sopenharmony_ci if (hasDepth) 1066e5c31af7Sopenharmony_ci { 1067e5c31af7Sopenharmony_ci float refDepth = reference.getPixDepth(x, y, z); 1068e5c31af7Sopenharmony_ci float cmpDepth = result.getPixDepth(x, y, z); 1069e5c31af7Sopenharmony_ci float diff = de::abs(refDepth - cmpDepth); 1070e5c31af7Sopenharmony_ci 1071e5c31af7Sopenharmony_ci isOk = diff <= threshold; 1072e5c31af7Sopenharmony_ci maxDiff = (float) deMax(maxDiff, diff); 1073e5c31af7Sopenharmony_ci } 1074e5c31af7Sopenharmony_ci 1075e5c31af7Sopenharmony_ci if (hasStencil) 1076e5c31af7Sopenharmony_ci { 1077e5c31af7Sopenharmony_ci deUint8 refStencil = (deUint8) reference.getPixStencil(x, y, z); 1078e5c31af7Sopenharmony_ci deUint8 cmpStencil = (deUint8) result.getPixStencil(x, y, z); 1079e5c31af7Sopenharmony_ci 1080e5c31af7Sopenharmony_ci bool isStencilOk = (refStencil == cmpStencil); 1081e5c31af7Sopenharmony_ci allStencilOk = allStencilOk && isStencilOk; 1082e5c31af7Sopenharmony_ci isOk = isOk && isStencilOk; 1083e5c31af7Sopenharmony_ci } 1084e5c31af7Sopenharmony_ci 1085e5c31af7Sopenharmony_ci errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z); 1086e5c31af7Sopenharmony_ci } 1087e5c31af7Sopenharmony_ci } 1088e5c31af7Sopenharmony_ci } 1089e5c31af7Sopenharmony_ci 1090e5c31af7Sopenharmony_ci bool compareOk = (maxDiff <= threshold) && allStencilOk; 1091e5c31af7Sopenharmony_ci 1092e5c31af7Sopenharmony_ci if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 1093e5c31af7Sopenharmony_ci { 1094e5c31af7Sopenharmony_ci if (!compareOk) 1095e5c31af7Sopenharmony_ci { 1096e5c31af7Sopenharmony_ci if (maxDiff > threshold) 1097e5c31af7Sopenharmony_ci log << TestLog::Message << "Depth comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 1098e5c31af7Sopenharmony_ci if (!allStencilOk) 1099e5c31af7Sopenharmony_ci log << TestLog::Message << "Stencil comparison failed" << TestLog::EndMessage; 1100e5c31af7Sopenharmony_ci } 1101e5c31af7Sopenharmony_ci 1102e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1103e5c31af7Sopenharmony_ci // TODO: Convert depth/stencil buffers into separate depth & stencil for logging? 1104e5c31af7Sopenharmony_ci// << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1105e5c31af7Sopenharmony_ci// << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 1106e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 1107e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1108e5c31af7Sopenharmony_ci } 1109e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 1110e5c31af7Sopenharmony_ci { 1111e5c31af7Sopenharmony_ci#if 0 1112e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1113e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 1114e5c31af7Sopenharmony_ci 1115e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1116e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1117e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1118e5c31af7Sopenharmony_ci#endif 1119e5c31af7Sopenharmony_ci } 1120e5c31af7Sopenharmony_ci 1121e5c31af7Sopenharmony_ci return compareOk; 1122e5c31af7Sopenharmony_ci} 1123e5c31af7Sopenharmony_ci 1124e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 1125e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based deviation-ignoring comparison 1126e5c31af7Sopenharmony_ci * 1127e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference 1128e5c31af7Sopenharmony_ci * image. Comparison fails if there is no pixel matching the given threshold 1129e5c31af7Sopenharmony_ci * value in the search volume. 1130e5c31af7Sopenharmony_ci * 1131e5c31af7Sopenharmony_ci * If the search volume contains out-of-bounds pixels, comparison can be set 1132e5c31af7Sopenharmony_ci * to either ignore these pixels in search or to accept any pixel that has 1133e5c31af7Sopenharmony_ci * out-of-bounds pixels in its search volume. 1134e5c31af7Sopenharmony_ci * 1135e5c31af7Sopenharmony_ci * This comparison can be used for integer- and fixed-point texture formats. 1136e5c31af7Sopenharmony_ci * Difference is computed in integer space. 1137e5c31af7Sopenharmony_ci * 1138e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 1139e5c31af7Sopenharmony_ci * are. 1140e5c31af7Sopenharmony_ci * 1141e5c31af7Sopenharmony_ci * \param log Test log for results 1142e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 1143e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 1144e5c31af7Sopenharmony_ci * \param reference Reference image 1145e5c31af7Sopenharmony_ci * \param result Result image 1146e5c31af7Sopenharmony_ci * \param threshold Maximum allowed difference 1147e5c31af7Sopenharmony_ci * \param maxPositionDeviation Maximum allowed distance in the search 1148e5c31af7Sopenharmony_ci * volume. 1149e5c31af7Sopenharmony_ci * \param acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region 1150e5c31af7Sopenharmony_ci * \param logMode Logging mode 1151e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 1152e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 1153e5c31af7Sopenharmony_cibool intThresholdPositionDeviationCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, const tcu::IVec3& maxPositionDeviation, bool acceptOutOfBoundsAsAnyValue, CompareLogMode logMode) 1154e5c31af7Sopenharmony_ci{ 1155e5c31af7Sopenharmony_ci const int width = reference.getWidth(); 1156e5c31af7Sopenharmony_ci const int height = reference.getHeight(); 1157e5c31af7Sopenharmony_ci const int depth = reference.getDepth(); 1158e5c31af7Sopenharmony_ci TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 1159e5c31af7Sopenharmony_ci PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 1160e5c31af7Sopenharmony_ci const int numFailingPixels = findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue); 1161e5c31af7Sopenharmony_ci const bool compareOk = numFailingPixels == 0; 1162e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 1163e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 1164e5c31af7Sopenharmony_ci 1165e5c31af7Sopenharmony_ci if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 1166e5c31af7Sopenharmony_ci { 1167e5c31af7Sopenharmony_ci // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 1168e5c31af7Sopenharmony_ci if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 1169e5c31af7Sopenharmony_ci tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 1170e5c31af7Sopenharmony_ci { 1171e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 1172e5c31af7Sopenharmony_ci log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 1173e5c31af7Sopenharmony_ci } 1174e5c31af7Sopenharmony_ci 1175e5c31af7Sopenharmony_ci if (!compareOk) 1176e5c31af7Sopenharmony_ci log << TestLog::Message 1177e5c31af7Sopenharmony_ci << "Image comparison failed:\n" 1178e5c31af7Sopenharmony_ci << "\tallowed position deviation = " << maxPositionDeviation << "\n" 1179e5c31af7Sopenharmony_ci << "\tcolor threshold = " << threshold 1180e5c31af7Sopenharmony_ci << TestLog::EndMessage; 1181e5c31af7Sopenharmony_ci 1182e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1183e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1184e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 1185e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 1186e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1187e5c31af7Sopenharmony_ci } 1188e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 1189e5c31af7Sopenharmony_ci { 1190e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1191e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 1192e5c31af7Sopenharmony_ci 1193e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1194e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1195e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1196e5c31af7Sopenharmony_ci } 1197e5c31af7Sopenharmony_ci 1198e5c31af7Sopenharmony_ci return compareOk; 1199e5c31af7Sopenharmony_ci} 1200e5c31af7Sopenharmony_ci 1201e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 1202e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based deviation-ignoring comparison 1203e5c31af7Sopenharmony_ci * 1204e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference 1205e5c31af7Sopenharmony_ci * image. Pixel fails the test if there is no pixel matching the given 1206e5c31af7Sopenharmony_ci * threshold value in the search volume. Comparison fails if the number of 1207e5c31af7Sopenharmony_ci * failing pixels exceeds the given limit. 1208e5c31af7Sopenharmony_ci * 1209e5c31af7Sopenharmony_ci * If the search volume contains out-of-bounds pixels, comparison can be set 1210e5c31af7Sopenharmony_ci * to either ignore these pixels in search or to accept any pixel that has 1211e5c31af7Sopenharmony_ci * out-of-bounds pixels in its search volume. 1212e5c31af7Sopenharmony_ci * 1213e5c31af7Sopenharmony_ci * This comparison can be used for integer- and fixed-point texture formats. 1214e5c31af7Sopenharmony_ci * Difference is computed in integer space. 1215e5c31af7Sopenharmony_ci * 1216e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 1217e5c31af7Sopenharmony_ci * are. 1218e5c31af7Sopenharmony_ci * 1219e5c31af7Sopenharmony_ci * \param log Test log for results 1220e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 1221e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 1222e5c31af7Sopenharmony_ci * \param reference Reference image 1223e5c31af7Sopenharmony_ci * \param result Result image 1224e5c31af7Sopenharmony_ci * \param threshold Maximum allowed difference 1225e5c31af7Sopenharmony_ci * \param maxPositionDeviation Maximum allowed distance in the search 1226e5c31af7Sopenharmony_ci * volume. 1227e5c31af7Sopenharmony_ci * \param acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region 1228e5c31af7Sopenharmony_ci * \param maxAllowedFailingPixels Maximum number of failing pixels 1229e5c31af7Sopenharmony_ci * \param logMode Logging mode 1230e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 1231e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 1232e5c31af7Sopenharmony_cibool intThresholdPositionDeviationErrorThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, const tcu::IVec3& maxPositionDeviation, bool acceptOutOfBoundsAsAnyValue, int maxAllowedFailingPixels, CompareLogMode logMode) 1233e5c31af7Sopenharmony_ci{ 1234e5c31af7Sopenharmony_ci const int width = reference.getWidth(); 1235e5c31af7Sopenharmony_ci const int height = reference.getHeight(); 1236e5c31af7Sopenharmony_ci const int depth = reference.getDepth(); 1237e5c31af7Sopenharmony_ci TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 1238e5c31af7Sopenharmony_ci PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 1239e5c31af7Sopenharmony_ci const int numFailingPixels = findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue); 1240e5c31af7Sopenharmony_ci const bool compareOk = numFailingPixels <= maxAllowedFailingPixels; 1241e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 1242e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 1243e5c31af7Sopenharmony_ci 1244e5c31af7Sopenharmony_ci if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 1245e5c31af7Sopenharmony_ci { 1246e5c31af7Sopenharmony_ci // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 1247e5c31af7Sopenharmony_ci if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 1248e5c31af7Sopenharmony_ci tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 1249e5c31af7Sopenharmony_ci { 1250e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 1251e5c31af7Sopenharmony_ci log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 1252e5c31af7Sopenharmony_ci } 1253e5c31af7Sopenharmony_ci 1254e5c31af7Sopenharmony_ci if (!compareOk) 1255e5c31af7Sopenharmony_ci log << TestLog::Message 1256e5c31af7Sopenharmony_ci << "Image comparison failed:\n" 1257e5c31af7Sopenharmony_ci << "\tallowed position deviation = " << maxPositionDeviation << "\n" 1258e5c31af7Sopenharmony_ci << "\tcolor threshold = " << threshold 1259e5c31af7Sopenharmony_ci << TestLog::EndMessage; 1260e5c31af7Sopenharmony_ci log << TestLog::Message << "Number of failing pixels = " << numFailingPixels << ", max allowed = " << maxAllowedFailingPixels << TestLog::EndMessage; 1261e5c31af7Sopenharmony_ci 1262e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1263e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1264e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 1265e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 1266e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1267e5c31af7Sopenharmony_ci } 1268e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 1269e5c31af7Sopenharmony_ci { 1270e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1271e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 1272e5c31af7Sopenharmony_ci 1273e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1274e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1275e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1276e5c31af7Sopenharmony_ci } 1277e5c31af7Sopenharmony_ci 1278e5c31af7Sopenharmony_ci return compareOk; 1279e5c31af7Sopenharmony_ci} 1280e5c31af7Sopenharmony_ci 1281e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 1282e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison 1283e5c31af7Sopenharmony_ci * 1284e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference 1285e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value. 1286e5c31af7Sopenharmony_ci * 1287e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 1288e5c31af7Sopenharmony_ci * are. 1289e5c31af7Sopenharmony_ci * 1290e5c31af7Sopenharmony_ci * \param log Test log for results 1291e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 1292e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 1293e5c31af7Sopenharmony_ci * \param reference Reference image 1294e5c31af7Sopenharmony_ci * \param result Result image 1295e5c31af7Sopenharmony_ci * \param threshold Maximum allowed difference 1296e5c31af7Sopenharmony_ci * \param logMode Logging mode 1297e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 1298e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 1299e5c31af7Sopenharmony_cibool pixelThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, const RGBA& threshold, CompareLogMode logMode) 1300e5c31af7Sopenharmony_ci{ 1301e5c31af7Sopenharmony_ci return intThresholdCompare(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold.toIVec().cast<deUint32>(), logMode); 1302e5c31af7Sopenharmony_ci} 1303e5c31af7Sopenharmony_ci 1304e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 1305e5c31af7Sopenharmony_ci * \brief Bilinear image comparison 1306e5c31af7Sopenharmony_ci * 1307e5c31af7Sopenharmony_ci * \todo [pyry] Describe 1308e5c31af7Sopenharmony_ci * 1309e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels 1310e5c31af7Sopenharmony_ci * are. 1311e5c31af7Sopenharmony_ci * 1312e5c31af7Sopenharmony_ci * \note Currently supports only RGBA, UNORM_INT8 formats 1313e5c31af7Sopenharmony_ci * \param log Test log for results 1314e5c31af7Sopenharmony_ci * \param imageSetName Name for image set when logging results 1315e5c31af7Sopenharmony_ci * \param imageSetDesc Description for image set 1316e5c31af7Sopenharmony_ci * \param reference Reference image 1317e5c31af7Sopenharmony_ci * \param result Result image 1318e5c31af7Sopenharmony_ci * \param threshold Maximum local difference 1319e5c31af7Sopenharmony_ci * \param logMode Logging mode 1320e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise 1321e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 1322e5c31af7Sopenharmony_cibool bilinearCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const RGBA threshold, CompareLogMode logMode) 1323e5c31af7Sopenharmony_ci{ 1324e5c31af7Sopenharmony_ci TextureLevel errorMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight()); 1325e5c31af7Sopenharmony_ci bool isOk = bilinearCompare(reference, result, errorMask, threshold); 1326e5c31af7Sopenharmony_ci Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 1327e5c31af7Sopenharmony_ci Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 1328e5c31af7Sopenharmony_ci 1329e5c31af7Sopenharmony_ci if (!isOk || logMode == COMPARE_LOG_EVERYTHING) 1330e5c31af7Sopenharmony_ci { 1331e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1332e5c31af7Sopenharmony_ci computeScaleAndBias(reference, result, pixelScale, pixelBias); 1333e5c31af7Sopenharmony_ci 1334e5c31af7Sopenharmony_ci if (!isOk) 1335e5c31af7Sopenharmony_ci log << TestLog::Message << "Image comparison failed, threshold = " << threshold << TestLog::EndMessage; 1336e5c31af7Sopenharmony_ci 1337e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1338e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1339e5c31af7Sopenharmony_ci << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 1340e5c31af7Sopenharmony_ci << TestLog::Image("ErrorMask", "Error mask", errorMask) 1341e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1342e5c31af7Sopenharmony_ci } 1343e5c31af7Sopenharmony_ci else if (logMode == COMPARE_LOG_RESULT) 1344e5c31af7Sopenharmony_ci { 1345e5c31af7Sopenharmony_ci if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1346e5c31af7Sopenharmony_ci computePixelScaleBias(result, pixelScale, pixelBias); 1347e5c31af7Sopenharmony_ci 1348e5c31af7Sopenharmony_ci log << TestLog::ImageSet(imageSetName, imageSetDesc) 1349e5c31af7Sopenharmony_ci << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1350e5c31af7Sopenharmony_ci << TestLog::EndImageSet; 1351e5c31af7Sopenharmony_ci } 1352e5c31af7Sopenharmony_ci 1353e5c31af7Sopenharmony_ci return isOk; 1354e5c31af7Sopenharmony_ci} 1355e5c31af7Sopenharmony_ci 1356e5c31af7Sopenharmony_ci} // tcu 1357