Merge upstream-vulkan-cts-1.0-dev into master
[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
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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
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
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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