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()) : (width); 105 const int endY = (acceptOutOfBoundsAsAnyValue) ? (height - maxPositionDeviation.y()) : (height); 106 const int endZ = (acceptOutOfBoundsAsAnyValue) ? (depth - maxPositionDeviation.z()) : (depth); 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. Add one since the removed range 431 // contained one representable value, 0. 432 return (deInt32)(f.bits() - (1u << 23u) + 1u); 433 } 434 } 435} 436 437static deUint32 computeFloatFlushRelaxedULPDiff (float a, float b) 438{ 439 if (deIsNaN(a) && deIsNaN(b)) 440 return 0; 441 else if (deIsNaN(a) || deIsNaN(b)) 442 { 443 return 0xFFFFFFFFu; 444 } 445 else 446 { 447 // Using the "definition 5" in Muller, Jean-Michel. "On the definition of ulp (x)" (2005) 448 // assuming a floating point space is IEEE single precision floating point space without 449 // denormals (and signed zeros). 450 const deInt32 aIndex = getPositionOfIEEEFloatWithoutDenormals(a); 451 const deInt32 bIndex = getPositionOfIEEEFloatWithoutDenormals(b); 452 return (deUint32)de::abs(aIndex - bIndex); 453 } 454} 455 456static tcu::UVec4 computeFlushRelaxedULPDiff (const tcu::Vec4& a, const tcu::Vec4& b) 457{ 458 return tcu::UVec4(computeFloatFlushRelaxedULPDiff(a.x(), b.x()), 459 computeFloatFlushRelaxedULPDiff(a.y(), b.y()), 460 computeFloatFlushRelaxedULPDiff(a.z(), b.z()), 461 computeFloatFlushRelaxedULPDiff(a.w(), b.w())); 462} 463 464/*--------------------------------------------------------------------*//*! 465 * \brief Per-pixel threshold-based comparison 466 * 467 * This compare computes per-pixel differences between result and reference 468 * image. Comparison fails if any pixels exceed the given threshold value. 469 * 470 * This comparison uses ULP (units in last place) metric for computing the 471 * difference between floating-point values and thus this function can 472 * be used only for comparing floating-point texture data. In ULP calculation 473 * the denormal numbers are allowed to be flushed to zero. 474 * 475 * On failure error image is generated that shows where the failing pixels 476 * are. 477 * 478 * \param log Test log for results 479 * \param imageSetName Name for image set when logging results 480 * \param imageSetDesc Description for image set 481 * \param reference Reference image 482 * \param result Result image 483 * \param threshold Maximum allowed difference 484 * \param logMode Logging mode 485 * \return true if comparison passes, false otherwise 486 *//*--------------------------------------------------------------------*/ 487bool floatUlpThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode) 488{ 489 int width = reference.getWidth(); 490 int height = reference.getHeight(); 491 int depth = reference.getDepth(); 492 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 493 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 494 UVec4 maxDiff (0, 0, 0, 0); 495 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 496 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 497 498 TCU_CHECK(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 499 500 for (int z = 0; z < depth; z++) 501 { 502 for (int y = 0; y < height; y++) 503 { 504 for (int x = 0; x < width; x++) 505 { 506 const Vec4 refPix = reference.getPixel(x, y, z); 507 const Vec4 cmpPix = result.getPixel(x, y, z); 508 const UVec4 diff = computeFlushRelaxedULPDiff(refPix, cmpPix); 509 const bool isOk = boolAll(lessThanEqual(diff, threshold)); 510 511 maxDiff = max(maxDiff, diff); 512 513 errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 514 } 515 } 516 } 517 518 bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 519 520 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 521 { 522 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 523 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 524 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 525 { 526 computeScaleAndBias(reference, result, pixelScale, pixelBias); 527 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 528 } 529 530 if (!compareOk) 531 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 532 533 log << TestLog::ImageSet(imageSetName, imageSetDesc) 534 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 535 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 536 << TestLog::Image("ErrorMask", "Error mask", errorMask) 537 << TestLog::EndImageSet; 538 } 539 else if (logMode == COMPARE_LOG_RESULT) 540 { 541 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 542 computePixelScaleBias(result, pixelScale, pixelBias); 543 544 log << TestLog::ImageSet(imageSetName, imageSetDesc) 545 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 546 << TestLog::EndImageSet; 547 } 548 549 return compareOk; 550} 551 552/*--------------------------------------------------------------------*//*! 553 * \brief Per-pixel threshold-based comparison 554 * 555 * This compare computes per-pixel differences between result and reference 556 * image. Comparison fails if any pixels exceed the given threshold value. 557 * 558 * This comparison can be used for floating-point and fixed-point formats. 559 * Difference is computed in floating-point space. 560 * 561 * On failure an error image is generated that shows where the failing 562 * pixels are. 563 * 564 * \param log Test log for results 565 * \param imageSetName Name for image set when logging results 566 * \param imageSetDesc Description for image set 567 * \param reference Reference image 568 * \param result Result image 569 * \param threshold Maximum allowed difference 570 * \param logMode Logging mode 571 * \return true if comparison passes, false otherwise 572 *//*--------------------------------------------------------------------*/ 573bool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode) 574{ 575 int width = reference.getWidth(); 576 int height = reference.getHeight(); 577 int depth = reference.getDepth(); 578 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 579 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 580 Vec4 maxDiff (0.0f, 0.0f, 0.0f, 0.0f); 581 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 582 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 583 584 TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 585 586 for (int z = 0; z < depth; z++) 587 { 588 for (int y = 0; y < height; y++) 589 { 590 for (int x = 0; x < width; x++) 591 { 592 Vec4 refPix = reference.getPixel(x, y, z); 593 Vec4 cmpPix = result.getPixel(x, y, z); 594 595 Vec4 diff = abs(refPix - cmpPix); 596 bool isOk = boolAll(lessThanEqual(diff, threshold)); 597 598 maxDiff = max(maxDiff, diff); 599 600 errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 601 } 602 } 603 } 604 605 bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 606 607 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 608 { 609 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 610 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 611 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 612 { 613 computeScaleAndBias(reference, result, pixelScale, pixelBias); 614 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 615 } 616 617 if (!compareOk) 618 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 619 620 log << TestLog::ImageSet(imageSetName, imageSetDesc) 621 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 622 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 623 << TestLog::Image("ErrorMask", "Error mask", errorMask) 624 << TestLog::EndImageSet; 625 } 626 else if (logMode == COMPARE_LOG_RESULT) 627 { 628 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 629 computePixelScaleBias(result, pixelScale, pixelBias); 630 631 log << TestLog::ImageSet(imageSetName, imageSetDesc) 632 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 633 << TestLog::EndImageSet; 634 } 635 636 return compareOk; 637} 638 639/*--------------------------------------------------------------------*//*! 640 * \brief Per-pixel threshold-based comparison 641 * 642 * This compare computes per-pixel differences between result and reference 643 * color. Comparison fails if any pixels exceed the given threshold value. 644 * 645 * This comparison can be used for floating-point and fixed-point formats. 646 * Difference is computed in floating-point space. 647 * 648 * On failure an error image is generated that shows where the failing 649 * pixels are. 650 * 651 * \param log Test log for results 652 * \param imageSetName Name for image set when logging results 653 * \param imageSetDesc Description for image set 654 * \param reference Reference color 655 * \param result Result image 656 * \param threshold Maximum allowed difference 657 * \param logMode Logging mode 658 * \return true if comparison passes, false otherwise 659 *//*--------------------------------------------------------------------*/ 660bool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Vec4& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode) 661{ 662 const int width = result.getWidth(); 663 const int height = result.getHeight(); 664 const int depth = result.getDepth(); 665 666 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 667 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 668 Vec4 maxDiff (0.0f, 0.0f, 0.0f, 0.0f); 669 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 670 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 671 672 for (int z = 0; z < depth; z++) 673 { 674 for (int y = 0; y < height; y++) 675 { 676 for (int x = 0; x < width; x++) 677 { 678 const Vec4 cmpPix = result.getPixel(x, y, z); 679 const Vec4 diff = abs(reference - cmpPix); 680 const bool isOk = boolAll(lessThanEqual(diff, threshold)); 681 682 maxDiff = max(maxDiff, diff); 683 684 errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z); 685 } 686 } 687 } 688 689 bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 690 691 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 692 { 693 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 694 if (tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 695 { 696 computeScaleAndBias(result, result, pixelScale, pixelBias); 697 log << TestLog::Message << "Result image is normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 698 } 699 700 if (!compareOk) 701 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << ", reference = " << reference << TestLog::EndMessage; 702 703 log << TestLog::ImageSet(imageSetName, imageSetDesc) 704 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 705 << TestLog::Image("ErrorMask", "Error mask", errorMask) 706 << TestLog::EndImageSet; 707 } 708 else if (logMode == COMPARE_LOG_RESULT) 709 { 710 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 711 computePixelScaleBias(result, pixelScale, pixelBias); 712 713 log << TestLog::ImageSet(imageSetName, imageSetDesc) 714 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 715 << TestLog::EndImageSet; 716 } 717 718 return compareOk; 719} 720 721/*--------------------------------------------------------------------*//*! 722 * \brief Per-pixel threshold-based comparison 723 * 724 * This compare computes per-pixel differences between result and reference 725 * image. Comparison fails if any pixels exceed the given threshold value. 726 * 727 * This comparison can be used for integer- and fixed-point texture formats. 728 * Difference is computed in integer space. 729 * 730 * On failure error image is generated that shows where the failing pixels 731 * are. 732 * 733 * \param log Test log for results 734 * \param imageSetName Name for image set when logging results 735 * \param imageSetDesc Description for image set 736 * \param reference Reference image 737 * \param result Result image 738 * \param threshold Maximum allowed difference 739 * \param logMode Logging mode 740 * \return true if comparison passes, false otherwise 741 *//*--------------------------------------------------------------------*/ 742bool intThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode) 743{ 744 int width = reference.getWidth(); 745 int height = reference.getHeight(); 746 int depth = reference.getDepth(); 747 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 748 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 749 UVec4 maxDiff (0, 0, 0, 0); 750 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 751 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 752 753 TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 754 755 for (int z = 0; z < depth; z++) 756 { 757 for (int y = 0; y < height; y++) 758 { 759 for (int x = 0; x < width; x++) 760 { 761 IVec4 refPix = reference.getPixelInt(x, y, z); 762 IVec4 cmpPix = result.getPixelInt(x, y, z); 763 764 UVec4 diff = abs(refPix - cmpPix).cast<deUint32>(); 765 bool isOk = boolAll(lessThanEqual(diff, threshold)); 766 767 maxDiff = max(maxDiff, diff); 768 769 errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z); 770 } 771 } 772 } 773 774 bool compareOk = boolAll(lessThanEqual(maxDiff, threshold)); 775 776 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 777 { 778 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 779 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 780 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 781 { 782 computeScaleAndBias(reference, result, pixelScale, pixelBias); 783 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 784 } 785 786 if (!compareOk) 787 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage; 788 789 log << TestLog::ImageSet(imageSetName, imageSetDesc) 790 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 791 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 792 << TestLog::Image("ErrorMask", "Error mask", errorMask) 793 << TestLog::EndImageSet; 794 } 795 else if (logMode == COMPARE_LOG_RESULT) 796 { 797 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 798 computePixelScaleBias(result, pixelScale, pixelBias); 799 800 log << TestLog::ImageSet(imageSetName, imageSetDesc) 801 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 802 << TestLog::EndImageSet; 803 } 804 805 return compareOk; 806} 807 808/*--------------------------------------------------------------------*//*! 809 * \brief Per-pixel threshold-based deviation-ignoring comparison 810 * 811 * This compare computes per-pixel differences between result and reference 812 * image. Comparison fails if there is no pixel matching the given threshold 813 * value in the search volume. 814 * 815 * If the search volume contains out-of-bounds pixels, comparison can be set 816 * to either ignore these pixels in search or to accept any pixel that has 817 * out-of-bounds pixels in its search volume. 818 * 819 * This comparison can be used for integer- and fixed-point texture formats. 820 * Difference is computed in integer space. 821 * 822 * On failure error image is generated that shows where the failing pixels 823 * are. 824 * 825 * \param log Test log for results 826 * \param imageSetName Name for image set when logging results 827 * \param imageSetDesc Description for image set 828 * \param reference Reference image 829 * \param result Result image 830 * \param threshold Maximum allowed difference 831 * \param maxPositionDeviation Maximum allowed distance in the search 832 * volume. 833 * \param acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region 834 * \param logMode Logging mode 835 * \return true if comparison passes, false otherwise 836 *//*--------------------------------------------------------------------*/ 837bool 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) 838{ 839 const int width = reference.getWidth(); 840 const int height = reference.getHeight(); 841 const int depth = reference.getDepth(); 842 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 843 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 844 const int numFailingPixels = findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue); 845 const bool compareOk = numFailingPixels == 0; 846 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 847 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 848 849 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 850 { 851 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 852 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 853 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 854 { 855 computeScaleAndBias(reference, result, pixelScale, pixelBias); 856 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 857 } 858 859 if (!compareOk) 860 log << TestLog::Message 861 << "Image comparison failed:\n" 862 << "\tallowed position deviation = " << maxPositionDeviation << "\n" 863 << "\tcolor threshold = " << threshold 864 << TestLog::EndMessage; 865 866 log << TestLog::ImageSet(imageSetName, imageSetDesc) 867 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 868 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 869 << TestLog::Image("ErrorMask", "Error mask", errorMask) 870 << TestLog::EndImageSet; 871 } 872 else if (logMode == COMPARE_LOG_RESULT) 873 { 874 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 875 computePixelScaleBias(result, pixelScale, pixelBias); 876 877 log << TestLog::ImageSet(imageSetName, imageSetDesc) 878 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 879 << TestLog::EndImageSet; 880 } 881 882 return compareOk; 883} 884 885/*--------------------------------------------------------------------*//*! 886 * \brief Per-pixel threshold-based deviation-ignoring comparison 887 * 888 * This compare computes per-pixel differences between result and reference 889 * image. Pixel fails the test if there is no pixel matching the given 890 * threshold value in the search volume. Comparison fails if the number of 891 * failing pixels exceeds the given limit. 892 * 893 * If the search volume contains out-of-bounds pixels, comparison can be set 894 * to either ignore these pixels in search or to accept any pixel that has 895 * out-of-bounds pixels in its search volume. 896 * 897 * This comparison can be used for integer- and fixed-point texture formats. 898 * Difference is computed in integer space. 899 * 900 * On failure error image is generated that shows where the failing pixels 901 * are. 902 * 903 * \param log Test log for results 904 * \param imageSetName Name for image set when logging results 905 * \param imageSetDesc Description for image set 906 * \param reference Reference image 907 * \param result Result image 908 * \param threshold Maximum allowed difference 909 * \param maxPositionDeviation Maximum allowed distance in the search 910 * volume. 911 * \param acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region 912 * \param maxAllowedFailingPixels Maximum number of failing pixels 913 * \param logMode Logging mode 914 * \return true if comparison passes, false otherwise 915 *//*--------------------------------------------------------------------*/ 916bool 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) 917{ 918 const int width = reference.getWidth(); 919 const int height = reference.getHeight(); 920 const int depth = reference.getDepth(); 921 TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth); 922 PixelBufferAccess errorMask = errorMaskStorage.getAccess(); 923 const int numFailingPixels = findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue); 924 const bool compareOk = numFailingPixels <= maxAllowedFailingPixels; 925 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 926 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 927 928 if (!compareOk || logMode == COMPARE_LOG_EVERYTHING) 929 { 930 // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images. 931 if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT || 932 tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) 933 { 934 computeScaleAndBias(reference, result, pixelScale, pixelBias); 935 log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage; 936 } 937 938 if (!compareOk) 939 log << TestLog::Message 940 << "Image comparison failed:\n" 941 << "\tallowed position deviation = " << maxPositionDeviation << "\n" 942 << "\tcolor threshold = " << threshold 943 << TestLog::EndMessage; 944 log << TestLog::Message << "Number of failing pixels = " << numFailingPixels << ", max allowed = " << maxAllowedFailingPixels << TestLog::EndMessage; 945 946 log << TestLog::ImageSet(imageSetName, imageSetDesc) 947 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 948 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 949 << TestLog::Image("ErrorMask", "Error mask", errorMask) 950 << TestLog::EndImageSet; 951 } 952 else if (logMode == COMPARE_LOG_RESULT) 953 { 954 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 955 computePixelScaleBias(result, pixelScale, pixelBias); 956 957 log << TestLog::ImageSet(imageSetName, imageSetDesc) 958 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 959 << TestLog::EndImageSet; 960 } 961 962 return compareOk; 963} 964 965/*--------------------------------------------------------------------*//*! 966 * \brief Per-pixel threshold-based comparison 967 * 968 * This compare computes per-pixel differences between result and reference 969 * image. Comparison fails if any pixels exceed the given threshold value. 970 * 971 * On failure error image is generated that shows where the failing pixels 972 * are. 973 * 974 * \param log Test log for results 975 * \param imageSetName Name for image set when logging results 976 * \param imageSetDesc Description for image set 977 * \param reference Reference image 978 * \param result Result image 979 * \param threshold Maximum allowed difference 980 * \param logMode Logging mode 981 * \return true if comparison passes, false otherwise 982 *//*--------------------------------------------------------------------*/ 983bool pixelThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, const RGBA& threshold, CompareLogMode logMode) 984{ 985 return intThresholdCompare(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold.toIVec().cast<deUint32>(), logMode); 986} 987 988/*--------------------------------------------------------------------*//*! 989 * \brief Bilinear image comparison 990 * 991 * \todo [pyry] Describe 992 * 993 * On failure error image is generated that shows where the failing pixels 994 * are. 995 * 996 * \note Currently supports only RGBA, UNORM_INT8 formats 997 * \param log Test log for results 998 * \param imageSetName Name for image set when logging results 999 * \param imageSetDesc Description for image set 1000 * \param reference Reference image 1001 * \param result Result image 1002 * \param threshold Maximum local difference 1003 * \param logMode Logging mode 1004 * \return true if comparison passes, false otherwise 1005 *//*--------------------------------------------------------------------*/ 1006bool bilinearCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const RGBA threshold, CompareLogMode logMode) 1007{ 1008 TextureLevel errorMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight()); 1009 bool isOk = bilinearCompare(reference, result, errorMask, threshold); 1010 Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f); 1011 Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f); 1012 1013 if (!isOk || logMode == COMPARE_LOG_EVERYTHING) 1014 { 1015 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1016 computeScaleAndBias(reference, result, pixelScale, pixelBias); 1017 1018 if (!isOk) 1019 log << TestLog::Message << "Image comparison failed, threshold = " << threshold << TestLog::EndMessage; 1020 1021 log << TestLog::ImageSet(imageSetName, imageSetDesc) 1022 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1023 << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias) 1024 << TestLog::Image("ErrorMask", "Error mask", errorMask) 1025 << TestLog::EndImageSet; 1026 } 1027 else if (logMode == COMPARE_LOG_RESULT) 1028 { 1029 if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8)) 1030 computePixelScaleBias(result, pixelScale, pixelBias); 1031 1032 log << TestLog::ImageSet(imageSetName, imageSetDesc) 1033 << TestLog::Image("Result", "Result", result, pixelScale, pixelBias) 1034 << TestLog::EndImageSet; 1035 } 1036 1037 return isOk; 1038} 1039 1040} // tcu 1041