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