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