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
38 namespace tcu
39 {
40
41 namespace
42 {
43
computeScaleAndBias(const ConstPixelBufferAccess & reference,const ConstPixelBufferAccess & result,tcu::Vec4 & scale,tcu::Vec4 & bias)44 void 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
findNumPositionDeviationFailingPixels(const PixelBufferAccess & errorMask,const ConstPixelBufferAccess & reference,const ConstPixelBufferAccess & result,const UVec4 & threshold,const tcu::IVec3 & maxPositionDeviation,bool acceptOutOfBoundsAsAnyValue)91 static 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 *//*--------------------------------------------------------------------*/
fuzzyCompare(TestLog & log,const char * imageSetName,const char * imageSetDesc,const ConstPixelBufferAccess & reference,const ConstPixelBufferAccess & result,float threshold,CompareLogMode logMode)216 bool 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 *//*--------------------------------------------------------------------*/
fuzzyCompare(TestLog & log,const char * imageSetName,const char * imageSetDesc,const Surface & reference,const Surface & result,float threshold,CompareLogMode logMode)285 bool 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
computeSquaredDiffSum(const ConstPixelBufferAccess & ref,const ConstPixelBufferAccess & cmp,const PixelBufferAccess & diffMask,int diffFactor)290 static 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 *//*--------------------------------------------------------------------*/
measurePixelDiffAccuracy(TestLog & log,const char * imageSetName,const char * imageSetDesc,const ConstPixelBufferAccess & reference,const ConstPixelBufferAccess & result,int bestScoreDiff,int worstScoreDiff,CompareLogMode logMode)334 int 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 *//*--------------------------------------------------------------------*/
measurePixelDiffAccuracy(TestLog & log,const char * imageSetName,const char * imageSetDesc,const Surface & reference,const Surface & result,int bestScoreDiff,int worstScoreDiff,CompareLogMode logMode)390 int 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 *//*--------------------------------------------------------------------*/
getPositionOfIEEEFloatWithoutDenormals(float x)404 static 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
computeFloatFlushRelaxedULPDiff(float a,float b)437 static 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
computeFlushRelaxedULPDiff(const tcu::Vec4 & a,const tcu::Vec4 & b)456 static 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 *//*--------------------------------------------------------------------*/
floatUlpThresholdCompare(TestLog & log,const char * imageSetName,const char * imageSetDesc,const ConstPixelBufferAccess & reference,const ConstPixelBufferAccess & result,const UVec4 & threshold,CompareLogMode logMode)487 bool 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 *//*--------------------------------------------------------------------*/
floatThresholdCompare(TestLog & log,const char * imageSetName,const char * imageSetDesc,const ConstPixelBufferAccess & reference,const ConstPixelBufferAccess & result,const Vec4 & threshold,CompareLogMode logMode)573 bool 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 *//*--------------------------------------------------------------------*/
floatThresholdCompare(TestLog & log,const char * imageSetName,const char * imageSetDesc,const Vec4 & reference,const ConstPixelBufferAccess & result,const Vec4 & threshold,CompareLogMode logMode)660 bool 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 *//*--------------------------------------------------------------------*/
intThresholdCompare(TestLog & log,const char * imageSetName,const char * imageSetDesc,const ConstPixelBufferAccess & reference,const ConstPixelBufferAccess & result,const UVec4 & threshold,CompareLogMode logMode)742 bool 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 *//*--------------------------------------------------------------------*/
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 bool 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 *//*--------------------------------------------------------------------*/
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 bool 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 *//*--------------------------------------------------------------------*/
pixelThresholdCompare(TestLog & log,const char * imageSetName,const char * imageSetDesc,const Surface & reference,const Surface & result,const RGBA & threshold,CompareLogMode logMode)983 bool 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 *//*--------------------------------------------------------------------*/
bilinearCompare(TestLog & log,const char * imageSetName,const char * imageSetDesc,const ConstPixelBufferAccess & reference,const ConstPixelBufferAccess & result,const RGBA threshold,CompareLogMode logMode)1006 bool 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