xref: /aosp_15_r20/external/deqp/framework/common/tcuImageCompare.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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