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