Home | History | Annotate | Download | only in common
      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 
     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 
     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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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 
    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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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  *//*--------------------------------------------------------------------*/
    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