tcuImageCompare.cpp revision f385ac03b815baa98a5dff16b3b5c6398622c53d
1/*------------------------------------------------------------------------- 2 * drawElements Quality Program Tester Core 3 * ---------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Image comparison utilities. 22 *//*--------------------------------------------------------------------*/ 23 24#include "tcuImageCompare.hpp" 25#include "tcuSurface.hpp" 26#include "tcuFuzzyImageCompare.hpp" 27#include "tcuBilinearImageCompare.hpp" 28#include "tcuTestLog.hpp" 29#include "tcuVector.hpp" 30#include "tcuVectorUtil.hpp" 31#include "tcuRGBA.hpp" 32#include "tcuTexture.hpp" 33#include "tcuTextureUtil.hpp" 34#include "tcuFloat.hpp" 35 36#include <string.h> 37 38namespace tcu 39{ 40 41namespace 42{ 43 44void computeScaleAndBias (const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, tcu::Vec4& scale, tcu::Vec4& bias) 45{ 46 Vec4 minVal; 47 Vec4 maxVal; 48 const float eps = 0.0001f; 49 50 { 51 Vec4 refMin; 52 Vec4 refMax; 53 estimatePixelValueRange(reference, refMin, refMax); 54 55 minVal = refMin; 56 maxVal = refMax; 57 } 58 59 { 60 Vec4 resMin; 61 Vec4 resMax; 62 63 estimatePixelValueRange(result, resMin, resMax); 64 65 minVal[0] = de::min(minVal[0], resMin[0]); 66 minVal[1] = de::min(minVal[1], resMin[1]); 67 minVal[2] = de::min(minVal[2], resMin[2]); 68 minVal[3] = de::min(minVal[3], resMin[3]); 69 70 maxVal[0] = de::max(maxVal[0], resMax[0]); 71 maxVal[1] = de::max(maxVal[1], resMax[1]); 72 maxVal[2] = de::max(maxVal[2], resMax[2]); 73 maxVal[3] = de::max(maxVal[3], resMax[3]); 74 } 75 76 for (int c = 0; c < 4; c++) 77 { 78 if (maxVal[c] - minVal[c] < eps) 79 { 80 scale[c] = (maxVal[c] < eps) ? 1.0f : (1.0f / maxVal[c]); 81 bias[c] = (c == 3) ? (1.0f - maxVal[c]*scale[c]) : (0.0f - minVal[c]*scale[c]); 82 } 83 else 84 { 85 scale[c] = 1.0f / (maxVal[c] - minVal[c]); 86 bias[c] = 0.0f - minVal[c]*scale[c]; 87 } 88 } 89} 90 91static int findNumPositionDeviationFailingPixels (const PixelBufferAccess& errorMask, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, const tcu::IVec3& maxPositionDeviation, bool acceptOutOfBoundsAsAnyValue) 92{ 93 const tcu::IVec4 okColor (0, 255, 0, 255); 94 const tcu::IVec4 errorColor (255, 0, 0, 255); 95 const int width = reference.getWidth(); 96 const int height = reference.getHeight(); 97 const int depth = reference.getDepth(); 98 int numFailingPixels = 0; 99 100 // Accept pixels "sampling" over the image bounds pixels since "taps" could be anything 101 const int beginX = (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.x()) : (0); 102 const int beginY = (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.y()) : (0); 103 const int beginZ = (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.z()) : (0); 104 const int endX = (acceptOutOfBoundsAsAnyValue) ? (width - maxPositionDeviation.x()) : (0); 105 const int endY = (acceptOutOfBoundsAsAnyValue) ? (height - maxPositionDeviation.y()) : (0); 106 const int endZ = (acceptOutOfBoundsAsAnyValue) ? (depth - maxPositionDeviation.z()) : (0); 107 108 TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 109 110 tcu::clear(errorMask, okColor); 111 112 for (int z = beginZ; z < endZ; z++) 113 { 114 for (int y = beginY; y < endY; y++) 115 { 116 for (int x = beginX; x < endX; x++) 117 { 118 const IVec4 refPix = reference.getPixelInt(x, y, z); 119 const IVec4 cmpPix = result.getPixelInt(x, y, z); 120 121 // Exact match 122 { 123 const UVec4 diff = abs(refPix - cmpPix).cast<deUint32>(); 124 const bool isOk = boolAll(lessThanEqual(diff, threshold)); 125 126 if (isOk) 127 continue; 128 } 129 130 // Find matching pixels for both result and reference pixel 131 132 { 133 bool pixelFoundForReference = false; 134 135 // Find deviated result pixel for reference 136 137 for (int sz = de::max(0, z - maxPositionDeviation.z()); sz <= de::min(depth - 1, z + maxPositionDeviation.z()) && !pixelFoundForReference; ++sz) 138 for (int sy = de::max(0, y - maxPositionDeviation.y()); sy <= de::min(height - 1, y + maxPositionDeviation.y()) && !pixelFoundForReference; ++sy) 139 for (int sx = de::max(0, x - maxPositionDeviation.x()); sx <= de::min(width - 1, x + maxPositionDeviation.x()) && !pixelFoundForReference; ++sx) 140 { 141 const IVec4 deviatedCmpPix = result.getPixelInt(sx, sy, sz); 142 const UVec4 diff = abs(refPix - deviatedCmpPix).cast<deUint32>(); 143 const bool isOk = boolAll(lessThanEqual(diff, threshold)); 144 145 pixelFoundForReference = isOk; 146 } 147 148 if (!pixelFoundForReference) 149 { 150 errorMask.setPixel(errorColor, x, y, z); 151 ++numFailingPixels; 152 continue; 153 } 154 } 155 { 156 bool pixelFoundForResult = false; 157 158 // Find deviated reference pixel for result 159 160 for (int sz = de::max(0, z - maxPositionDeviation.z()); sz <= de::min(depth - 1, z + maxPositionDeviation.z()) && !pixelFoundForResult; ++sz) 161 for (int sy = de::max(0, y - maxPositionDeviation.y()); sy <= de::min(height - 1, y + maxPositionDeviation.y()) && !pixelFoundForResult; ++sy) 162 for (int sx = de::max(0, x - maxPositionDeviation.x()); sx <= de::min(width - 1, x + maxPositionDeviation.x()) && !pixelFoundForResult; ++sx) 163 { 164 const IVec4 deviatedRefPix = reference.getPixelInt(sx, sy, sz); 165 const UVec4 diff = abs(cmpPix - deviatedRefPix).cast<deUint32>(); 166 const bool isOk = boolAll(lessThanEqual(diff, threshold)); 167 168 pixelFoundForResult = isOk; 169 } 170 171 if (!pixelFoundForResult) 172 { 173 errorMask.setPixel(errorColor, x, y, z); 174 ++numFailingPixels; 175 continue; 176 } 177 } 178 } 179 } 180 } 181 182 return numFailingPixels; 183} 184 185} // anonymous 186 187/*--------------------------------------------------------------------*//*! 188 * \brief Fuzzy image comparison 189 * 190 * This image comparison is designed for comparing images rendered by 3D 191 * graphics APIs such as OpenGL. The comparison allows small local differences 192 * and compensates for aliasing. 193 * 194 * The algorithm first performs light blurring on both images and then 195 * does per-pixel analysis. Pixels are compared to 3x3 bilinear surface 196 * defined by adjecent pixels. This compensates for both 1-pixel deviations 197 * in geometry and aliasing in texture data. 198 * 199 * Error metric is computed based on the differences. On valid images the 200 * metric is usually <0.01. Thus good threshold values are in range 0.02 to 201 * 0.05. 202 * 203 * On failure error image is generated that shows where the failing pixels 204 * are. 205 * 206 * \note Currently supports only UNORM_INT8 formats 207 * \param log Test log for results 208 * \param imageSetName Name for image set when logging results 209 * \param imageSetDesc Description for image set 210 * \param reference Reference image 211 * \param result Result image 212 * \param threshold Error metric threshold (good values are 0.02-0.05) 213 * \param logMode Logging mode 214 * \return true if comparison passes, false otherwise 215 *//*--------------------------------------------------------------------*/ 216bool fuzzyCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, float threshold, CompareLogMode logMode) 217{ 218 FuzzyCompareParams params; // Use defaults. 219 TextureLevel errorMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight()); 220 float difference = fuzzyCompare(params, reference, result, errorMask.getAccess()); 221 bool isOk = difference <= threshold; 222 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 223 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 224 225 if (!isOk || logMode == COMPARE_LOG_EVERYTHING) 226 { 227 // Generate more accurate error mask. 228 params.maxSampleSkip = 0; 229 fuzzyCompare(params, reference, result, errorMask.getAccess()); 230 231 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 232 computeScaleAndBias(reference, result, pixelScale, pixelBias); 233 234 if (!isOk) 235 log << TestLog::Message << "Image comparison failed: difference = " << difference << ", threshold = " << threshold << TestLog::EndMessage; 236 237 log << TestLog::ImageSet(imageSetName, imageSetDesc) 238 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 239 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 240 << TestLog::Image("ErrorMask", "Error mask", errorMask) 241 << TestLog::EndImageSet; 242 } 243 else if (logMode == COMPARE_LOG_RESULT) 244 { 245 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 246 computePixelScaleBias(result, pixelScale, pixelBias); 247 248 log << TestLog::ImageSet(imageSetName, imageSetDesc) 249 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 250 << TestLog::EndImageSet; 251 } 252 253 return isOk; 254} 255 256/*--------------------------------------------------------------------*//*! 257 * \brief Fuzzy image comparison 258 * 259 * This image comparison is designed for comparing images rendered by 3D 260 * graphics APIs such as OpenGL. The comparison allows small local differences 261 * and compensates for aliasing. 262 * 263 * The algorithm first performs light blurring on both images and then 264 * does per-pixel analysis. Pixels are compared to 3x3 bilinear surface 265 * defined by adjecent pixels. This compensates for both 1-pixel deviations 266 * in geometry and aliasing in texture data. 267 * 268 * Error metric is computed based on the differences. On valid images the 269 * metric is usually <0.01. Thus good threshold values are in range 0.02 to 270 * 0.05. 271 * 272 * On failure error image is generated that shows where the failing pixels 273 * are. 274 * 275 * \note Currently supports only UNORM_INT8 formats 276 * \param log Test log for results 277 * \param imageSetName Name for image set when logging results 278 * \param imageSetDesc Description for image set 279 * \param reference Reference image 280 * \param result Result image 281 * \param threshold Error metric threshold (good values are 0.02-0.05) 282 * \param logMode Logging mode 283 * \return true if comparison passes, false otherwise 284 *//*--------------------------------------------------------------------*/ 285bool fuzzyCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, float threshold, CompareLogMode logMode) 286{ 287 return fuzzyCompare(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold, logMode); 288} 289 290static deInt64 computeSquaredDiffSum (const ConstPixelBufferAccess& ref, const ConstPixelBufferAccess& cmp, const PixelBufferAccess& diffMask, int diffFactor) 291{ 292 TCU_CHECK_INTERNAL(ref.getFormat().type == TextureFormat::UNORM_INT8 && cmp.getFormat().type == TextureFormat::UNORM_INT8); 293 DE_ASSERT(ref.getWidth() == cmp.getWidth() && ref.getWidth() == diffMask.getWidth()); 294 DE_ASSERT(ref.getHeight() == cmp.getHeight() && ref.getHeight() == diffMask.getHeight()); 295 296 deInt64 diffSum = 0; 297 298 for (int y = 0; y < cmp.getHeight(); y++) 299 { 300 for (int x = 0; x < cmp.getWidth(); x++) 301 { 302 IVec4 a = ref.getPixelInt(x, y); 303 IVec4 b = cmp.getPixelInt(x, y); 304 IVec4 diff = abs(a - b); 305 int sum = diff.x() + diff.y() + diff.z() + diff.w(); 306 int sqSum = diff.x()*diff.x() + diff.y()*diff.y() + diff.z()*diff.z() + diff.w()*diff.w(); 307 308 diffMask.setPixel(tcu::RGBA(deClamp32(sum*diffFactor, 0, 255), deClamp32(255-sum*diffFactor, 0, 255), 0, 255).toVec(), x, y); 309 310 diffSum += (deInt64)sqSum; 311 } 312 } 313 314 return diffSum; 315} 316 317/*--------------------------------------------------------------------*//*! 318 * \brief Per-pixel difference accuracy metric 319 * 320 * Computes accuracy metric using per-pixel differences between reference 321 * and result images. 322 * 323 * \note Supports only integer- and fixed-point formats 324 * \param log Test log for results 325 * \param imageSetName Name for image set when logging results 326 * \param imageSetDesc Description for image set 327 * \param reference Reference image 328 * \param result Result image 329 * \param bestScoreDiff Scaling factor 330 * \param worstScoreDiff Scaling factor 331 * \param logMode Logging mode 332 * \return true if comparison passes, false otherwise 333 *//*--------------------------------------------------------------------*/ 334int measurePixelDiffAccuracy (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, int bestScoreDiff, int worstScoreDiff, CompareLogMode logMode) 335{ 336 TextureLevel diffMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight()); 337 int diffFactor = 8; 338 deInt64 squaredSum = computeSquaredDiffSum(reference, result, diffMask.getAccess(), diffFactor); 339 float sum = deFloatSqrt((float)squaredSum); 340 int score = deClamp32(deFloorFloatToInt32(100.0f - (de::max(sum-(float)bestScoreDiff, 0.0f) / (float)(worstScoreDiff-bestScoreDiff))*100.0f), 0, 100); 341 const int failThreshold = 10; 342 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 343 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 344 345 if (logMode == COMPARE_LOG_EVERYTHING || score <= failThreshold) 346 { 347 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 348 computeScaleAndBias(reference, result, pixelScale, pixelBias); 349 350 log << TestLog::ImageSet(imageSetName, imageSetDesc) 351 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 352 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 353 << TestLog::Image("DiffMask", "Difference", diffMask) 354 << TestLog::EndImageSet; 355 } 356 else if (logMode == COMPARE_LOG_RESULT) 357 { 358 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 359 computePixelScaleBias(result, pixelScale, pixelBias); 360 361 log << TestLog::ImageSet(imageSetName, imageSetDesc) 362 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 363 << TestLog::EndImageSet; 364 } 365 366 if (logMode != COMPARE_LOG_ON_ERROR || score <= failThreshold) 367 log << TestLog::Integer("DiffSum", "Squared difference sum", "", QP_KEY_TAG_NONE, squaredSum) 368 << TestLog::Integer("Score", "Score", "", QP_KEY_TAG_QUALITY, score); 369 370 return score; 371} 372 373/*--------------------------------------------------------------------*//*! 374 * \brief Per-pixel difference accuracy metric 375 * 376 * Computes accuracy metric using per-pixel differences between reference 377 * and result images. 378 * 379 * \note Supports only integer- and fixed-point formats 380 * \param log Test log for results 381 * \param imageSetName Name for image set when logging results 382 * \param imageSetDesc Description for image set 383 * \param reference Reference image 384 * \param result Result image 385 * \param bestScoreDiff Scaling factor 386 * \param worstScoreDiff Scaling factor 387 * \param logMode Logging mode 388 * \return true if comparison passes, false otherwise 389 *//*--------------------------------------------------------------------*/ 390int measurePixelDiffAccuracy (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, int bestScoreDiff, int worstScoreDiff, CompareLogMode logMode) 391{ 392 return measurePixelDiffAccuracy(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), bestScoreDiff, worstScoreDiff, logMode); 393} 394 395/*--------------------------------------------------------------------*//*! 396 * Returns the index of float in a float space without denormals 397 * so that: 398 * 1) f(0.0) = 0 399 * 2) f(-0.0) = 0 400 * 3) f(b) = f(a) + 1 <==> b = nextAfter(a) 401 * 402 * See computeFloatFlushRelaxedULPDiff for details 403 *//*--------------------------------------------------------------------*/ 404static deInt32 getPositionOfIEEEFloatWithoutDenormals (float x) 405{ 406 DE_ASSERT(!deIsNaN(x)); // not sane 407 408 if (x == 0.0f) 409 return 0; 410 else if (x < 0.0f) 411 return -getPositionOfIEEEFloatWithoutDenormals(-x); 412 else 413 { 414 DE_ASSERT(x > 0.0f); 415 416 const tcu::Float32 f(x); 417 418 if (f.isDenorm()) 419 { 420 // Denorms are flushed to zero 421 return 0; 422 } 423 else 424 { 425 // sign is 0, and it's a normal number. Natural position is its bit 426 // pattern but since we've collapsed the denorms, we must remove 427 // the gap here too to keep the float enumeration continuous. 428 // 429 // Denormals occupy one exponent pattern. Removing one from 430 // exponent should to the trick. 431 return (deInt32)(f.bits() - (1u << 23u)); 432 } 433 } 434} 435 436static deUint32 computeFloatFlushRelaxedULPDiff (float a, float b) 437{ 438 if (deIsNaN(a) && deIsNaN(b)) 439 return 0; 440 else if (deIsNaN(a) || deIsNaN(b)) 441 { 442 return 0xFFFFFFFFu; 443 } 444 else 445 { 446 // Using the "definition 5" in Muller, Jean-Michel. "On the definition of ulp (x)" (2005) 447 // assuming a floating point space is IEEE single precision floating point space without 448 // denormals (and signed zeros). 449 const deInt32 aIndex = getPositionOfIEEEFloatWithoutDenormals(a); 450 const deInt32 bIndex = getPositionOfIEEEFloatWithoutDenormals(b); 451 return (deUint32)de::abs(aIndex - bIndex); 452 } 453} 454 455static tcu::UVec4 computeFlushRelaxedULPDiff (const tcu::Vec4& a, const tcu::Vec4& b) 456{ 457 return tcu::UVec4(computeFloatFlushRelaxedULPDiff(a.x(), b.x()), 458 computeFloatFlushRelaxedULPDiff(a.y(), b.y()), 459 computeFloatFlushRelaxedULPDiff(a.z(), b.z()), 460 computeFloatFlushRelaxedULPDiff(a.w(), b.w())); 461} 462 463/*--------------------------------------------------------------------*//*! 464 * \brief Per-pixel threshold-based comparison 465 * 466 * This compare computes per-pixel differences between result and reference 467 * image. Comparison fails if any pixels exceed the given threshold value. 468 * 469 * This comparison uses ULP (units in last place) metric for computing the 470 * difference between floating-point values and thus this function can 471 * be used only for comparing floating-point texture data. In ULP calculation 472 * the denormal numbers are allowed to be flushed to zero. 473 * 474 * On failure error image is generated that shows where the failing pixels 475 * are. 476 * 477 * \param log Test log for results 478 * \param imageSetName Name for image set when logging results 479 * \param imageSetDesc Description for image set 480 * \param reference Reference image 481 * \param result Result image 482 * \param threshold Maximum allowed difference 483 * \param logMode Logging mode 484 * \return true if comparison passes, false otherwise 485 *//*--------------------------------------------------------------------*/ 486bool floatUlpThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode) 487{ 488 int width = reference.getWidth(); 489 int height = reference.getHeight(); 490 int depth = reference.getDepth(); 491 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 492 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 493 UVec4 maxDiff (0, 0, 0, 0); 494 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 495 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 496 497 TCU_CHECK(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 498 499 for (int z = 0; z < depth; z++) 500 { 501 for (int y = 0; y < height; y++) 502 { 503 for (int x = 0; x < width; x++) 504 { 505 const Vec4 refPix = reference.getPixel(x, y, z); 506 const Vec4 cmpPix = result.getPixel(x, y, z); 507 const UVec4 diff = computeFlushRelaxedULPDiff(refPix, cmpPix); 508 const bool isOk = boolAll(lessThanEqual(diff, threshold)); 509 510 maxDiff = max(maxDiff, diff); 511 512 errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 513 } 514 } 515 } 516 517 bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 518 519 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 520 { 521 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 522 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 523 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 524 { 525 computeScaleAndBias(reference, result, pixelScale, pixelBias); 526 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 527 } 528 529 if (!compareOk) 530 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 531 532 log << TestLog::ImageSet(imageSetName, imageSetDesc) 533 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 534 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 535 << TestLog::Image("ErrorMask", "Error mask", errorMask) 536 << TestLog::EndImageSet; 537 } 538 else if (logMode == COMPARE_LOG_RESULT) 539 { 540 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 541 computePixelScaleBias(result, pixelScale, pixelBias); 542 543 log << TestLog::ImageSet(imageSetName, imageSetDesc) 544 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 545 << TestLog::EndImageSet; 546 } 547 548 return compareOk; 549} 550 551/*--------------------------------------------------------------------*//*! 552 * \brief Per-pixel threshold-based comparison 553 * 554 * This compare computes per-pixel differences between result and reference 555 * image. Comparison fails if any pixels exceed the given threshold value. 556 * 557 * This comparison can be used for floating-point and fixed-point formats. 558 * Difference is computed in floating-point space. 559 * 560 * On failure an error image is generated that shows where the failing 561 * pixels are. 562 * 563 * \param log Test log for results 564 * \param imageSetName Name for image set when logging results 565 * \param imageSetDesc Description for image set 566 * \param reference Reference image 567 * \param result Result image 568 * \param threshold Maximum allowed difference 569 * \param logMode Logging mode 570 * \return true if comparison passes, false otherwise 571 *//*--------------------------------------------------------------------*/ 572bool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode) 573{ 574 int width = reference.getWidth(); 575 int height = reference.getHeight(); 576 int depth = reference.getDepth(); 577 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 578 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 579 Vec4 maxDiff (0.0f, 0.0f, 0.0f, 0.0f); 580 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 581 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 582 583 TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 584 585 for (int z = 0; z < depth; z++) 586 { 587 for (int y = 0; y < height; y++) 588 { 589 for (int x = 0; x < width; x++) 590 { 591 Vec4 refPix = reference.getPixel(x, y, z); 592 Vec4 cmpPix = result.getPixel(x, y, z); 593 594 Vec4 diff = abs(refPix - cmpPix); 595 bool isOk = boolAll(lessThanEqual(diff, threshold)); 596 597 maxDiff = max(maxDiff, diff); 598 599 errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 600 } 601 } 602 } 603 604 bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 605 606 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 607 { 608 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 609 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 610 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 611 { 612 computeScaleAndBias(reference, result, pixelScale, pixelBias); 613 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 614 } 615 616 if (!compareOk) 617 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 618 619 log << TestLog::ImageSet(imageSetName, imageSetDesc) 620 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 621 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 622 << TestLog::Image("ErrorMask", "Error mask", errorMask) 623 << TestLog::EndImageSet; 624 } 625 else if (logMode == COMPARE_LOG_RESULT) 626 { 627 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 628 computePixelScaleBias(result, pixelScale, pixelBias); 629 630 log << TestLog::ImageSet(imageSetName, imageSetDesc) 631 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 632 << TestLog::EndImageSet; 633 } 634 635 return compareOk; 636} 637 638/*--------------------------------------------------------------------*//*! 639 * \brief Per-pixel threshold-based comparison 640 * 641 * This compare computes per-pixel differences between result and reference 642 * color. Comparison fails if any pixels exceed the given threshold value. 643 * 644 * This comparison can be used for floating-point and fixed-point formats. 645 * Difference is computed in floating-point space. 646 * 647 * On failure an error image is generated that shows where the failing 648 * pixels are. 649 * 650 * \param log Test log for results 651 * \param imageSetName Name for image set when logging results 652 * \param imageSetDesc Description for image set 653 * \param reference Reference color 654 * \param result Result image 655 * \param threshold Maximum allowed difference 656 * \param logMode Logging mode 657 * \return true if comparison passes, false otherwise 658 *//*--------------------------------------------------------------------*/ 659bool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Vec4& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode) 660{ 661 const int width = result.getWidth(); 662 const int height = result.getHeight(); 663 const int depth = result.getDepth(); 664 665 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 666 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 667 Vec4 maxDiff (0.0f, 0.0f, 0.0f, 0.0f); 668 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 669 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 670 671 for (int z = 0; z < depth; z++) 672 { 673 for (int y = 0; y < height; y++) 674 { 675 for (int x = 0; x < width; x++) 676 { 677 const Vec4 cmpPix = result.getPixel(x, y, z); 678 const Vec4 diff = abs(reference - cmpPix); 679 const bool isOk = boolAll(lessThanEqual(diff, threshold)); 680 681 maxDiff = max(maxDiff, diff); 682 683 errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 684 } 685 } 686 } 687 688 bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 689 690 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 691 { 692 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 693 if (tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 694 { 695 computeScaleAndBias(result, result, pixelScale, pixelBias); 696 log << TestLog::Message << "Result image is normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 697 } 698 699 if (!compareOk) 700 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << ", reference = " << reference << TestLog::EndMessage; 701 702 log << TestLog::ImageSet(imageSetName, imageSetDesc) 703 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 704 << TestLog::Image("ErrorMask", "Error mask", errorMask) 705 << TestLog::EndImageSet; 706 } 707 else if (logMode == COMPARE_LOG_RESULT) 708 { 709 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 710 computePixelScaleBias(result, pixelScale, pixelBias); 711 712 log << TestLog::ImageSet(imageSetName, imageSetDesc) 713 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 714 << TestLog::EndImageSet; 715 } 716 717 return compareOk; 718} 719 720/*--------------------------------------------------------------------*//*! 721 * \brief Per-pixel threshold-based comparison 722 * 723 * This compare computes per-pixel differences between result and reference 724 * image. Comparison fails if any pixels exceed the given threshold value. 725 * 726 * This comparison can be used for integer- and fixed-point texture formats. 727 * Difference is computed in integer space. 728 * 729 * On failure error image is generated that shows where the failing pixels 730 * are. 731 * 732 * \param log Test log for results 733 * \param imageSetName Name for image set when logging results 734 * \param imageSetDesc Description for image set 735 * \param reference Reference image 736 * \param result Result image 737 * \param threshold Maximum allowed difference 738 * \param logMode Logging mode 739 * \return true if comparison passes, false otherwise 740 *//*--------------------------------------------------------------------*/ 741bool intThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode) 742{ 743 int width = reference.getWidth(); 744 int height = reference.getHeight(); 745 int depth = reference.getDepth(); 746 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 747 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 748 UVec4 maxDiff (0, 0, 0, 0); 749 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 750 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 751 752 TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 753 754 for (int z = 0; z < depth; z++) 755 { 756 for (int y = 0; y < height; y++) 757 { 758 for (int x = 0; x < width; x++) 759 { 760 IVec4 refPix = reference.getPixelInt(x, y, z); 761 IVec4 cmpPix = result.getPixelInt(x, y, z); 762 763 UVec4 diff = abs(refPix - cmpPix).cast<deUint32>(); 764 bool isOk = boolAll(lessThanEqual(diff, threshold)); 765 766 maxDiff = max(maxDiff, diff); 767 768 errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z); 769 } 770 } 771 } 772 773 bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 774 775 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 776 { 777 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 778 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 779 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 780 { 781 computeScaleAndBias(reference, result, pixelScale, pixelBias); 782 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 783 } 784 785 if (!compareOk) 786 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 787 788 log << TestLog::ImageSet(imageSetName, imageSetDesc) 789 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 790 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 791 << TestLog::Image("ErrorMask", "Error mask", errorMask) 792 << TestLog::EndImageSet; 793 } 794 else if (logMode == COMPARE_LOG_RESULT) 795 { 796 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 797 computePixelScaleBias(result, pixelScale, pixelBias); 798 799 log << TestLog::ImageSet(imageSetName, imageSetDesc) 800 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 801 << TestLog::EndImageSet; 802 } 803 804 return compareOk; 805} 806 807/*--------------------------------------------------------------------*//*! 808 * \brief Per-pixel threshold-based deviation-ignoring comparison 809 * 810 * This compare computes per-pixel differences between result and reference 811 * image. Comparison fails if there is no pixel matching the given threshold 812 * value in the search volume. 813 * 814 * If the search volume contains out-of-bounds pixels, comparison can be set 815 * to either ignore these pixels in search or to accept any pixel that has 816 * out-of-bounds pixels in its search volume. 817 * 818 * This comparison can be used for integer- and fixed-point texture formats. 819 * Difference is computed in integer space. 820 * 821 * On failure error image is generated that shows where the failing pixels 822 * are. 823 * 824 * \param log Test log for results 825 * \param imageSetName Name for image set when logging results 826 * \param imageSetDesc Description for image set 827 * \param reference Reference image 828 * \param result Result image 829 * \param threshold Maximum allowed difference 830 * \param maxPositionDeviation Maximum allowed distance in the search 831 * volume. 832 * \param acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region 833 * \param logMode Logging mode 834 * \return true if comparison passes, false otherwise 835 *//*--------------------------------------------------------------------*/ 836bool 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) 837{ 838 const int width = reference.getWidth(); 839 const int height = reference.getHeight(); 840 const int depth = reference.getDepth(); 841 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 842 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 843 const int numFailingPixels = findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue); 844 const bool compareOk = numFailingPixels == 0; 845 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 846 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 847 848 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 849 { 850 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 851 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 852 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 853 { 854 computeScaleAndBias(reference, result, pixelScale, pixelBias); 855 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 856 } 857 858 if (!compareOk) 859 log << TestLog::Message 860 << "Image comparison failed:\n" 861 << "\tallowed position deviation = " << maxPositionDeviation << "\n" 862 << "\tcolor threshold = " << threshold 863 << TestLog::EndMessage; 864 865 log << TestLog::ImageSet(imageSetName, imageSetDesc) 866 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 867 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 868 << TestLog::Image("ErrorMask", "Error mask", errorMask) 869 << TestLog::EndImageSet; 870 } 871 else if (logMode == COMPARE_LOG_RESULT) 872 { 873 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 874 computePixelScaleBias(result, pixelScale, pixelBias); 875 876 log << TestLog::ImageSet(imageSetName, imageSetDesc) 877 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 878 << TestLog::EndImageSet; 879 } 880 881 return compareOk; 882} 883 884/*--------------------------------------------------------------------*//*! 885 * \brief Per-pixel threshold-based deviation-ignoring comparison 886 * 887 * This compare computes per-pixel differences between result and reference 888 * image. Pixel fails the test if there is no pixel matching the given 889 * threshold value in the search volume. Comparison fails if the number of 890 * failing pixels exceeds the given limit. 891 * 892 * If the search volume contains out-of-bounds pixels, comparison can be set 893 * to either ignore these pixels in search or to accept any pixel that has 894 * out-of-bounds pixels in its search volume. 895 * 896 * This comparison can be used for integer- and fixed-point texture formats. 897 * Difference is computed in integer space. 898 * 899 * On failure error image is generated that shows where the failing pixels 900 * are. 901 * 902 * \param log Test log for results 903 * \param imageSetName Name for image set when logging results 904 * \param imageSetDesc Description for image set 905 * \param reference Reference image 906 * \param result Result image 907 * \param threshold Maximum allowed difference 908 * \param maxPositionDeviation Maximum allowed distance in the search 909 * volume. 910 * \param acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region 911 * \param maxAllowedFailingPixels Maximum number of failing pixels 912 * \param logMode Logging mode 913 * \return true if comparison passes, false otherwise 914 *//*--------------------------------------------------------------------*/ 915bool 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) 916{ 917 const int width = reference.getWidth(); 918 const int height = reference.getHeight(); 919 const int depth = reference.getDepth(); 920 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 921 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 922 const int numFailingPixels = findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue); 923 const bool compareOk = numFailingPixels <= maxAllowedFailingPixels; 924 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 925 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 926 927 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 928 { 929 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 930 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 931 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 932 { 933 computeScaleAndBias(reference, result, pixelScale, pixelBias); 934 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 935 } 936 937 if (!compareOk) 938 log << TestLog::Message 939 << "Image comparison failed:\n" 940 << "\tallowed position deviation = " << maxPositionDeviation << "\n" 941 << "\tcolor threshold = " << threshold 942 << TestLog::EndMessage; 943 log << TestLog::Message << "Number of failing pixels = " << numFailingPixels << ", max allowed = " << maxAllowedFailingPixels << TestLog::EndMessage; 944 945 log << TestLog::ImageSet(imageSetName, imageSetDesc) 946 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 947 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 948 << TestLog::Image("ErrorMask", "Error mask", errorMask) 949 << TestLog::EndImageSet; 950 } 951 else if (logMode == COMPARE_LOG_RESULT) 952 { 953 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 954 computePixelScaleBias(result, pixelScale, pixelBias); 955 956 log << TestLog::ImageSet(imageSetName, imageSetDesc) 957 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 958 << TestLog::EndImageSet; 959 } 960 961 return compareOk; 962} 963 964/*--------------------------------------------------------------------*//*! 965 * \brief Per-pixel threshold-based comparison 966 * 967 * This compare computes per-pixel differences between result and reference 968 * image. Comparison fails if any pixels exceed the given threshold value. 969 * 970 * On failure error image is generated that shows where the failing pixels 971 * are. 972 * 973 * \param log Test log for results 974 * \param imageSetName Name for image set when logging results 975 * \param imageSetDesc Description for image set 976 * \param reference Reference image 977 * \param result Result image 978 * \param threshold Maximum allowed difference 979 * \param logMode Logging mode 980 * \return true if comparison passes, false otherwise 981 *//*--------------------------------------------------------------------*/ 982bool pixelThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, const RGBA& threshold, CompareLogMode logMode) 983{ 984 return intThresholdCompare(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold.toIVec().cast<deUint32>(), logMode); 985} 986 987/*--------------------------------------------------------------------*//*! 988 * \brief Bilinear image comparison 989 * 990 * \todo [pyry] Describe 991 * 992 * On failure error image is generated that shows where the failing pixels 993 * are. 994 * 995 * \note Currently supports only RGBA, UNORM_INT8 formats 996 * \param log Test log for results 997 * \param imageSetName Name for image set when logging results 998 * \param imageSetDesc Description for image set 999 * \param reference Reference image 1000 * \param result Result image 1001 * \param threshold Maximum local difference 1002 * \param logMode Logging mode 1003 * \return true if comparison passes, false otherwise 1004 *//*--------------------------------------------------------------------*/ 1005bool bilinearCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const RGBA threshold, CompareLogMode logMode) 1006{ 1007 TextureLevel errorMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight()); 1008 bool isOk = bilinearCompare(reference, result, errorMask, threshold); 1009 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 1010 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 1011 1012 if (!isOk || logMode == COMPARE_LOG_EVERYTHING) 1013 { 1014 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1015 computeScaleAndBias(reference, result, pixelScale, pixelBias); 1016 1017 if (!isOk) 1018 log << TestLog::Message << "Image comparison failed, threshold = " << threshold << TestLog::EndMessage; 1019 1020 log << TestLog::ImageSet(imageSetName, imageSetDesc) 1021 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1022 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 1023 << TestLog::Image("ErrorMask", "Error mask", errorMask) 1024 << TestLog::EndImageSet; 1025 } 1026 else if (logMode == COMPARE_LOG_RESULT) 1027 { 1028 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1029 computePixelScaleBias(result, pixelScale, pixelBias); 1030 1031 log << TestLog::ImageSet(imageSetName, imageSetDesc) 1032 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1033 << TestLog::EndImageSet; 1034 } 1035 1036 return isOk; 1037} 1038 1039} // tcu 1040