1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program Tester Core
3e5c31af7Sopenharmony_ci * ----------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Image comparison utilities.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp"
25e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
26e5c31af7Sopenharmony_ci#include "tcuFuzzyImageCompare.hpp"
27e5c31af7Sopenharmony_ci#include "tcuBilinearImageCompare.hpp"
28e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
29e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
30e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp"
31e5c31af7Sopenharmony_ci#include "tcuRGBA.hpp"
32e5c31af7Sopenharmony_ci#include "tcuTexture.hpp"
33e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
34e5c31af7Sopenharmony_ci#include "tcuFloat.hpp"
35e5c31af7Sopenharmony_ci
36e5c31af7Sopenharmony_ci#include <string.h>
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_cinamespace tcu
39e5c31af7Sopenharmony_ci{
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_cinamespace
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_civoid computeScaleAndBias (const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, tcu::Vec4& scale, tcu::Vec4& bias)
45e5c31af7Sopenharmony_ci{
46e5c31af7Sopenharmony_ci	Vec4 minVal;
47e5c31af7Sopenharmony_ci	Vec4 maxVal;
48e5c31af7Sopenharmony_ci	const float eps = 0.0001f;
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_ci	{
51e5c31af7Sopenharmony_ci		Vec4 refMin;
52e5c31af7Sopenharmony_ci		Vec4 refMax;
53e5c31af7Sopenharmony_ci		estimatePixelValueRange(reference, refMin, refMax);
54e5c31af7Sopenharmony_ci
55e5c31af7Sopenharmony_ci		minVal	= refMin;
56e5c31af7Sopenharmony_ci		maxVal	= refMax;
57e5c31af7Sopenharmony_ci	}
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_ci	{
60e5c31af7Sopenharmony_ci		Vec4 resMin;
61e5c31af7Sopenharmony_ci		Vec4 resMax;
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ci		estimatePixelValueRange(result, resMin, resMax);
64e5c31af7Sopenharmony_ci
65e5c31af7Sopenharmony_ci		minVal[0] = de::min(minVal[0], resMin[0]);
66e5c31af7Sopenharmony_ci		minVal[1] = de::min(minVal[1], resMin[1]);
67e5c31af7Sopenharmony_ci		minVal[2] = de::min(minVal[2], resMin[2]);
68e5c31af7Sopenharmony_ci		minVal[3] = de::min(minVal[3], resMin[3]);
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ci		maxVal[0] = de::max(maxVal[0], resMax[0]);
71e5c31af7Sopenharmony_ci		maxVal[1] = de::max(maxVal[1], resMax[1]);
72e5c31af7Sopenharmony_ci		maxVal[2] = de::max(maxVal[2], resMax[2]);
73e5c31af7Sopenharmony_ci		maxVal[3] = de::max(maxVal[3], resMax[3]);
74e5c31af7Sopenharmony_ci	}
75e5c31af7Sopenharmony_ci
76e5c31af7Sopenharmony_ci	for (int c = 0; c < 4; c++)
77e5c31af7Sopenharmony_ci	{
78e5c31af7Sopenharmony_ci		if (maxVal[c] - minVal[c] < eps)
79e5c31af7Sopenharmony_ci		{
80e5c31af7Sopenharmony_ci			scale[c]	= (maxVal[c] < eps) ? 1.0f : (1.0f / maxVal[c]);
81e5c31af7Sopenharmony_ci			bias[c]		= (c == 3) ? (1.0f - maxVal[c]*scale[c]) : (0.0f - minVal[c]*scale[c]);
82e5c31af7Sopenharmony_ci		}
83e5c31af7Sopenharmony_ci		else
84e5c31af7Sopenharmony_ci		{
85e5c31af7Sopenharmony_ci			scale[c]	= 1.0f / (maxVal[c] - minVal[c]);
86e5c31af7Sopenharmony_ci			bias[c]		= 0.0f - minVal[c]*scale[c];
87e5c31af7Sopenharmony_ci		}
88e5c31af7Sopenharmony_ci	}
89e5c31af7Sopenharmony_ci}
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_cistatic int findNumPositionDeviationFailingPixels (const PixelBufferAccess& errorMask, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, const tcu::IVec3& maxPositionDeviation, bool acceptOutOfBoundsAsAnyValue)
92e5c31af7Sopenharmony_ci{
93e5c31af7Sopenharmony_ci	const tcu::IVec4	okColor				(0, 255, 0, 255);
94e5c31af7Sopenharmony_ci	const tcu::IVec4	errorColor			(255, 0, 0, 255);
95e5c31af7Sopenharmony_ci	const int			width				= reference.getWidth();
96e5c31af7Sopenharmony_ci	const int			height				= reference.getHeight();
97e5c31af7Sopenharmony_ci	const int			depth				= reference.getDepth();
98e5c31af7Sopenharmony_ci	int					numFailingPixels	= 0;
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_ci	// Accept pixels "sampling" over the image bounds pixels since "taps" could be anything
101e5c31af7Sopenharmony_ci	const int			beginX				= (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.x()) : (0);
102e5c31af7Sopenharmony_ci	const int			beginY				= (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.y()) : (0);
103e5c31af7Sopenharmony_ci	const int			beginZ				= (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.z()) : (0);
104e5c31af7Sopenharmony_ci	const int			endX				= (acceptOutOfBoundsAsAnyValue) ? (width  - maxPositionDeviation.x()) : (width);
105e5c31af7Sopenharmony_ci	const int			endY				= (acceptOutOfBoundsAsAnyValue) ? (height - maxPositionDeviation.y()) : (height);
106e5c31af7Sopenharmony_ci	const int			endZ				= (acceptOutOfBoundsAsAnyValue) ? (depth  - maxPositionDeviation.z()) : (depth);
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
109e5c31af7Sopenharmony_ci	DE_ASSERT(endX > 0 && endY > 0 && endZ > 0);	// most likely a bug
110e5c31af7Sopenharmony_ci
111e5c31af7Sopenharmony_ci	tcu::clear(errorMask, okColor);
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci	for (int z = beginZ; z < endZ; z++)
114e5c31af7Sopenharmony_ci	{
115e5c31af7Sopenharmony_ci		for (int y = beginY; y < endY; y++)
116e5c31af7Sopenharmony_ci		{
117e5c31af7Sopenharmony_ci			for (int x = beginX; x < endX; x++)
118e5c31af7Sopenharmony_ci			{
119e5c31af7Sopenharmony_ci				const IVec4	refPix = reference.getPixelInt(x, y, z);
120e5c31af7Sopenharmony_ci				const IVec4	cmpPix = result.getPixelInt(x, y, z);
121e5c31af7Sopenharmony_ci
122e5c31af7Sopenharmony_ci				// Exact match
123e5c31af7Sopenharmony_ci				{
124e5c31af7Sopenharmony_ci					const UVec4	diff = abs(refPix - cmpPix).cast<deUint32>();
125e5c31af7Sopenharmony_ci					const bool	isOk = boolAll(lessThanEqual(diff, threshold));
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci					if (isOk)
128e5c31af7Sopenharmony_ci						continue;
129e5c31af7Sopenharmony_ci				}
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci				// Find matching pixels for both result and reference pixel
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ci				{
134e5c31af7Sopenharmony_ci					bool pixelFoundForReference = false;
135e5c31af7Sopenharmony_ci
136e5c31af7Sopenharmony_ci					// Find deviated result pixel for reference
137e5c31af7Sopenharmony_ci
138e5c31af7Sopenharmony_ci					for (int sz = de::max(0, z - maxPositionDeviation.z()); sz <= de::min(depth  - 1, z + maxPositionDeviation.z()) && !pixelFoundForReference; ++sz)
139e5c31af7Sopenharmony_ci					for (int sy = de::max(0, y - maxPositionDeviation.y()); sy <= de::min(height - 1, y + maxPositionDeviation.y()) && !pixelFoundForReference; ++sy)
140e5c31af7Sopenharmony_ci					for (int sx = de::max(0, x - maxPositionDeviation.x()); sx <= de::min(width  - 1, x + maxPositionDeviation.x()) && !pixelFoundForReference; ++sx)
141e5c31af7Sopenharmony_ci					{
142e5c31af7Sopenharmony_ci						const IVec4	deviatedCmpPix	= result.getPixelInt(sx, sy, sz);
143e5c31af7Sopenharmony_ci						const UVec4	diff			= abs(refPix - deviatedCmpPix).cast<deUint32>();
144e5c31af7Sopenharmony_ci						const bool	isOk			= boolAll(lessThanEqual(diff, threshold));
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ci						pixelFoundForReference		= isOk;
147e5c31af7Sopenharmony_ci					}
148e5c31af7Sopenharmony_ci
149e5c31af7Sopenharmony_ci					if (!pixelFoundForReference)
150e5c31af7Sopenharmony_ci					{
151e5c31af7Sopenharmony_ci						errorMask.setPixel(errorColor, x, y, z);
152e5c31af7Sopenharmony_ci						++numFailingPixels;
153e5c31af7Sopenharmony_ci						continue;
154e5c31af7Sopenharmony_ci					}
155e5c31af7Sopenharmony_ci				}
156e5c31af7Sopenharmony_ci				{
157e5c31af7Sopenharmony_ci					bool pixelFoundForResult = false;
158e5c31af7Sopenharmony_ci
159e5c31af7Sopenharmony_ci					// Find deviated reference pixel for result
160e5c31af7Sopenharmony_ci
161e5c31af7Sopenharmony_ci					for (int sz = de::max(0, z - maxPositionDeviation.z()); sz <= de::min(depth  - 1, z + maxPositionDeviation.z()) && !pixelFoundForResult; ++sz)
162e5c31af7Sopenharmony_ci					for (int sy = de::max(0, y - maxPositionDeviation.y()); sy <= de::min(height - 1, y + maxPositionDeviation.y()) && !pixelFoundForResult; ++sy)
163e5c31af7Sopenharmony_ci					for (int sx = de::max(0, x - maxPositionDeviation.x()); sx <= de::min(width  - 1, x + maxPositionDeviation.x()) && !pixelFoundForResult; ++sx)
164e5c31af7Sopenharmony_ci					{
165e5c31af7Sopenharmony_ci						const IVec4	deviatedRefPix	= reference.getPixelInt(sx, sy, sz);
166e5c31af7Sopenharmony_ci						const UVec4	diff			= abs(cmpPix - deviatedRefPix).cast<deUint32>();
167e5c31af7Sopenharmony_ci						const bool	isOk			= boolAll(lessThanEqual(diff, threshold));
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_ci						pixelFoundForResult			= isOk;
170e5c31af7Sopenharmony_ci					}
171e5c31af7Sopenharmony_ci
172e5c31af7Sopenharmony_ci					if (!pixelFoundForResult)
173e5c31af7Sopenharmony_ci					{
174e5c31af7Sopenharmony_ci						errorMask.setPixel(errorColor, x, y, z);
175e5c31af7Sopenharmony_ci						++numFailingPixels;
176e5c31af7Sopenharmony_ci						continue;
177e5c31af7Sopenharmony_ci					}
178e5c31af7Sopenharmony_ci				}
179e5c31af7Sopenharmony_ci			}
180e5c31af7Sopenharmony_ci		}
181e5c31af7Sopenharmony_ci	}
182e5c31af7Sopenharmony_ci
183e5c31af7Sopenharmony_ci	return numFailingPixels;
184e5c31af7Sopenharmony_ci}
185e5c31af7Sopenharmony_ci
186e5c31af7Sopenharmony_ci} // anonymous
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
189e5c31af7Sopenharmony_ci * \brief Fuzzy image comparison
190e5c31af7Sopenharmony_ci *
191e5c31af7Sopenharmony_ci * This image comparison is designed for comparing images rendered by 3D
192e5c31af7Sopenharmony_ci * graphics APIs such as OpenGL. The comparison allows small local differences
193e5c31af7Sopenharmony_ci * and compensates for aliasing.
194e5c31af7Sopenharmony_ci *
195e5c31af7Sopenharmony_ci * The algorithm first performs light blurring on both images and then
196e5c31af7Sopenharmony_ci * does per-pixel analysis. Pixels are compared to 3x3 bilinear surface
197e5c31af7Sopenharmony_ci * defined by adjecent pixels. This compensates for both 1-pixel deviations
198e5c31af7Sopenharmony_ci * in geometry and aliasing in texture data.
199e5c31af7Sopenharmony_ci *
200e5c31af7Sopenharmony_ci * Error metric is computed based on the differences. On valid images the
201e5c31af7Sopenharmony_ci * metric is usually <0.01. Thus good threshold values are in range 0.02 to
202e5c31af7Sopenharmony_ci * 0.05.
203e5c31af7Sopenharmony_ci *
204e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
205e5c31af7Sopenharmony_ci * are.
206e5c31af7Sopenharmony_ci *
207e5c31af7Sopenharmony_ci * \note				Currently supports only UNORM_INT8 formats
208e5c31af7Sopenharmony_ci * \param log			Test log for results
209e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
210e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
211e5c31af7Sopenharmony_ci * \param reference		Reference image
212e5c31af7Sopenharmony_ci * \param result		Result image
213e5c31af7Sopenharmony_ci * \param threshold		Error metric threshold (good values are 0.02-0.05)
214e5c31af7Sopenharmony_ci * \param logMode		Logging mode
215e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
216e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
217e5c31af7Sopenharmony_cibool fuzzyCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, float threshold, CompareLogMode logMode)
218e5c31af7Sopenharmony_ci{
219e5c31af7Sopenharmony_ci	FuzzyCompareParams	params;		// Use defaults.
220e5c31af7Sopenharmony_ci	TextureLevel		errorMask		(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight());
221e5c31af7Sopenharmony_ci	float				difference		= fuzzyCompare(params, reference, result, errorMask.getAccess());
222e5c31af7Sopenharmony_ci	bool				isOk			= difference <= threshold;
223e5c31af7Sopenharmony_ci	Vec4				pixelBias		(0.0f, 0.0f, 0.0f, 0.0f);
224e5c31af7Sopenharmony_ci	Vec4				pixelScale		(1.0f, 1.0f, 1.0f, 1.0f);
225e5c31af7Sopenharmony_ci
226e5c31af7Sopenharmony_ci	if (!isOk || logMode == COMPARE_LOG_EVERYTHING)
227e5c31af7Sopenharmony_ci	{
228e5c31af7Sopenharmony_ci		// Generate more accurate error mask.
229e5c31af7Sopenharmony_ci		params.maxSampleSkip = 0;
230e5c31af7Sopenharmony_ci		fuzzyCompare(params, reference, result, errorMask.getAccess());
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
233e5c31af7Sopenharmony_ci			computeScaleAndBias(reference, result, pixelScale, pixelBias);
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_ci		if (!isOk)
236e5c31af7Sopenharmony_ci			log << TestLog::Message << "Image comparison failed: difference = " << difference << ", threshold = " << threshold << TestLog::EndMessage;
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
239e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
240e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference,	pixelScale, pixelBias)
241e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
242e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
243e5c31af7Sopenharmony_ci	}
244e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
245e5c31af7Sopenharmony_ci	{
246e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
247e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
248e5c31af7Sopenharmony_ci
249e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
250e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result, pixelScale, pixelBias)
251e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
252e5c31af7Sopenharmony_ci	}
253e5c31af7Sopenharmony_ci
254e5c31af7Sopenharmony_ci	return isOk;
255e5c31af7Sopenharmony_ci}
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
258e5c31af7Sopenharmony_ci * \brief Per-pixel bitwise comparison
259e5c31af7Sopenharmony_ci *
260e5c31af7Sopenharmony_ci * This compare expects bit precision between result and reference image.
261e5c31af7Sopenharmony_ci * Comparison fails if any pixels do not match bitwise.
262e5c31af7Sopenharmony_ci * Reference and result format must match.
263e5c31af7Sopenharmony_ci *
264e5c31af7Sopenharmony_ci * This comparison can be used for any type texture formats since it does
265e5c31af7Sopenharmony_ci * not care about types.
266e5c31af7Sopenharmony_ci *
267e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
268e5c31af7Sopenharmony_ci * are.
269e5c31af7Sopenharmony_ci *
270e5c31af7Sopenharmony_ci * \param log			Test log for results
271e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
272e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
273e5c31af7Sopenharmony_ci * \param reference		Reference image
274e5c31af7Sopenharmony_ci * \param result		Result image
275e5c31af7Sopenharmony_ci * \param logMode		Logging mode
276e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
277e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
278e5c31af7Sopenharmony_cibool bitwiseCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, CompareLogMode logMode)
279e5c31af7Sopenharmony_ci{
280e5c31af7Sopenharmony_ci	int	width	= reference.getWidth();
281e5c31af7Sopenharmony_ci	int	height	= reference.getHeight();
282e5c31af7Sopenharmony_ci	int	depth	= reference.getDepth();
283e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci	// Enforce texture has same channel count and channel size
286e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(reference.getFormat() == result.getFormat()); result.getPixelPitch();
287e5c31af7Sopenharmony_ci
288e5c31af7Sopenharmony_ci	TextureLevel		errorMaskStorage	(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
289e5c31af7Sopenharmony_ci	PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
290e5c31af7Sopenharmony_ci	Vec4				pixelBias			(0.0f, 0.0f, 0.0f, 0.0f);
291e5c31af7Sopenharmony_ci	Vec4				pixelScale			(1.0f, 1.0f, 1.0f, 1.0f);
292e5c31af7Sopenharmony_ci	bool				compareOk			= true;
293e5c31af7Sopenharmony_ci
294e5c31af7Sopenharmony_ci	for (int z = 0; z < depth; z++)
295e5c31af7Sopenharmony_ci	{
296e5c31af7Sopenharmony_ci		for (int y = 0; y < height; y++)
297e5c31af7Sopenharmony_ci		{
298e5c31af7Sopenharmony_ci			for (int x = 0; x < width; x++)
299e5c31af7Sopenharmony_ci			{
300e5c31af7Sopenharmony_ci				const U64Vec4	refPix	= reference.getPixelBitsAsUint64(x, y, z);
301e5c31af7Sopenharmony_ci				const U64Vec4	cmpPix	= result.getPixelBitsAsUint64(x, y, z);
302e5c31af7Sopenharmony_ci				const bool		isOk	= (refPix == cmpPix);
303e5c31af7Sopenharmony_ci
304e5c31af7Sopenharmony_ci				errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z);
305e5c31af7Sopenharmony_ci				compareOk	&= isOk;
306e5c31af7Sopenharmony_ci			}
307e5c31af7Sopenharmony_ci		}
308e5c31af7Sopenharmony_ci	}
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ci	if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
311e5c31af7Sopenharmony_ci	{
312e5c31af7Sopenharmony_ci		{
313e5c31af7Sopenharmony_ci			const auto refChannelClass = tcu::getTextureChannelClass(reference.getFormat().type);
314e5c31af7Sopenharmony_ci			const auto resChannelClass = tcu::getTextureChannelClass(result.getFormat().type);
315e5c31af7Sopenharmony_ci
316e5c31af7Sopenharmony_ci			const bool refIsUint8 = (reference.getFormat().type == TextureFormat::UNSIGNED_INT8);
317e5c31af7Sopenharmony_ci			const bool resIsUint8 = (result.getFormat().type == TextureFormat::UNSIGNED_INT8);
318e5c31af7Sopenharmony_ci
319e5c31af7Sopenharmony_ci			const bool calcScaleBias = ((refChannelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT && !refIsUint8) ||
320e5c31af7Sopenharmony_ci				(resChannelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT && !resIsUint8));
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_ci			// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
323e5c31af7Sopenharmony_ci			if (calcScaleBias)
324e5c31af7Sopenharmony_ci			{
325e5c31af7Sopenharmony_ci				computeScaleAndBias(reference, result, pixelScale, pixelBias);
326e5c31af7Sopenharmony_ci				log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
327e5c31af7Sopenharmony_ci			}
328e5c31af7Sopenharmony_ci		}
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_ci		if (!compareOk)
331e5c31af7Sopenharmony_ci			log << TestLog::Message << "Image comparison failed: Pixels with different values were found when bitwise precision is expected" << TestLog::EndMessage;
332e5c31af7Sopenharmony_ci
333e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
334e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
335e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference,	pixelScale, pixelBias)
336e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
337e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
338e5c31af7Sopenharmony_ci	}
339e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
340e5c31af7Sopenharmony_ci	{
341e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
342e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
343e5c31af7Sopenharmony_ci
344e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
345e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
346e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
347e5c31af7Sopenharmony_ci	}
348e5c31af7Sopenharmony_ci
349e5c31af7Sopenharmony_ci	return compareOk;
350e5c31af7Sopenharmony_ci}
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
353e5c31af7Sopenharmony_ci * \brief Fuzzy image comparison
354e5c31af7Sopenharmony_ci *
355e5c31af7Sopenharmony_ci * This image comparison is designed for comparing images rendered by 3D
356e5c31af7Sopenharmony_ci * graphics APIs such as OpenGL. The comparison allows small local differences
357e5c31af7Sopenharmony_ci * and compensates for aliasing.
358e5c31af7Sopenharmony_ci *
359e5c31af7Sopenharmony_ci * The algorithm first performs light blurring on both images and then
360e5c31af7Sopenharmony_ci * does per-pixel analysis. Pixels are compared to 3x3 bilinear surface
361e5c31af7Sopenharmony_ci * defined by adjecent pixels. This compensates for both 1-pixel deviations
362e5c31af7Sopenharmony_ci * in geometry and aliasing in texture data.
363e5c31af7Sopenharmony_ci *
364e5c31af7Sopenharmony_ci * Error metric is computed based on the differences. On valid images the
365e5c31af7Sopenharmony_ci * metric is usually <0.01. Thus good threshold values are in range 0.02 to
366e5c31af7Sopenharmony_ci * 0.05.
367e5c31af7Sopenharmony_ci *
368e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
369e5c31af7Sopenharmony_ci * are.
370e5c31af7Sopenharmony_ci *
371e5c31af7Sopenharmony_ci * \note				Currently supports only UNORM_INT8 formats
372e5c31af7Sopenharmony_ci * \param log			Test log for results
373e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
374e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
375e5c31af7Sopenharmony_ci * \param reference		Reference image
376e5c31af7Sopenharmony_ci * \param result		Result image
377e5c31af7Sopenharmony_ci * \param threshold		Error metric threshold (good values are 0.02-0.05)
378e5c31af7Sopenharmony_ci * \param logMode		Logging mode
379e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
380e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
381e5c31af7Sopenharmony_cibool fuzzyCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, float threshold, CompareLogMode logMode)
382e5c31af7Sopenharmony_ci{
383e5c31af7Sopenharmony_ci	return fuzzyCompare(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold, logMode);
384e5c31af7Sopenharmony_ci}
385e5c31af7Sopenharmony_ci
386e5c31af7Sopenharmony_cistatic deInt64 computeSquaredDiffSum (const ConstPixelBufferAccess& ref, const ConstPixelBufferAccess& cmp, const PixelBufferAccess& diffMask, int diffFactor)
387e5c31af7Sopenharmony_ci{
388e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(ref.getFormat().type == TextureFormat::UNORM_INT8 && cmp.getFormat().type == TextureFormat::UNORM_INT8);
389e5c31af7Sopenharmony_ci	DE_ASSERT(ref.getWidth() == cmp.getWidth() && ref.getWidth() == diffMask.getWidth());
390e5c31af7Sopenharmony_ci	DE_ASSERT(ref.getHeight() == cmp.getHeight() && ref.getHeight() == diffMask.getHeight());
391e5c31af7Sopenharmony_ci
392e5c31af7Sopenharmony_ci	deInt64 diffSum = 0;
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci	for (int y = 0; y < cmp.getHeight(); y++)
395e5c31af7Sopenharmony_ci	{
396e5c31af7Sopenharmony_ci		for (int x = 0; x < cmp.getWidth(); x++)
397e5c31af7Sopenharmony_ci		{
398e5c31af7Sopenharmony_ci			IVec4	a		= ref.getPixelInt(x, y);
399e5c31af7Sopenharmony_ci			IVec4	b		= cmp.getPixelInt(x, y);
400e5c31af7Sopenharmony_ci			IVec4	diff	= abs(a - b);
401e5c31af7Sopenharmony_ci			int		sum		= diff.x() + diff.y() + diff.z() + diff.w();
402e5c31af7Sopenharmony_ci			int		sqSum	= diff.x()*diff.x() + diff.y()*diff.y() + diff.z()*diff.z() + diff.w()*diff.w();
403e5c31af7Sopenharmony_ci
404e5c31af7Sopenharmony_ci			diffMask.setPixel(tcu::RGBA(deClamp32(sum*diffFactor, 0, 255), deClamp32(255-sum*diffFactor, 0, 255), 0, 255).toVec(), x, y);
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_ci			diffSum += (deInt64)sqSum;
407e5c31af7Sopenharmony_ci		}
408e5c31af7Sopenharmony_ci	}
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci	return diffSum;
411e5c31af7Sopenharmony_ci}
412e5c31af7Sopenharmony_ci
413e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
414e5c31af7Sopenharmony_ci * \brief Per-pixel difference accuracy metric
415e5c31af7Sopenharmony_ci *
416e5c31af7Sopenharmony_ci * Computes accuracy metric using per-pixel differences between reference
417e5c31af7Sopenharmony_ci * and result images.
418e5c31af7Sopenharmony_ci *
419e5c31af7Sopenharmony_ci * \note					Supports only integer- and fixed-point formats
420e5c31af7Sopenharmony_ci * \param log				Test log for results
421e5c31af7Sopenharmony_ci * \param imageSetName		Name for image set when logging results
422e5c31af7Sopenharmony_ci * \param imageSetDesc		Description for image set
423e5c31af7Sopenharmony_ci * \param reference			Reference image
424e5c31af7Sopenharmony_ci * \param result			Result image
425e5c31af7Sopenharmony_ci * \param bestScoreDiff		Scaling factor
426e5c31af7Sopenharmony_ci * \param worstScoreDiff	Scaling factor
427e5c31af7Sopenharmony_ci * \param logMode			Logging mode
428e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
429e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
430e5c31af7Sopenharmony_ciint measurePixelDiffAccuracy (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, int bestScoreDiff, int worstScoreDiff, CompareLogMode logMode)
431e5c31af7Sopenharmony_ci{
432e5c31af7Sopenharmony_ci	TextureLevel	diffMask		(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight());
433e5c31af7Sopenharmony_ci	int				diffFactor		= 8;
434e5c31af7Sopenharmony_ci	deInt64			squaredSum		= computeSquaredDiffSum(reference, result, diffMask.getAccess(), diffFactor);
435e5c31af7Sopenharmony_ci	float			sum				= deFloatSqrt((float)squaredSum);
436e5c31af7Sopenharmony_ci	int				score			= deClamp32(deFloorFloatToInt32(100.0f - (de::max(sum-(float)bestScoreDiff, 0.0f) / (float)(worstScoreDiff-bestScoreDiff))*100.0f), 0, 100);
437e5c31af7Sopenharmony_ci	const int		failThreshold	= 10;
438e5c31af7Sopenharmony_ci	Vec4			pixelBias		(0.0f, 0.0f, 0.0f, 0.0f);
439e5c31af7Sopenharmony_ci	Vec4			pixelScale		(1.0f, 1.0f, 1.0f, 1.0f);
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci	if (logMode == COMPARE_LOG_EVERYTHING || score <= failThreshold)
442e5c31af7Sopenharmony_ci	{
443e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
444e5c31af7Sopenharmony_ci			computeScaleAndBias(reference, result, pixelScale, pixelBias);
445e5c31af7Sopenharmony_ci
446e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
447e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",			result,		pixelScale, pixelBias)
448e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",		reference,	pixelScale, pixelBias)
449e5c31af7Sopenharmony_ci			<< TestLog::Image("DiffMask",	"Difference",		diffMask)
450e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
451e5c31af7Sopenharmony_ci	}
452e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
453e5c31af7Sopenharmony_ci	{
454e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
455e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
458e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",			result,		pixelScale, pixelBias)
459e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
460e5c31af7Sopenharmony_ci	}
461e5c31af7Sopenharmony_ci
462e5c31af7Sopenharmony_ci	if (logMode != COMPARE_LOG_ON_ERROR || score <= failThreshold)
463e5c31af7Sopenharmony_ci		log << TestLog::Integer("DiffSum", "Squared difference sum", "", QP_KEY_TAG_NONE, squaredSum)
464e5c31af7Sopenharmony_ci			<< TestLog::Integer("Score", "Score", "", QP_KEY_TAG_QUALITY, score);
465e5c31af7Sopenharmony_ci
466e5c31af7Sopenharmony_ci	return score;
467e5c31af7Sopenharmony_ci}
468e5c31af7Sopenharmony_ci
469e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
470e5c31af7Sopenharmony_ci * \brief Per-pixel difference accuracy metric
471e5c31af7Sopenharmony_ci *
472e5c31af7Sopenharmony_ci * Computes accuracy metric using per-pixel differences between reference
473e5c31af7Sopenharmony_ci * and result images.
474e5c31af7Sopenharmony_ci *
475e5c31af7Sopenharmony_ci * \note					Supports only integer- and fixed-point formats
476e5c31af7Sopenharmony_ci * \param log				Test log for results
477e5c31af7Sopenharmony_ci * \param imageSetName		Name for image set when logging results
478e5c31af7Sopenharmony_ci * \param imageSetDesc		Description for image set
479e5c31af7Sopenharmony_ci * \param reference			Reference image
480e5c31af7Sopenharmony_ci * \param result			Result image
481e5c31af7Sopenharmony_ci * \param bestScoreDiff		Scaling factor
482e5c31af7Sopenharmony_ci * \param worstScoreDiff	Scaling factor
483e5c31af7Sopenharmony_ci * \param logMode			Logging mode
484e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
485e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
486e5c31af7Sopenharmony_ciint measurePixelDiffAccuracy (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, int bestScoreDiff, int worstScoreDiff, CompareLogMode logMode)
487e5c31af7Sopenharmony_ci{
488e5c31af7Sopenharmony_ci	return measurePixelDiffAccuracy(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), bestScoreDiff, worstScoreDiff, logMode);
489e5c31af7Sopenharmony_ci}
490e5c31af7Sopenharmony_ci
491e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
492e5c31af7Sopenharmony_ci * Returns the index of float in a float space without denormals
493e5c31af7Sopenharmony_ci * so that:
494e5c31af7Sopenharmony_ci * 1) f(0.0) = 0
495e5c31af7Sopenharmony_ci * 2) f(-0.0) = 0
496e5c31af7Sopenharmony_ci * 3) f(b) = f(a) + 1  <==>  b = nextAfter(a)
497e5c31af7Sopenharmony_ci *
498e5c31af7Sopenharmony_ci * See computeFloatFlushRelaxedULPDiff for details
499e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
500e5c31af7Sopenharmony_cistatic deInt32 getPositionOfIEEEFloatWithoutDenormals (float x)
501e5c31af7Sopenharmony_ci{
502e5c31af7Sopenharmony_ci	DE_ASSERT(!deIsNaN(x)); // not sane
503e5c31af7Sopenharmony_ci
504e5c31af7Sopenharmony_ci	if (x == 0.0f)
505e5c31af7Sopenharmony_ci		return 0;
506e5c31af7Sopenharmony_ci	else if (x < 0.0f)
507e5c31af7Sopenharmony_ci		return -getPositionOfIEEEFloatWithoutDenormals(-x);
508e5c31af7Sopenharmony_ci	else
509e5c31af7Sopenharmony_ci	{
510e5c31af7Sopenharmony_ci		DE_ASSERT(x > 0.0f);
511e5c31af7Sopenharmony_ci
512e5c31af7Sopenharmony_ci		const tcu::Float32 f(x);
513e5c31af7Sopenharmony_ci
514e5c31af7Sopenharmony_ci		if (f.isDenorm())
515e5c31af7Sopenharmony_ci		{
516e5c31af7Sopenharmony_ci			// Denorms are flushed to zero
517e5c31af7Sopenharmony_ci			return 0;
518e5c31af7Sopenharmony_ci		}
519e5c31af7Sopenharmony_ci		else
520e5c31af7Sopenharmony_ci		{
521e5c31af7Sopenharmony_ci			// sign is 0, and it's a normal number. Natural position is its bit
522e5c31af7Sopenharmony_ci			// pattern but since we've collapsed the denorms, we must remove
523e5c31af7Sopenharmony_ci			// the gap here too to keep the float enumeration continuous.
524e5c31af7Sopenharmony_ci			//
525e5c31af7Sopenharmony_ci			// Denormals occupy one exponent pattern. Removing one from
526e5c31af7Sopenharmony_ci			// exponent should to the trick. Add one since the removed range
527e5c31af7Sopenharmony_ci			// contained one representable value, 0.
528e5c31af7Sopenharmony_ci			return (deInt32)(f.bits() - (1u << 23u) + 1u);
529e5c31af7Sopenharmony_ci		}
530e5c31af7Sopenharmony_ci	}
531e5c31af7Sopenharmony_ci}
532e5c31af7Sopenharmony_ci
533e5c31af7Sopenharmony_cistatic deUint32 computeFloatFlushRelaxedULPDiff (float a, float b)
534e5c31af7Sopenharmony_ci{
535e5c31af7Sopenharmony_ci	if (deIsNaN(a) && deIsNaN(b))
536e5c31af7Sopenharmony_ci		return 0;
537e5c31af7Sopenharmony_ci	else if (deIsNaN(a) || deIsNaN(b))
538e5c31af7Sopenharmony_ci	{
539e5c31af7Sopenharmony_ci		return 0xFFFFFFFFu;
540e5c31af7Sopenharmony_ci	}
541e5c31af7Sopenharmony_ci	else
542e5c31af7Sopenharmony_ci	{
543e5c31af7Sopenharmony_ci		// Using the "definition 5" in Muller, Jean-Michel. "On the definition of ulp (x)" (2005)
544e5c31af7Sopenharmony_ci		// assuming a floating point space is IEEE single precision floating point space without
545e5c31af7Sopenharmony_ci		// denormals (and signed zeros).
546e5c31af7Sopenharmony_ci		const deInt32 aIndex = getPositionOfIEEEFloatWithoutDenormals(a);
547e5c31af7Sopenharmony_ci		const deInt32 bIndex = getPositionOfIEEEFloatWithoutDenormals(b);
548e5c31af7Sopenharmony_ci		return (deUint32)de::abs(aIndex - bIndex);
549e5c31af7Sopenharmony_ci	}
550e5c31af7Sopenharmony_ci}
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_cistatic tcu::UVec4 computeFlushRelaxedULPDiff (const tcu::Vec4& a, const tcu::Vec4& b)
553e5c31af7Sopenharmony_ci{
554e5c31af7Sopenharmony_ci	return tcu::UVec4(computeFloatFlushRelaxedULPDiff(a.x(), b.x()),
555e5c31af7Sopenharmony_ci					  computeFloatFlushRelaxedULPDiff(a.y(), b.y()),
556e5c31af7Sopenharmony_ci					  computeFloatFlushRelaxedULPDiff(a.z(), b.z()),
557e5c31af7Sopenharmony_ci					  computeFloatFlushRelaxedULPDiff(a.w(), b.w()));
558e5c31af7Sopenharmony_ci}
559e5c31af7Sopenharmony_ci
560e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
561e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison
562e5c31af7Sopenharmony_ci *
563e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference
564e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value.
565e5c31af7Sopenharmony_ci *
566e5c31af7Sopenharmony_ci * This comparison uses ULP (units in last place) metric for computing the
567e5c31af7Sopenharmony_ci * difference between floating-point values and thus this function can
568e5c31af7Sopenharmony_ci * be used only for comparing floating-point texture data. In ULP calculation
569e5c31af7Sopenharmony_ci * the denormal numbers are allowed to be flushed to zero.
570e5c31af7Sopenharmony_ci *
571e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
572e5c31af7Sopenharmony_ci * are.
573e5c31af7Sopenharmony_ci *
574e5c31af7Sopenharmony_ci * \param log			Test log for results
575e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
576e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
577e5c31af7Sopenharmony_ci * \param reference		Reference image
578e5c31af7Sopenharmony_ci * \param result		Result image
579e5c31af7Sopenharmony_ci * \param threshold		Maximum allowed difference
580e5c31af7Sopenharmony_ci * \param logMode		Logging mode
581e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
582e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
583e5c31af7Sopenharmony_cibool floatUlpThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode)
584e5c31af7Sopenharmony_ci{
585e5c31af7Sopenharmony_ci	int					width				= reference.getWidth();
586e5c31af7Sopenharmony_ci	int					height				= reference.getHeight();
587e5c31af7Sopenharmony_ci	int					depth				= reference.getDepth();
588e5c31af7Sopenharmony_ci	TextureLevel		errorMaskStorage	(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
589e5c31af7Sopenharmony_ci	PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
590e5c31af7Sopenharmony_ci	UVec4				maxDiff				(0, 0, 0, 0);
591e5c31af7Sopenharmony_ci	Vec4				pixelBias			(0.0f, 0.0f, 0.0f, 0.0f);
592e5c31af7Sopenharmony_ci	Vec4				pixelScale			(1.0f, 1.0f, 1.0f, 1.0f);
593e5c31af7Sopenharmony_ci
594e5c31af7Sopenharmony_ci	TCU_CHECK(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
595e5c31af7Sopenharmony_ci
596e5c31af7Sopenharmony_ci	for (int z = 0; z < depth; z++)
597e5c31af7Sopenharmony_ci	{
598e5c31af7Sopenharmony_ci		for (int y = 0; y < height; y++)
599e5c31af7Sopenharmony_ci		{
600e5c31af7Sopenharmony_ci			for (int x = 0; x < width; x++)
601e5c31af7Sopenharmony_ci			{
602e5c31af7Sopenharmony_ci				const Vec4	refPix	= reference.getPixel(x, y, z);
603e5c31af7Sopenharmony_ci				const Vec4	cmpPix	= result.getPixel(x, y, z);
604e5c31af7Sopenharmony_ci				const UVec4	diff	= computeFlushRelaxedULPDiff(refPix, cmpPix);
605e5c31af7Sopenharmony_ci				const bool	isOk	= boolAll(lessThanEqual(diff, threshold));
606e5c31af7Sopenharmony_ci
607e5c31af7Sopenharmony_ci				maxDiff = max(maxDiff, diff);
608e5c31af7Sopenharmony_ci
609e5c31af7Sopenharmony_ci				errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z);
610e5c31af7Sopenharmony_ci			}
611e5c31af7Sopenharmony_ci		}
612e5c31af7Sopenharmony_ci	}
613e5c31af7Sopenharmony_ci
614e5c31af7Sopenharmony_ci	bool compareOk = boolAll(lessThanEqual(maxDiff, threshold));
615e5c31af7Sopenharmony_ci
616e5c31af7Sopenharmony_ci	if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
617e5c31af7Sopenharmony_ci	{
618e5c31af7Sopenharmony_ci		// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
619e5c31af7Sopenharmony_ci		if (tcu::getTextureChannelClass(reference.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
620e5c31af7Sopenharmony_ci			tcu::getTextureChannelClass(result.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
621e5c31af7Sopenharmony_ci		{
622e5c31af7Sopenharmony_ci			computeScaleAndBias(reference, result, pixelScale, pixelBias);
623e5c31af7Sopenharmony_ci			log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
624e5c31af7Sopenharmony_ci		}
625e5c31af7Sopenharmony_ci
626e5c31af7Sopenharmony_ci		if (!compareOk)
627e5c31af7Sopenharmony_ci			log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
628e5c31af7Sopenharmony_ci
629e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
630e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
631e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference,	pixelScale, pixelBias)
632e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
633e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
634e5c31af7Sopenharmony_ci	}
635e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
636e5c31af7Sopenharmony_ci	{
637e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
638e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
641e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
642e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
643e5c31af7Sopenharmony_ci	}
644e5c31af7Sopenharmony_ci
645e5c31af7Sopenharmony_ci	return compareOk;
646e5c31af7Sopenharmony_ci}
647e5c31af7Sopenharmony_ci
648e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
649e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison
650e5c31af7Sopenharmony_ci *
651e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference
652e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value.
653e5c31af7Sopenharmony_ci *
654e5c31af7Sopenharmony_ci * This comparison can be used for floating-point and fixed-point formats.
655e5c31af7Sopenharmony_ci * Difference is computed in floating-point space.
656e5c31af7Sopenharmony_ci *
657e5c31af7Sopenharmony_ci * On failure an error image is generated that shows where the failing
658e5c31af7Sopenharmony_ci * pixels are.
659e5c31af7Sopenharmony_ci *
660e5c31af7Sopenharmony_ci * \param log			Test log for results
661e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
662e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
663e5c31af7Sopenharmony_ci * \param reference		Reference image
664e5c31af7Sopenharmony_ci * \param result		Result image
665e5c31af7Sopenharmony_ci * \param threshold		Maximum allowed difference
666e5c31af7Sopenharmony_ci * \param logMode		Logging mode
667e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
668e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
669e5c31af7Sopenharmony_cibool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode)
670e5c31af7Sopenharmony_ci{
671e5c31af7Sopenharmony_ci	int					width				= reference.getWidth();
672e5c31af7Sopenharmony_ci	int					height				= reference.getHeight();
673e5c31af7Sopenharmony_ci	int					depth				= reference.getDepth();
674e5c31af7Sopenharmony_ci	TextureLevel		errorMaskStorage	(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
675e5c31af7Sopenharmony_ci	PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
676e5c31af7Sopenharmony_ci	Vec4				maxDiff				(0.0f, 0.0f, 0.0f, 0.0f);
677e5c31af7Sopenharmony_ci	Vec4				pixelBias			(0.0f, 0.0f, 0.0f, 0.0f);
678e5c31af7Sopenharmony_ci	Vec4				pixelScale			(1.0f, 1.0f, 1.0f, 1.0f);
679e5c31af7Sopenharmony_ci
680e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
681e5c31af7Sopenharmony_ci
682e5c31af7Sopenharmony_ci	for (int z = 0; z < depth; z++)
683e5c31af7Sopenharmony_ci	{
684e5c31af7Sopenharmony_ci		for (int y = 0; y < height; y++)
685e5c31af7Sopenharmony_ci		{
686e5c31af7Sopenharmony_ci			for (int x = 0; x < width; x++)
687e5c31af7Sopenharmony_ci			{
688e5c31af7Sopenharmony_ci				Vec4	refPix		= reference.getPixel(x, y, z);
689e5c31af7Sopenharmony_ci				Vec4	cmpPix		= result.getPixel(x, y, z);
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ci				Vec4	diff		= abs(refPix - cmpPix);
692e5c31af7Sopenharmony_ci				bool	isOk		= boolAll(lessThanEqual(diff, threshold));
693e5c31af7Sopenharmony_ci
694e5c31af7Sopenharmony_ci				maxDiff = max(maxDiff, diff);
695e5c31af7Sopenharmony_ci
696e5c31af7Sopenharmony_ci				errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z);
697e5c31af7Sopenharmony_ci			}
698e5c31af7Sopenharmony_ci		}
699e5c31af7Sopenharmony_ci	}
700e5c31af7Sopenharmony_ci
701e5c31af7Sopenharmony_ci	bool compareOk = boolAll(lessThanEqual(maxDiff, threshold));
702e5c31af7Sopenharmony_ci
703e5c31af7Sopenharmony_ci	if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
704e5c31af7Sopenharmony_ci	{
705e5c31af7Sopenharmony_ci		// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
706e5c31af7Sopenharmony_ci		if (tcu::getTextureChannelClass(reference.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
707e5c31af7Sopenharmony_ci			tcu::getTextureChannelClass(result.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
708e5c31af7Sopenharmony_ci		{
709e5c31af7Sopenharmony_ci			computeScaleAndBias(reference, result, pixelScale, pixelBias);
710e5c31af7Sopenharmony_ci			log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
711e5c31af7Sopenharmony_ci		}
712e5c31af7Sopenharmony_ci
713e5c31af7Sopenharmony_ci		if (!compareOk)
714e5c31af7Sopenharmony_ci			log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
715e5c31af7Sopenharmony_ci
716e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
717e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
718e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference,	pixelScale, pixelBias)
719e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
720e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
721e5c31af7Sopenharmony_ci	}
722e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
723e5c31af7Sopenharmony_ci	{
724e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
725e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
726e5c31af7Sopenharmony_ci
727e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
728e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
729e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
730e5c31af7Sopenharmony_ci	}
731e5c31af7Sopenharmony_ci
732e5c31af7Sopenharmony_ci	return compareOk;
733e5c31af7Sopenharmony_ci}
734e5c31af7Sopenharmony_ci
735e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
736e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison with ignore key
737e5c31af7Sopenharmony_ci *
738e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference
739e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value.
740e5c31af7Sopenharmony_ci *
741e5c31af7Sopenharmony_ci * Any pixels in reference that match the ignore key are ignored.
742e5c31af7Sopenharmony_ci *
743e5c31af7Sopenharmony_ci * This comparison can be used for floating-point and fixed-point formats.
744e5c31af7Sopenharmony_ci * Difference is computed in floating-point space.
745e5c31af7Sopenharmony_ci *
746e5c31af7Sopenharmony_ci * On failure an error image is generated that shows where the failing
747e5c31af7Sopenharmony_ci * pixels are.
748e5c31af7Sopenharmony_ci *
749e5c31af7Sopenharmony_ci * \param log			Test log for results
750e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
751e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
752e5c31af7Sopenharmony_ci * \param reference		Reference image
753e5c31af7Sopenharmony_ci * \param result		Result image
754e5c31af7Sopenharmony_ci * \param ignorekey     Ignore key
755e5c31af7Sopenharmony_ci * \param threshold		Maximum allowed difference
756e5c31af7Sopenharmony_ci * \param logMode		Logging mode
757e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
758e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
759e5c31af7Sopenharmony_cibool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const Vec4& ignorekey, const Vec4& threshold, CompareLogMode logMode)
760e5c31af7Sopenharmony_ci{
761e5c31af7Sopenharmony_ci	int					width = reference.getWidth();
762e5c31af7Sopenharmony_ci	int					height = reference.getHeight();
763e5c31af7Sopenharmony_ci	int					depth = reference.getDepth();
764e5c31af7Sopenharmony_ci	TextureLevel		errorMaskStorage(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
765e5c31af7Sopenharmony_ci	PixelBufferAccess	errorMask = errorMaskStorage.getAccess();
766e5c31af7Sopenharmony_ci	Vec4				maxDiff(0.0f, 0.0f, 0.0f, 0.0f);
767e5c31af7Sopenharmony_ci	Vec4				pixelBias(0.0f, 0.0f, 0.0f, 0.0f);
768e5c31af7Sopenharmony_ci	Vec4				pixelScale(1.0f, 1.0f, 1.0f, 1.0f);
769e5c31af7Sopenharmony_ci
770e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
771e5c31af7Sopenharmony_ci
772e5c31af7Sopenharmony_ci	for (int z = 0; z < depth; z++)
773e5c31af7Sopenharmony_ci	{
774e5c31af7Sopenharmony_ci		for (int y = 0; y < height; y++)
775e5c31af7Sopenharmony_ci		{
776e5c31af7Sopenharmony_ci			for (int x = 0; x < width; x++)
777e5c31af7Sopenharmony_ci			{
778e5c31af7Sopenharmony_ci				Vec4	refPix = reference.getPixel(x, y, z);
779e5c31af7Sopenharmony_ci				Vec4	cmpPix = result.getPixel(x, y, z);
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci				if (refPix != ignorekey)
782e5c31af7Sopenharmony_ci				{
783e5c31af7Sopenharmony_ci
784e5c31af7Sopenharmony_ci					Vec4	diff = abs(refPix - cmpPix);
785e5c31af7Sopenharmony_ci					bool	isOk = boolAll(lessThanEqual(diff, threshold));
786e5c31af7Sopenharmony_ci
787e5c31af7Sopenharmony_ci					maxDiff = max(maxDiff, diff);
788e5c31af7Sopenharmony_ci
789e5c31af7Sopenharmony_ci					errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z);
790e5c31af7Sopenharmony_ci				}
791e5c31af7Sopenharmony_ci			}
792e5c31af7Sopenharmony_ci		}
793e5c31af7Sopenharmony_ci	}
794e5c31af7Sopenharmony_ci
795e5c31af7Sopenharmony_ci	bool compareOk = boolAll(lessThanEqual(maxDiff, threshold));
796e5c31af7Sopenharmony_ci
797e5c31af7Sopenharmony_ci	if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
798e5c31af7Sopenharmony_ci	{
799e5c31af7Sopenharmony_ci		// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
800e5c31af7Sopenharmony_ci		if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
801e5c31af7Sopenharmony_ci			tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
802e5c31af7Sopenharmony_ci		{
803e5c31af7Sopenharmony_ci			computeScaleAndBias(reference, result, pixelScale, pixelBias);
804e5c31af7Sopenharmony_ci			log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
805e5c31af7Sopenharmony_ci		}
806e5c31af7Sopenharmony_ci
807e5c31af7Sopenharmony_ci		if (!compareOk)
808e5c31af7Sopenharmony_ci			log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
809e5c31af7Sopenharmony_ci
810e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
811e5c31af7Sopenharmony_ci			<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
812e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
813e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask", "Error mask", errorMask)
814e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
815e5c31af7Sopenharmony_ci	}
816e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
817e5c31af7Sopenharmony_ci	{
818e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
819e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
820e5c31af7Sopenharmony_ci
821e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
822e5c31af7Sopenharmony_ci			<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
823e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
824e5c31af7Sopenharmony_ci	}
825e5c31af7Sopenharmony_ci
826e5c31af7Sopenharmony_ci	return compareOk;
827e5c31af7Sopenharmony_ci}
828e5c31af7Sopenharmony_ci
829e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
830e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison
831e5c31af7Sopenharmony_ci *
832e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference
833e5c31af7Sopenharmony_ci * color. Comparison fails if any pixels exceed the given threshold value.
834e5c31af7Sopenharmony_ci *
835e5c31af7Sopenharmony_ci * This comparison can be used for floating-point and fixed-point formats.
836e5c31af7Sopenharmony_ci * Difference is computed in floating-point space.
837e5c31af7Sopenharmony_ci *
838e5c31af7Sopenharmony_ci * On failure an error image is generated that shows where the failing
839e5c31af7Sopenharmony_ci * pixels are.
840e5c31af7Sopenharmony_ci *
841e5c31af7Sopenharmony_ci * \param log			Test log for results
842e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
843e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
844e5c31af7Sopenharmony_ci * \param reference		Reference color
845e5c31af7Sopenharmony_ci * \param result		Result image
846e5c31af7Sopenharmony_ci * \param threshold		Maximum allowed difference
847e5c31af7Sopenharmony_ci * \param logMode		Logging mode
848e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
849e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
850e5c31af7Sopenharmony_cibool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Vec4& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode)
851e5c31af7Sopenharmony_ci{
852e5c31af7Sopenharmony_ci	const int			width				= result.getWidth();
853e5c31af7Sopenharmony_ci	const int			height				= result.getHeight();
854e5c31af7Sopenharmony_ci	const int			depth				= result.getDepth();
855e5c31af7Sopenharmony_ci
856e5c31af7Sopenharmony_ci	TextureLevel		errorMaskStorage	(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
857e5c31af7Sopenharmony_ci	PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
858e5c31af7Sopenharmony_ci	Vec4				maxDiff				(0.0f, 0.0f, 0.0f, 0.0f);
859e5c31af7Sopenharmony_ci	Vec4				pixelBias			(0.0f, 0.0f, 0.0f, 0.0f);
860e5c31af7Sopenharmony_ci	Vec4				pixelScale			(1.0f, 1.0f, 1.0f, 1.0f);
861e5c31af7Sopenharmony_ci
862e5c31af7Sopenharmony_ci	for (int z = 0; z < depth; z++)
863e5c31af7Sopenharmony_ci	{
864e5c31af7Sopenharmony_ci		for (int y = 0; y < height; y++)
865e5c31af7Sopenharmony_ci		{
866e5c31af7Sopenharmony_ci			for (int x = 0; x < width; x++)
867e5c31af7Sopenharmony_ci			{
868e5c31af7Sopenharmony_ci				const Vec4	cmpPix		= result.getPixel(x, y, z);
869e5c31af7Sopenharmony_ci				const Vec4	diff		= abs(reference - cmpPix);
870e5c31af7Sopenharmony_ci				const bool	isOk		= boolAll(lessThanEqual(diff, threshold));
871e5c31af7Sopenharmony_ci
872e5c31af7Sopenharmony_ci				maxDiff = max(maxDiff, diff);
873e5c31af7Sopenharmony_ci
874e5c31af7Sopenharmony_ci				if (isOk)
875e5c31af7Sopenharmony_ci					errorMask.setPixel(Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y, z);
876e5c31af7Sopenharmony_ci				else
877e5c31af7Sopenharmony_ci					errorMask.setPixel(Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z);
878e5c31af7Sopenharmony_ci			}
879e5c31af7Sopenharmony_ci		}
880e5c31af7Sopenharmony_ci	}
881e5c31af7Sopenharmony_ci
882e5c31af7Sopenharmony_ci	bool compareOk = boolAll(lessThanEqual(maxDiff, threshold));
883e5c31af7Sopenharmony_ci
884e5c31af7Sopenharmony_ci	if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
885e5c31af7Sopenharmony_ci	{
886e5c31af7Sopenharmony_ci		// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
887e5c31af7Sopenharmony_ci		if (tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
888e5c31af7Sopenharmony_ci		{
889e5c31af7Sopenharmony_ci			computeScaleAndBias(result, result, pixelScale, pixelBias);
890e5c31af7Sopenharmony_ci			log << TestLog::Message << "Result image is normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
891e5c31af7Sopenharmony_ci		}
892e5c31af7Sopenharmony_ci
893e5c31af7Sopenharmony_ci		if (!compareOk)
894e5c31af7Sopenharmony_ci			log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << ", reference = " << reference << TestLog::EndMessage;
895e5c31af7Sopenharmony_ci
896e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
897e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
898e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
899e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
900e5c31af7Sopenharmony_ci	}
901e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
902e5c31af7Sopenharmony_ci	{
903e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
904e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
905e5c31af7Sopenharmony_ci
906e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
907e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
908e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
909e5c31af7Sopenharmony_ci	}
910e5c31af7Sopenharmony_ci
911e5c31af7Sopenharmony_ci	return compareOk;
912e5c31af7Sopenharmony_ci}
913e5c31af7Sopenharmony_ci
914e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
915e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison
916e5c31af7Sopenharmony_ci *
917e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference
918e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value.
919e5c31af7Sopenharmony_ci *
920e5c31af7Sopenharmony_ci * This comparison can be used for integer- and fixed-point texture formats.
921e5c31af7Sopenharmony_ci * Difference is computed in integer space.
922e5c31af7Sopenharmony_ci *
923e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
924e5c31af7Sopenharmony_ci * are.
925e5c31af7Sopenharmony_ci *
926e5c31af7Sopenharmony_ci * \param log			Test log for results
927e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
928e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
929e5c31af7Sopenharmony_ci * \param reference		Reference image
930e5c31af7Sopenharmony_ci * \param result		Result image
931e5c31af7Sopenharmony_ci * \param threshold		Maximum allowed difference
932e5c31af7Sopenharmony_ci * \param logMode		Logging mode
933e5c31af7Sopenharmony_ci * \param use64Bits		Use 64-bit components when reading image data.
934e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
935e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
936e5c31af7Sopenharmony_cibool intThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode, bool use64Bits)
937e5c31af7Sopenharmony_ci{
938e5c31af7Sopenharmony_ci	int					width				= reference.getWidth();
939e5c31af7Sopenharmony_ci	int					height				= reference.getHeight();
940e5c31af7Sopenharmony_ci	int					depth				= reference.getDepth();
941e5c31af7Sopenharmony_ci	TextureLevel		errorMaskStorage	(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
942e5c31af7Sopenharmony_ci	PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
943e5c31af7Sopenharmony_ci	U64Vec4				maxDiff				(0u, 0u, 0u, 0u);
944e5c31af7Sopenharmony_ci	U64Vec4				diff				(0u, 0u, 0u, 0u);
945e5c31af7Sopenharmony_ci	const U64Vec4		threshold64			= threshold.cast<deUint64>();
946e5c31af7Sopenharmony_ci	Vec4				pixelBias			(0.0f, 0.0f, 0.0f, 0.0f);
947e5c31af7Sopenharmony_ci	Vec4				pixelScale			(1.0f, 1.0f, 1.0f, 1.0f);
948e5c31af7Sopenharmony_ci
949e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
950e5c31af7Sopenharmony_ci
951e5c31af7Sopenharmony_ci	for (int z = 0; z < depth; z++)
952e5c31af7Sopenharmony_ci	{
953e5c31af7Sopenharmony_ci		for (int y = 0; y < height; y++)
954e5c31af7Sopenharmony_ci		{
955e5c31af7Sopenharmony_ci			for (int x = 0; x < width; x++)
956e5c31af7Sopenharmony_ci			{
957e5c31af7Sopenharmony_ci				if (use64Bits)
958e5c31af7Sopenharmony_ci				{
959e5c31af7Sopenharmony_ci					I64Vec4	refPix	= reference.getPixelInt64(x, y, z);
960e5c31af7Sopenharmony_ci					I64Vec4	cmpPix	= result.getPixelInt64(x, y, z);
961e5c31af7Sopenharmony_ci					diff			= abs(refPix - cmpPix).cast<deUint64>();
962e5c31af7Sopenharmony_ci				}
963e5c31af7Sopenharmony_ci				else
964e5c31af7Sopenharmony_ci				{
965e5c31af7Sopenharmony_ci					IVec4	refPix	= reference.getPixelInt(x, y, z);
966e5c31af7Sopenharmony_ci					IVec4	cmpPix	= result.getPixelInt(x, y, z);
967e5c31af7Sopenharmony_ci					diff			= abs(refPix - cmpPix).cast<deUint64>();
968e5c31af7Sopenharmony_ci				}
969e5c31af7Sopenharmony_ci
970e5c31af7Sopenharmony_ci				maxDiff = max(maxDiff, diff);
971e5c31af7Sopenharmony_ci
972e5c31af7Sopenharmony_ci				const bool isOk = boolAll(lessThanEqual(diff, threshold64));
973e5c31af7Sopenharmony_ci				errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z);
974e5c31af7Sopenharmony_ci			}
975e5c31af7Sopenharmony_ci		}
976e5c31af7Sopenharmony_ci	}
977e5c31af7Sopenharmony_ci
978e5c31af7Sopenharmony_ci	bool compareOk = boolAll(lessThanEqual(maxDiff, threshold64));
979e5c31af7Sopenharmony_ci
980e5c31af7Sopenharmony_ci	if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
981e5c31af7Sopenharmony_ci	{
982e5c31af7Sopenharmony_ci		{
983e5c31af7Sopenharmony_ci			const auto refChannelClass = tcu::getTextureChannelClass(reference.getFormat().type);
984e5c31af7Sopenharmony_ci			const auto resChannelClass = tcu::getTextureChannelClass(result.getFormat().type);
985e5c31af7Sopenharmony_ci
986e5c31af7Sopenharmony_ci			const bool refIsUint8 = (reference.getFormat().type == TextureFormat::UNSIGNED_INT8);
987e5c31af7Sopenharmony_ci			const bool resIsUint8 = (result.getFormat().type == TextureFormat::UNSIGNED_INT8);
988e5c31af7Sopenharmony_ci
989e5c31af7Sopenharmony_ci			const bool calcScaleBias = ((refChannelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT && !refIsUint8) ||
990e5c31af7Sopenharmony_ci				(resChannelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT && !resIsUint8));
991e5c31af7Sopenharmony_ci
992e5c31af7Sopenharmony_ci			// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
993e5c31af7Sopenharmony_ci			if (calcScaleBias)
994e5c31af7Sopenharmony_ci			{
995e5c31af7Sopenharmony_ci				computeScaleAndBias(reference, result, pixelScale, pixelBias);
996e5c31af7Sopenharmony_ci				log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
997e5c31af7Sopenharmony_ci			}
998e5c31af7Sopenharmony_ci		}
999e5c31af7Sopenharmony_ci
1000e5c31af7Sopenharmony_ci		if (!compareOk)
1001e5c31af7Sopenharmony_ci			log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
1002e5c31af7Sopenharmony_ci
1003e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1004e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
1005e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference,	pixelScale, pixelBias)
1006e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
1007e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1008e5c31af7Sopenharmony_ci	}
1009e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
1010e5c31af7Sopenharmony_ci	{
1011e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
1012e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
1013e5c31af7Sopenharmony_ci
1014e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1015e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
1016e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1017e5c31af7Sopenharmony_ci	}
1018e5c31af7Sopenharmony_ci
1019e5c31af7Sopenharmony_ci	return compareOk;
1020e5c31af7Sopenharmony_ci}
1021e5c31af7Sopenharmony_ci
1022e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1023e5c31af7Sopenharmony_ci * \brief Per-pixel depth/stencil threshold-based comparison
1024e5c31af7Sopenharmony_ci *
1025e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference
1026e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value.
1027e5c31af7Sopenharmony_ci *
1028e5c31af7Sopenharmony_ci * This comparison can be used for depth and depth/stencil images.
1029e5c31af7Sopenharmony_ci * Difference is computed in integer space.
1030e5c31af7Sopenharmony_ci *
1031e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
1032e5c31af7Sopenharmony_ci * are.
1033e5c31af7Sopenharmony_ci *
1034e5c31af7Sopenharmony_ci * \param log			Test log for results
1035e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
1036e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
1037e5c31af7Sopenharmony_ci * \param reference		Reference image
1038e5c31af7Sopenharmony_ci * \param result		Result image
1039e5c31af7Sopenharmony_ci * \param threshold		Maximum allowed depth difference (stencil must be exact)
1040e5c31af7Sopenharmony_ci * \param logMode		Logging mode
1041e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
1042e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1043e5c31af7Sopenharmony_cibool dsThresholdCompare(TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const float threshold, CompareLogMode logMode)
1044e5c31af7Sopenharmony_ci{
1045e5c31af7Sopenharmony_ci	int					width = reference.getWidth();
1046e5c31af7Sopenharmony_ci	int					height = reference.getHeight();
1047e5c31af7Sopenharmony_ci	int					depth = reference.getDepth();
1048e5c31af7Sopenharmony_ci	TextureLevel		errorMaskStorage(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
1049e5c31af7Sopenharmony_ci	PixelBufferAccess	errorMask = errorMaskStorage.getAccess();
1050e5c31af7Sopenharmony_ci	float				maxDiff = 0.0;
1051e5c31af7Sopenharmony_ci	bool				allStencilOk = true;
1052e5c31af7Sopenharmony_ci	bool				hasDepth = tcu::hasDepthComponent(result.getFormat().order);
1053e5c31af7Sopenharmony_ci	bool				hasStencil = tcu::hasStencilComponent(result.getFormat().order);
1054e5c31af7Sopenharmony_ci
1055e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
1056e5c31af7Sopenharmony_ci
1057e5c31af7Sopenharmony_ci	for (int z = 0; z < depth; z++)
1058e5c31af7Sopenharmony_ci	{
1059e5c31af7Sopenharmony_ci		for (int y = 0; y < height; y++)
1060e5c31af7Sopenharmony_ci		{
1061e5c31af7Sopenharmony_ci			for (int x = 0; x < width; x++)
1062e5c31af7Sopenharmony_ci			{
1063e5c31af7Sopenharmony_ci				bool	isOk = true;
1064e5c31af7Sopenharmony_ci
1065e5c31af7Sopenharmony_ci				if (hasDepth)
1066e5c31af7Sopenharmony_ci				{
1067e5c31af7Sopenharmony_ci					float refDepth	= reference.getPixDepth(x, y, z);
1068e5c31af7Sopenharmony_ci					float cmpDepth	= result.getPixDepth(x, y, z);
1069e5c31af7Sopenharmony_ci					float diff		= de::abs(refDepth - cmpDepth);
1070e5c31af7Sopenharmony_ci
1071e5c31af7Sopenharmony_ci					isOk = diff <= threshold;
1072e5c31af7Sopenharmony_ci					maxDiff = (float) deMax(maxDiff, diff);
1073e5c31af7Sopenharmony_ci				}
1074e5c31af7Sopenharmony_ci
1075e5c31af7Sopenharmony_ci				if (hasStencil)
1076e5c31af7Sopenharmony_ci				{
1077e5c31af7Sopenharmony_ci					deUint8 refStencil = (deUint8) reference.getPixStencil(x, y, z);
1078e5c31af7Sopenharmony_ci					deUint8 cmpStencil = (deUint8) result.getPixStencil(x, y, z);
1079e5c31af7Sopenharmony_ci
1080e5c31af7Sopenharmony_ci					bool isStencilOk = (refStencil == cmpStencil);
1081e5c31af7Sopenharmony_ci					allStencilOk = allStencilOk && isStencilOk;
1082e5c31af7Sopenharmony_ci					isOk = isOk && isStencilOk;
1083e5c31af7Sopenharmony_ci				}
1084e5c31af7Sopenharmony_ci
1085e5c31af7Sopenharmony_ci				errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z);
1086e5c31af7Sopenharmony_ci			}
1087e5c31af7Sopenharmony_ci		}
1088e5c31af7Sopenharmony_ci	}
1089e5c31af7Sopenharmony_ci
1090e5c31af7Sopenharmony_ci	bool compareOk = (maxDiff <= threshold) && allStencilOk;
1091e5c31af7Sopenharmony_ci
1092e5c31af7Sopenharmony_ci	if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
1093e5c31af7Sopenharmony_ci	{
1094e5c31af7Sopenharmony_ci		if (!compareOk)
1095e5c31af7Sopenharmony_ci		{
1096e5c31af7Sopenharmony_ci			if (maxDiff > threshold)
1097e5c31af7Sopenharmony_ci				log << TestLog::Message << "Depth comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
1098e5c31af7Sopenharmony_ci			if (!allStencilOk)
1099e5c31af7Sopenharmony_ci				log << TestLog::Message << "Stencil comparison failed" << TestLog::EndMessage;
1100e5c31af7Sopenharmony_ci		}
1101e5c31af7Sopenharmony_ci
1102e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1103e5c31af7Sopenharmony_ci			// TODO: Convert depth/stencil buffers into separate depth & stencil for logging?
1104e5c31af7Sopenharmony_ci//			<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
1105e5c31af7Sopenharmony_ci//			<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
1106e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask", "Error mask", errorMask)
1107e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1108e5c31af7Sopenharmony_ci	}
1109e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
1110e5c31af7Sopenharmony_ci	{
1111e5c31af7Sopenharmony_ci#if 0
1112e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
1113e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
1114e5c31af7Sopenharmony_ci
1115e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1116e5c31af7Sopenharmony_ci			<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
1117e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1118e5c31af7Sopenharmony_ci#endif
1119e5c31af7Sopenharmony_ci	}
1120e5c31af7Sopenharmony_ci
1121e5c31af7Sopenharmony_ci	return compareOk;
1122e5c31af7Sopenharmony_ci}
1123e5c31af7Sopenharmony_ci
1124e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1125e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based deviation-ignoring comparison
1126e5c31af7Sopenharmony_ci *
1127e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference
1128e5c31af7Sopenharmony_ci * image. Comparison fails if there is no pixel matching the given threshold
1129e5c31af7Sopenharmony_ci * value in the search volume.
1130e5c31af7Sopenharmony_ci *
1131e5c31af7Sopenharmony_ci * If the search volume contains out-of-bounds pixels, comparison can be set
1132e5c31af7Sopenharmony_ci * to either ignore these pixels in search or to accept any pixel that has
1133e5c31af7Sopenharmony_ci * out-of-bounds pixels in its search volume.
1134e5c31af7Sopenharmony_ci *
1135e5c31af7Sopenharmony_ci * This comparison can be used for integer- and fixed-point texture formats.
1136e5c31af7Sopenharmony_ci * Difference is computed in integer space.
1137e5c31af7Sopenharmony_ci *
1138e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
1139e5c31af7Sopenharmony_ci * are.
1140e5c31af7Sopenharmony_ci *
1141e5c31af7Sopenharmony_ci * \param log							Test log for results
1142e5c31af7Sopenharmony_ci * \param imageSetName					Name for image set when logging results
1143e5c31af7Sopenharmony_ci * \param imageSetDesc					Description for image set
1144e5c31af7Sopenharmony_ci * \param reference						Reference image
1145e5c31af7Sopenharmony_ci * \param result						Result image
1146e5c31af7Sopenharmony_ci * \param threshold						Maximum allowed difference
1147e5c31af7Sopenharmony_ci * \param maxPositionDeviation			Maximum allowed distance in the search
1148e5c31af7Sopenharmony_ci *										volume.
1149e5c31af7Sopenharmony_ci * \param acceptOutOfBoundsAsAnyValue	Accept any pixel in the boundary region
1150e5c31af7Sopenharmony_ci * \param logMode						Logging mode
1151e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
1152e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1153e5c31af7Sopenharmony_cibool 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)
1154e5c31af7Sopenharmony_ci{
1155e5c31af7Sopenharmony_ci	const int			width				= reference.getWidth();
1156e5c31af7Sopenharmony_ci	const int			height				= reference.getHeight();
1157e5c31af7Sopenharmony_ci	const int			depth				= reference.getDepth();
1158e5c31af7Sopenharmony_ci	TextureLevel		errorMaskStorage	(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
1159e5c31af7Sopenharmony_ci	PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
1160e5c31af7Sopenharmony_ci	const int			numFailingPixels	= findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue);
1161e5c31af7Sopenharmony_ci	const bool			compareOk			= numFailingPixels == 0;
1162e5c31af7Sopenharmony_ci	Vec4				pixelBias			(0.0f, 0.0f, 0.0f, 0.0f);
1163e5c31af7Sopenharmony_ci	Vec4				pixelScale			(1.0f, 1.0f, 1.0f, 1.0f);
1164e5c31af7Sopenharmony_ci
1165e5c31af7Sopenharmony_ci	if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
1166e5c31af7Sopenharmony_ci	{
1167e5c31af7Sopenharmony_ci		// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
1168e5c31af7Sopenharmony_ci		if (tcu::getTextureChannelClass(reference.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1169e5c31af7Sopenharmony_ci			tcu::getTextureChannelClass(result.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
1170e5c31af7Sopenharmony_ci		{
1171e5c31af7Sopenharmony_ci			computeScaleAndBias(reference, result, pixelScale, pixelBias);
1172e5c31af7Sopenharmony_ci			log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
1173e5c31af7Sopenharmony_ci		}
1174e5c31af7Sopenharmony_ci
1175e5c31af7Sopenharmony_ci		if (!compareOk)
1176e5c31af7Sopenharmony_ci			log	<< TestLog::Message
1177e5c31af7Sopenharmony_ci				<< "Image comparison failed:\n"
1178e5c31af7Sopenharmony_ci				<< "\tallowed position deviation = " << maxPositionDeviation << "\n"
1179e5c31af7Sopenharmony_ci				<< "\tcolor threshold = " << threshold
1180e5c31af7Sopenharmony_ci				<< TestLog::EndMessage;
1181e5c31af7Sopenharmony_ci
1182e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1183e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
1184e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference,	pixelScale, pixelBias)
1185e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
1186e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1187e5c31af7Sopenharmony_ci	}
1188e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
1189e5c31af7Sopenharmony_ci	{
1190e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
1191e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
1192e5c31af7Sopenharmony_ci
1193e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1194e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
1195e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1196e5c31af7Sopenharmony_ci	}
1197e5c31af7Sopenharmony_ci
1198e5c31af7Sopenharmony_ci	return compareOk;
1199e5c31af7Sopenharmony_ci}
1200e5c31af7Sopenharmony_ci
1201e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1202e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based deviation-ignoring comparison
1203e5c31af7Sopenharmony_ci *
1204e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference
1205e5c31af7Sopenharmony_ci * image. Pixel fails the test if there is no pixel matching the given
1206e5c31af7Sopenharmony_ci * threshold value in the search volume. Comparison fails if the number of
1207e5c31af7Sopenharmony_ci * failing pixels exceeds the given limit.
1208e5c31af7Sopenharmony_ci *
1209e5c31af7Sopenharmony_ci * If the search volume contains out-of-bounds pixels, comparison can be set
1210e5c31af7Sopenharmony_ci * to either ignore these pixels in search or to accept any pixel that has
1211e5c31af7Sopenharmony_ci * out-of-bounds pixels in its search volume.
1212e5c31af7Sopenharmony_ci *
1213e5c31af7Sopenharmony_ci * This comparison can be used for integer- and fixed-point texture formats.
1214e5c31af7Sopenharmony_ci * Difference is computed in integer space.
1215e5c31af7Sopenharmony_ci *
1216e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
1217e5c31af7Sopenharmony_ci * are.
1218e5c31af7Sopenharmony_ci *
1219e5c31af7Sopenharmony_ci * \param log							Test log for results
1220e5c31af7Sopenharmony_ci * \param imageSetName					Name for image set when logging results
1221e5c31af7Sopenharmony_ci * \param imageSetDesc					Description for image set
1222e5c31af7Sopenharmony_ci * \param reference						Reference image
1223e5c31af7Sopenharmony_ci * \param result						Result image
1224e5c31af7Sopenharmony_ci * \param threshold						Maximum allowed difference
1225e5c31af7Sopenharmony_ci * \param maxPositionDeviation			Maximum allowed distance in the search
1226e5c31af7Sopenharmony_ci *										volume.
1227e5c31af7Sopenharmony_ci * \param acceptOutOfBoundsAsAnyValue	Accept any pixel in the boundary region
1228e5c31af7Sopenharmony_ci * \param maxAllowedFailingPixels		Maximum number of failing pixels
1229e5c31af7Sopenharmony_ci * \param logMode						Logging mode
1230e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
1231e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1232e5c31af7Sopenharmony_cibool 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)
1233e5c31af7Sopenharmony_ci{
1234e5c31af7Sopenharmony_ci	const int			width				= reference.getWidth();
1235e5c31af7Sopenharmony_ci	const int			height				= reference.getHeight();
1236e5c31af7Sopenharmony_ci	const int			depth				= reference.getDepth();
1237e5c31af7Sopenharmony_ci	TextureLevel		errorMaskStorage	(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
1238e5c31af7Sopenharmony_ci	PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
1239e5c31af7Sopenharmony_ci	const int			numFailingPixels	= findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue);
1240e5c31af7Sopenharmony_ci	const bool			compareOk			= numFailingPixels <= maxAllowedFailingPixels;
1241e5c31af7Sopenharmony_ci	Vec4				pixelBias			(0.0f, 0.0f, 0.0f, 0.0f);
1242e5c31af7Sopenharmony_ci	Vec4				pixelScale			(1.0f, 1.0f, 1.0f, 1.0f);
1243e5c31af7Sopenharmony_ci
1244e5c31af7Sopenharmony_ci	if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
1245e5c31af7Sopenharmony_ci	{
1246e5c31af7Sopenharmony_ci		// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
1247e5c31af7Sopenharmony_ci		if (tcu::getTextureChannelClass(reference.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1248e5c31af7Sopenharmony_ci			tcu::getTextureChannelClass(result.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
1249e5c31af7Sopenharmony_ci		{
1250e5c31af7Sopenharmony_ci			computeScaleAndBias(reference, result, pixelScale, pixelBias);
1251e5c31af7Sopenharmony_ci			log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
1252e5c31af7Sopenharmony_ci		}
1253e5c31af7Sopenharmony_ci
1254e5c31af7Sopenharmony_ci		if (!compareOk)
1255e5c31af7Sopenharmony_ci			log	<< TestLog::Message
1256e5c31af7Sopenharmony_ci				<< "Image comparison failed:\n"
1257e5c31af7Sopenharmony_ci				<< "\tallowed position deviation = " << maxPositionDeviation << "\n"
1258e5c31af7Sopenharmony_ci				<< "\tcolor threshold = " << threshold
1259e5c31af7Sopenharmony_ci				<< TestLog::EndMessage;
1260e5c31af7Sopenharmony_ci		log << TestLog::Message << "Number of failing pixels = " << numFailingPixels << ", max allowed = " << maxAllowedFailingPixels << TestLog::EndMessage;
1261e5c31af7Sopenharmony_ci
1262e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1263e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
1264e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference,	pixelScale, pixelBias)
1265e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
1266e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1267e5c31af7Sopenharmony_ci	}
1268e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
1269e5c31af7Sopenharmony_ci	{
1270e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
1271e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
1272e5c31af7Sopenharmony_ci
1273e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1274e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
1275e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1276e5c31af7Sopenharmony_ci	}
1277e5c31af7Sopenharmony_ci
1278e5c31af7Sopenharmony_ci	return compareOk;
1279e5c31af7Sopenharmony_ci}
1280e5c31af7Sopenharmony_ci
1281e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1282e5c31af7Sopenharmony_ci * \brief Per-pixel threshold-based comparison
1283e5c31af7Sopenharmony_ci *
1284e5c31af7Sopenharmony_ci * This compare computes per-pixel differences between result and reference
1285e5c31af7Sopenharmony_ci * image. Comparison fails if any pixels exceed the given threshold value.
1286e5c31af7Sopenharmony_ci *
1287e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
1288e5c31af7Sopenharmony_ci * are.
1289e5c31af7Sopenharmony_ci *
1290e5c31af7Sopenharmony_ci * \param log			Test log for results
1291e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
1292e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
1293e5c31af7Sopenharmony_ci * \param reference		Reference image
1294e5c31af7Sopenharmony_ci * \param result		Result image
1295e5c31af7Sopenharmony_ci * \param threshold		Maximum allowed difference
1296e5c31af7Sopenharmony_ci * \param logMode		Logging mode
1297e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
1298e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1299e5c31af7Sopenharmony_cibool pixelThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, const RGBA& threshold, CompareLogMode logMode)
1300e5c31af7Sopenharmony_ci{
1301e5c31af7Sopenharmony_ci	return intThresholdCompare(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold.toIVec().cast<deUint32>(), logMode);
1302e5c31af7Sopenharmony_ci}
1303e5c31af7Sopenharmony_ci
1304e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1305e5c31af7Sopenharmony_ci * \brief Bilinear image comparison
1306e5c31af7Sopenharmony_ci *
1307e5c31af7Sopenharmony_ci * \todo [pyry] Describe
1308e5c31af7Sopenharmony_ci *
1309e5c31af7Sopenharmony_ci * On failure error image is generated that shows where the failing pixels
1310e5c31af7Sopenharmony_ci * are.
1311e5c31af7Sopenharmony_ci *
1312e5c31af7Sopenharmony_ci * \note				Currently supports only RGBA, UNORM_INT8 formats
1313e5c31af7Sopenharmony_ci * \param log			Test log for results
1314e5c31af7Sopenharmony_ci * \param imageSetName	Name for image set when logging results
1315e5c31af7Sopenharmony_ci * \param imageSetDesc	Description for image set
1316e5c31af7Sopenharmony_ci * \param reference		Reference image
1317e5c31af7Sopenharmony_ci * \param result		Result image
1318e5c31af7Sopenharmony_ci * \param threshold		Maximum local difference
1319e5c31af7Sopenharmony_ci * \param logMode		Logging mode
1320e5c31af7Sopenharmony_ci * \return true if comparison passes, false otherwise
1321e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1322e5c31af7Sopenharmony_cibool bilinearCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const RGBA threshold, CompareLogMode logMode)
1323e5c31af7Sopenharmony_ci{
1324e5c31af7Sopenharmony_ci	TextureLevel		errorMask		(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight());
1325e5c31af7Sopenharmony_ci	bool				isOk			= bilinearCompare(reference, result, errorMask, threshold);
1326e5c31af7Sopenharmony_ci	Vec4				pixelBias		(0.0f, 0.0f, 0.0f, 0.0f);
1327e5c31af7Sopenharmony_ci	Vec4				pixelScale		(1.0f, 1.0f, 1.0f, 1.0f);
1328e5c31af7Sopenharmony_ci
1329e5c31af7Sopenharmony_ci	if (!isOk || logMode == COMPARE_LOG_EVERYTHING)
1330e5c31af7Sopenharmony_ci	{
1331e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
1332e5c31af7Sopenharmony_ci			computeScaleAndBias(reference, result, pixelScale, pixelBias);
1333e5c31af7Sopenharmony_ci
1334e5c31af7Sopenharmony_ci		if (!isOk)
1335e5c31af7Sopenharmony_ci			log << TestLog::Message << "Image comparison failed, threshold = " << threshold << TestLog::EndMessage;
1336e5c31af7Sopenharmony_ci
1337e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1338e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
1339e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference,	pixelScale, pixelBias)
1340e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
1341e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1342e5c31af7Sopenharmony_ci	}
1343e5c31af7Sopenharmony_ci	else if (logMode == COMPARE_LOG_RESULT)
1344e5c31af7Sopenharmony_ci	{
1345e5c31af7Sopenharmony_ci		if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
1346e5c31af7Sopenharmony_ci			computePixelScaleBias(result, pixelScale, pixelBias);
1347e5c31af7Sopenharmony_ci
1348e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
1349e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result, pixelScale, pixelBias)
1350e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
1351e5c31af7Sopenharmony_ci	}
1352e5c31af7Sopenharmony_ci
1353e5c31af7Sopenharmony_ci	return isOk;
1354e5c31af7Sopenharmony_ci}
1355e5c31af7Sopenharmony_ci
1356e5c31af7Sopenharmony_ci} // tcu
1357