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