You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1144 lines
47 KiB
1144 lines
47 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program Tester Core
|
|
* ----------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Image comparison utilities.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "tcuImageCompare.hpp"
|
|
#include "tcuSurface.hpp"
|
|
#include "tcuFuzzyImageCompare.hpp"
|
|
#include "tcuBilinearImageCompare.hpp"
|
|
#include "tcuTestLog.hpp"
|
|
#include "tcuVector.hpp"
|
|
#include "tcuVectorUtil.hpp"
|
|
#include "tcuRGBA.hpp"
|
|
#include "tcuTexture.hpp"
|
|
#include "tcuTextureUtil.hpp"
|
|
#include "tcuFloat.hpp"
|
|
|
|
#include <string.h>
|
|
|
|
namespace tcu
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
void computeScaleAndBias (const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, tcu::Vec4& scale, tcu::Vec4& bias)
|
|
{
|
|
Vec4 minVal;
|
|
Vec4 maxVal;
|
|
const float eps = 0.0001f;
|
|
|
|
{
|
|
Vec4 refMin;
|
|
Vec4 refMax;
|
|
estimatePixelValueRange(reference, refMin, refMax);
|
|
|
|
minVal = refMin;
|
|
maxVal = refMax;
|
|
}
|
|
|
|
{
|
|
Vec4 resMin;
|
|
Vec4 resMax;
|
|
|
|
estimatePixelValueRange(result, resMin, resMax);
|
|
|
|
minVal[0] = de::min(minVal[0], resMin[0]);
|
|
minVal[1] = de::min(minVal[1], resMin[1]);
|
|
minVal[2] = de::min(minVal[2], resMin[2]);
|
|
minVal[3] = de::min(minVal[3], resMin[3]);
|
|
|
|
maxVal[0] = de::max(maxVal[0], resMax[0]);
|
|
maxVal[1] = de::max(maxVal[1], resMax[1]);
|
|
maxVal[2] = de::max(maxVal[2], resMax[2]);
|
|
maxVal[3] = de::max(maxVal[3], resMax[3]);
|
|
}
|
|
|
|
for (int c = 0; c < 4; c++)
|
|
{
|
|
if (maxVal[c] - minVal[c] < eps)
|
|
{
|
|
scale[c] = (maxVal[c] < eps) ? 1.0f : (1.0f / maxVal[c]);
|
|
bias[c] = (c == 3) ? (1.0f - maxVal[c]*scale[c]) : (0.0f - minVal[c]*scale[c]);
|
|
}
|
|
else
|
|
{
|
|
scale[c] = 1.0f / (maxVal[c] - minVal[c]);
|
|
bias[c] = 0.0f - minVal[c]*scale[c];
|
|
}
|
|
}
|
|
}
|
|
|
|
static int findNumPositionDeviationFailingPixels (const PixelBufferAccess& errorMask, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, const tcu::IVec3& maxPositionDeviation, bool acceptOutOfBoundsAsAnyValue)
|
|
{
|
|
const tcu::IVec4 okColor (0, 255, 0, 255);
|
|
const tcu::IVec4 errorColor (255, 0, 0, 255);
|
|
const int width = reference.getWidth();
|
|
const int height = reference.getHeight();
|
|
const int depth = reference.getDepth();
|
|
int numFailingPixels = 0;
|
|
|
|
// Accept pixels "sampling" over the image bounds pixels since "taps" could be anything
|
|
const int beginX = (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.x()) : (0);
|
|
const int beginY = (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.y()) : (0);
|
|
const int beginZ = (acceptOutOfBoundsAsAnyValue) ? (maxPositionDeviation.z()) : (0);
|
|
const int endX = (acceptOutOfBoundsAsAnyValue) ? (width - maxPositionDeviation.x()) : (width);
|
|
const int endY = (acceptOutOfBoundsAsAnyValue) ? (height - maxPositionDeviation.y()) : (height);
|
|
const int endZ = (acceptOutOfBoundsAsAnyValue) ? (depth - maxPositionDeviation.z()) : (depth);
|
|
|
|
TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
|
|
DE_ASSERT(endX > 0 && endY > 0 && endZ > 0); // most likely a bug
|
|
|
|
tcu::clear(errorMask, okColor);
|
|
|
|
for (int z = beginZ; z < endZ; z++)
|
|
{
|
|
for (int y = beginY; y < endY; y++)
|
|
{
|
|
for (int x = beginX; x < endX; x++)
|
|
{
|
|
const IVec4 refPix = reference.getPixelInt(x, y, z);
|
|
const IVec4 cmpPix = result.getPixelInt(x, y, z);
|
|
|
|
// Exact match
|
|
{
|
|
const UVec4 diff = abs(refPix - cmpPix).cast<deUint32>();
|
|
const bool isOk = boolAll(lessThanEqual(diff, threshold));
|
|
|
|
if (isOk)
|
|
continue;
|
|
}
|
|
|
|
// Find matching pixels for both result and reference pixel
|
|
|
|
{
|
|
bool pixelFoundForReference = false;
|
|
|
|
// Find deviated result pixel for reference
|
|
|
|
for (int sz = de::max(0, z - maxPositionDeviation.z()); sz <= de::min(depth - 1, z + maxPositionDeviation.z()) && !pixelFoundForReference; ++sz)
|
|
for (int sy = de::max(0, y - maxPositionDeviation.y()); sy <= de::min(height - 1, y + maxPositionDeviation.y()) && !pixelFoundForReference; ++sy)
|
|
for (int sx = de::max(0, x - maxPositionDeviation.x()); sx <= de::min(width - 1, x + maxPositionDeviation.x()) && !pixelFoundForReference; ++sx)
|
|
{
|
|
const IVec4 deviatedCmpPix = result.getPixelInt(sx, sy, sz);
|
|
const UVec4 diff = abs(refPix - deviatedCmpPix).cast<deUint32>();
|
|
const bool isOk = boolAll(lessThanEqual(diff, threshold));
|
|
|
|
pixelFoundForReference = isOk;
|
|
}
|
|
|
|
if (!pixelFoundForReference)
|
|
{
|
|
errorMask.setPixel(errorColor, x, y, z);
|
|
++numFailingPixels;
|
|
continue;
|
|
}
|
|
}
|
|
{
|
|
bool pixelFoundForResult = false;
|
|
|
|
// Find deviated reference pixel for result
|
|
|
|
for (int sz = de::max(0, z - maxPositionDeviation.z()); sz <= de::min(depth - 1, z + maxPositionDeviation.z()) && !pixelFoundForResult; ++sz)
|
|
for (int sy = de::max(0, y - maxPositionDeviation.y()); sy <= de::min(height - 1, y + maxPositionDeviation.y()) && !pixelFoundForResult; ++sy)
|
|
for (int sx = de::max(0, x - maxPositionDeviation.x()); sx <= de::min(width - 1, x + maxPositionDeviation.x()) && !pixelFoundForResult; ++sx)
|
|
{
|
|
const IVec4 deviatedRefPix = reference.getPixelInt(sx, sy, sz);
|
|
const UVec4 diff = abs(cmpPix - deviatedRefPix).cast<deUint32>();
|
|
const bool isOk = boolAll(lessThanEqual(diff, threshold));
|
|
|
|
pixelFoundForResult = isOk;
|
|
}
|
|
|
|
if (!pixelFoundForResult)
|
|
{
|
|
errorMask.setPixel(errorColor, x, y, z);
|
|
++numFailingPixels;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return numFailingPixels;
|
|
}
|
|
|
|
} // anonymous
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Fuzzy image comparison
|
|
*
|
|
* This image comparison is designed for comparing images rendered by 3D
|
|
* graphics APIs such as OpenGL. The comparison allows small local differences
|
|
* and compensates for aliasing.
|
|
*
|
|
* The algorithm first performs light blurring on both images and then
|
|
* does per-pixel analysis. Pixels are compared to 3x3 bilinear surface
|
|
* defined by adjecent pixels. This compensates for both 1-pixel deviations
|
|
* in geometry and aliasing in texture data.
|
|
*
|
|
* Error metric is computed based on the differences. On valid images the
|
|
* metric is usually <0.01. Thus good threshold values are in range 0.02 to
|
|
* 0.05.
|
|
*
|
|
* On failure error image is generated that shows where the failing pixels
|
|
* are.
|
|
*
|
|
* \note Currently supports only UNORM_INT8 formats
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Error metric threshold (good values are 0.02-0.05)
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool fuzzyCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, float threshold, CompareLogMode logMode)
|
|
{
|
|
FuzzyCompareParams params; // Use defaults.
|
|
TextureLevel errorMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight());
|
|
float difference = fuzzyCompare(params, reference, result, errorMask.getAccess());
|
|
bool isOk = difference <= threshold;
|
|
Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
if (!isOk || logMode == COMPARE_LOG_EVERYTHING)
|
|
{
|
|
// Generate more accurate error mask.
|
|
params.maxSampleSkip = 0;
|
|
fuzzyCompare(params, reference, result, errorMask.getAccess());
|
|
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computeScaleAndBias(reference, result, pixelScale, pixelBias);
|
|
|
|
if (!isOk)
|
|
log << TestLog::Message << "Image comparison failed: difference = " << difference << ", threshold = " << threshold << TestLog::EndMessage;
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
|
|
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
|
|
return isOk;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Fuzzy image comparison
|
|
*
|
|
* This image comparison is designed for comparing images rendered by 3D
|
|
* graphics APIs such as OpenGL. The comparison allows small local differences
|
|
* and compensates for aliasing.
|
|
*
|
|
* The algorithm first performs light blurring on both images and then
|
|
* does per-pixel analysis. Pixels are compared to 3x3 bilinear surface
|
|
* defined by adjecent pixels. This compensates for both 1-pixel deviations
|
|
* in geometry and aliasing in texture data.
|
|
*
|
|
* Error metric is computed based on the differences. On valid images the
|
|
* metric is usually <0.01. Thus good threshold values are in range 0.02 to
|
|
* 0.05.
|
|
*
|
|
* On failure error image is generated that shows where the failing pixels
|
|
* are.
|
|
*
|
|
* \note Currently supports only UNORM_INT8 formats
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Error metric threshold (good values are 0.02-0.05)
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool fuzzyCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, float threshold, CompareLogMode logMode)
|
|
{
|
|
return fuzzyCompare(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold, logMode);
|
|
}
|
|
|
|
static deInt64 computeSquaredDiffSum (const ConstPixelBufferAccess& ref, const ConstPixelBufferAccess& cmp, const PixelBufferAccess& diffMask, int diffFactor)
|
|
{
|
|
TCU_CHECK_INTERNAL(ref.getFormat().type == TextureFormat::UNORM_INT8 && cmp.getFormat().type == TextureFormat::UNORM_INT8);
|
|
DE_ASSERT(ref.getWidth() == cmp.getWidth() && ref.getWidth() == diffMask.getWidth());
|
|
DE_ASSERT(ref.getHeight() == cmp.getHeight() && ref.getHeight() == diffMask.getHeight());
|
|
|
|
deInt64 diffSum = 0;
|
|
|
|
for (int y = 0; y < cmp.getHeight(); y++)
|
|
{
|
|
for (int x = 0; x < cmp.getWidth(); x++)
|
|
{
|
|
IVec4 a = ref.getPixelInt(x, y);
|
|
IVec4 b = cmp.getPixelInt(x, y);
|
|
IVec4 diff = abs(a - b);
|
|
int sum = diff.x() + diff.y() + diff.z() + diff.w();
|
|
int sqSum = diff.x()*diff.x() + diff.y()*diff.y() + diff.z()*diff.z() + diff.w()*diff.w();
|
|
|
|
diffMask.setPixel(tcu::RGBA(deClamp32(sum*diffFactor, 0, 255), deClamp32(255-sum*diffFactor, 0, 255), 0, 255).toVec(), x, y);
|
|
|
|
diffSum += (deInt64)sqSum;
|
|
}
|
|
}
|
|
|
|
return diffSum;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel difference accuracy metric
|
|
*
|
|
* Computes accuracy metric using per-pixel differences between reference
|
|
* and result images.
|
|
*
|
|
* \note Supports only integer- and fixed-point formats
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param bestScoreDiff Scaling factor
|
|
* \param worstScoreDiff Scaling factor
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
int measurePixelDiffAccuracy (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, int bestScoreDiff, int worstScoreDiff, CompareLogMode logMode)
|
|
{
|
|
TextureLevel diffMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight());
|
|
int diffFactor = 8;
|
|
deInt64 squaredSum = computeSquaredDiffSum(reference, result, diffMask.getAccess(), diffFactor);
|
|
float sum = deFloatSqrt((float)squaredSum);
|
|
int score = deClamp32(deFloorFloatToInt32(100.0f - (de::max(sum-(float)bestScoreDiff, 0.0f) / (float)(worstScoreDiff-bestScoreDiff))*100.0f), 0, 100);
|
|
const int failThreshold = 10;
|
|
Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
if (logMode == COMPARE_LOG_EVERYTHING || score <= failThreshold)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computeScaleAndBias(reference, result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
|
|
<< TestLog::Image("DiffMask", "Difference", diffMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
|
|
if (logMode != COMPARE_LOG_ON_ERROR || score <= failThreshold)
|
|
log << TestLog::Integer("DiffSum", "Squared difference sum", "", QP_KEY_TAG_NONE, squaredSum)
|
|
<< TestLog::Integer("Score", "Score", "", QP_KEY_TAG_QUALITY, score);
|
|
|
|
return score;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel difference accuracy metric
|
|
*
|
|
* Computes accuracy metric using per-pixel differences between reference
|
|
* and result images.
|
|
*
|
|
* \note Supports only integer- and fixed-point formats
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param bestScoreDiff Scaling factor
|
|
* \param worstScoreDiff Scaling factor
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
int measurePixelDiffAccuracy (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, int bestScoreDiff, int worstScoreDiff, CompareLogMode logMode)
|
|
{
|
|
return measurePixelDiffAccuracy(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), bestScoreDiff, worstScoreDiff, logMode);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* Returns the index of float in a float space without denormals
|
|
* so that:
|
|
* 1) f(0.0) = 0
|
|
* 2) f(-0.0) = 0
|
|
* 3) f(b) = f(a) + 1 <==> b = nextAfter(a)
|
|
*
|
|
* See computeFloatFlushRelaxedULPDiff for details
|
|
*//*--------------------------------------------------------------------*/
|
|
static deInt32 getPositionOfIEEEFloatWithoutDenormals (float x)
|
|
{
|
|
DE_ASSERT(!deIsNaN(x)); // not sane
|
|
|
|
if (x == 0.0f)
|
|
return 0;
|
|
else if (x < 0.0f)
|
|
return -getPositionOfIEEEFloatWithoutDenormals(-x);
|
|
else
|
|
{
|
|
DE_ASSERT(x > 0.0f);
|
|
|
|
const tcu::Float32 f(x);
|
|
|
|
if (f.isDenorm())
|
|
{
|
|
// Denorms are flushed to zero
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
// sign is 0, and it's a normal number. Natural position is its bit
|
|
// pattern but since we've collapsed the denorms, we must remove
|
|
// the gap here too to keep the float enumeration continuous.
|
|
//
|
|
// Denormals occupy one exponent pattern. Removing one from
|
|
// exponent should to the trick. Add one since the removed range
|
|
// contained one representable value, 0.
|
|
return (deInt32)(f.bits() - (1u << 23u) + 1u);
|
|
}
|
|
}
|
|
}
|
|
|
|
static deUint32 computeFloatFlushRelaxedULPDiff (float a, float b)
|
|
{
|
|
if (deIsNaN(a) && deIsNaN(b))
|
|
return 0;
|
|
else if (deIsNaN(a) || deIsNaN(b))
|
|
{
|
|
return 0xFFFFFFFFu;
|
|
}
|
|
else
|
|
{
|
|
// Using the "definition 5" in Muller, Jean-Michel. "On the definition of ulp (x)" (2005)
|
|
// assuming a floating point space is IEEE single precision floating point space without
|
|
// denormals (and signed zeros).
|
|
const deInt32 aIndex = getPositionOfIEEEFloatWithoutDenormals(a);
|
|
const deInt32 bIndex = getPositionOfIEEEFloatWithoutDenormals(b);
|
|
return (deUint32)de::abs(aIndex - bIndex);
|
|
}
|
|
}
|
|
|
|
static tcu::UVec4 computeFlushRelaxedULPDiff (const tcu::Vec4& a, const tcu::Vec4& b)
|
|
{
|
|
return tcu::UVec4(computeFloatFlushRelaxedULPDiff(a.x(), b.x()),
|
|
computeFloatFlushRelaxedULPDiff(a.y(), b.y()),
|
|
computeFloatFlushRelaxedULPDiff(a.z(), b.z()),
|
|
computeFloatFlushRelaxedULPDiff(a.w(), b.w()));
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel threshold-based comparison
|
|
*
|
|
* This compare computes per-pixel differences between result and reference
|
|
* image. Comparison fails if any pixels exceed the given threshold value.
|
|
*
|
|
* This comparison uses ULP (units in last place) metric for computing the
|
|
* difference between floating-point values and thus this function can
|
|
* be used only for comparing floating-point texture data. In ULP calculation
|
|
* the denormal numbers are allowed to be flushed to zero.
|
|
*
|
|
* On failure error image is generated that shows where the failing pixels
|
|
* are.
|
|
*
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Maximum allowed difference
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool floatUlpThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode)
|
|
{
|
|
int width = reference.getWidth();
|
|
int height = reference.getHeight();
|
|
int depth = reference.getDepth();
|
|
TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
|
|
PixelBufferAccess errorMask = errorMaskStorage.getAccess();
|
|
UVec4 maxDiff (0, 0, 0, 0);
|
|
Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
TCU_CHECK(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
|
|
|
|
for (int z = 0; z < depth; z++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
const Vec4 refPix = reference.getPixel(x, y, z);
|
|
const Vec4 cmpPix = result.getPixel(x, y, z);
|
|
const UVec4 diff = computeFlushRelaxedULPDiff(refPix, cmpPix);
|
|
const bool isOk = boolAll(lessThanEqual(diff, threshold));
|
|
|
|
maxDiff = max(maxDiff, diff);
|
|
|
|
errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool compareOk = boolAll(lessThanEqual(maxDiff, threshold));
|
|
|
|
if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
|
|
{
|
|
// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
|
|
if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
|
|
tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
|
|
{
|
|
computeScaleAndBias(reference, result, pixelScale, pixelBias);
|
|
log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
|
|
}
|
|
|
|
if (!compareOk)
|
|
log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
|
|
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
|
|
return compareOk;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel threshold-based comparison
|
|
*
|
|
* This compare computes per-pixel differences between result and reference
|
|
* image. Comparison fails if any pixels exceed the given threshold value.
|
|
*
|
|
* This comparison can be used for floating-point and fixed-point formats.
|
|
* Difference is computed in floating-point space.
|
|
*
|
|
* On failure an error image is generated that shows where the failing
|
|
* pixels are.
|
|
*
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Maximum allowed difference
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode)
|
|
{
|
|
int width = reference.getWidth();
|
|
int height = reference.getHeight();
|
|
int depth = reference.getDepth();
|
|
TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
|
|
PixelBufferAccess errorMask = errorMaskStorage.getAccess();
|
|
Vec4 maxDiff (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
|
|
|
|
for (int z = 0; z < depth; z++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
Vec4 refPix = reference.getPixel(x, y, z);
|
|
Vec4 cmpPix = result.getPixel(x, y, z);
|
|
|
|
Vec4 diff = abs(refPix - cmpPix);
|
|
bool isOk = boolAll(lessThanEqual(diff, threshold));
|
|
|
|
maxDiff = max(maxDiff, diff);
|
|
|
|
errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool compareOk = boolAll(lessThanEqual(maxDiff, threshold));
|
|
|
|
if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
|
|
{
|
|
// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
|
|
if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
|
|
tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
|
|
{
|
|
computeScaleAndBias(reference, result, pixelScale, pixelBias);
|
|
log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
|
|
}
|
|
|
|
if (!compareOk)
|
|
log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
|
|
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
|
|
return compareOk;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel threshold-based comparison
|
|
*
|
|
* This compare computes per-pixel differences between result and reference
|
|
* color. Comparison fails if any pixels exceed the given threshold value.
|
|
*
|
|
* This comparison can be used for floating-point and fixed-point formats.
|
|
* Difference is computed in floating-point space.
|
|
*
|
|
* On failure an error image is generated that shows where the failing
|
|
* pixels are.
|
|
*
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference color
|
|
* \param result Result image
|
|
* \param threshold Maximum allowed difference
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool floatThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Vec4& reference, const ConstPixelBufferAccess& result, const Vec4& threshold, CompareLogMode logMode)
|
|
{
|
|
const int width = result.getWidth();
|
|
const int height = result.getHeight();
|
|
const int depth = result.getDepth();
|
|
|
|
TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
|
|
PixelBufferAccess errorMask = errorMaskStorage.getAccess();
|
|
Vec4 maxDiff (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
for (int z = 0; z < depth; z++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
const Vec4 cmpPix = result.getPixel(x, y, z);
|
|
const Vec4 diff = abs(reference - cmpPix);
|
|
const bool isOk = boolAll(lessThanEqual(diff, threshold));
|
|
|
|
maxDiff = max(maxDiff, diff);
|
|
|
|
errorMask.setPixel(isOk ? Vec4(0.0f, 1.0f, 0.0f, 1.0f) : Vec4(1.0f, 0.0f, 0.0f, 1.0f), x, y, z);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool compareOk = boolAll(lessThanEqual(maxDiff, threshold));
|
|
|
|
if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
|
|
{
|
|
// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
|
|
if (tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
|
|
{
|
|
computeScaleAndBias(result, result, pixelScale, pixelBias);
|
|
log << TestLog::Message << "Result image is normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
|
|
}
|
|
|
|
if (!compareOk)
|
|
log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << ", reference = " << reference << TestLog::EndMessage;
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
|
|
return compareOk;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel threshold-based comparison
|
|
*
|
|
* This compare computes per-pixel differences between result and reference
|
|
* image. Comparison fails if any pixels exceed the given threshold value.
|
|
*
|
|
* This comparison can be used for integer- and fixed-point texture formats.
|
|
* Difference is computed in integer space.
|
|
*
|
|
* On failure error image is generated that shows where the failing pixels
|
|
* are.
|
|
*
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Maximum allowed difference
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool intThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, CompareLogMode logMode)
|
|
{
|
|
int width = reference.getWidth();
|
|
int height = reference.getHeight();
|
|
int depth = reference.getDepth();
|
|
TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
|
|
PixelBufferAccess errorMask = errorMaskStorage.getAccess();
|
|
UVec4 maxDiff (0, 0, 0, 0);
|
|
Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
|
|
|
|
for (int z = 0; z < depth; z++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
IVec4 refPix = reference.getPixelInt(x, y, z);
|
|
IVec4 cmpPix = result.getPixelInt(x, y, z);
|
|
|
|
UVec4 diff = abs(refPix - cmpPix).cast<deUint32>();
|
|
bool isOk = boolAll(lessThanEqual(diff, threshold));
|
|
|
|
maxDiff = max(maxDiff, diff);
|
|
|
|
errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool compareOk = boolAll(lessThanEqual(maxDiff, threshold));
|
|
|
|
if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
|
|
{
|
|
// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
|
|
if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
|
|
tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
|
|
{
|
|
computeScaleAndBias(reference, result, pixelScale, pixelBias);
|
|
log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
|
|
}
|
|
|
|
if (!compareOk)
|
|
log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
|
|
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
|
|
return compareOk;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel depth/stencil threshold-based comparison
|
|
*
|
|
* This compare computes per-pixel differences between result and reference
|
|
* image. Comparison fails if any pixels exceed the given threshold value.
|
|
*
|
|
* This comparison can be used for depth and depth/stencil images.
|
|
* Difference is computed in integer space.
|
|
*
|
|
* On failure error image is generated that shows where the failing pixels
|
|
* are.
|
|
*
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Maximum allowed depth difference (stencil must be exact)
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool dsThresholdCompare(TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const float threshold, CompareLogMode logMode)
|
|
{
|
|
int width = reference.getWidth();
|
|
int height = reference.getHeight();
|
|
int depth = reference.getDepth();
|
|
TextureLevel errorMaskStorage(TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
|
|
PixelBufferAccess errorMask = errorMaskStorage.getAccess();
|
|
float maxDiff = 0.0;
|
|
bool allStencilOk = true;
|
|
bool hasDepth = tcu::hasDepthComponent(result.getFormat().order);
|
|
bool hasStencil = tcu::hasStencilComponent(result.getFormat().order);
|
|
|
|
TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth);
|
|
|
|
for (int z = 0; z < depth; z++)
|
|
{
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
bool isOk = true;
|
|
|
|
if (hasDepth)
|
|
{
|
|
float refDepth = reference.getPixDepth(x, y, z);
|
|
float cmpDepth = result.getPixDepth(x, y, z);
|
|
float diff = de::abs(refDepth - cmpDepth);
|
|
|
|
isOk = diff <= threshold;
|
|
maxDiff = (float) deMax(maxDiff, diff);
|
|
}
|
|
|
|
if (hasStencil)
|
|
{
|
|
deUint8 refStencil = (deUint8) reference.getPixStencil(x, y, z);
|
|
deUint8 cmpStencil = (deUint8) result.getPixStencil(x, y, z);
|
|
|
|
bool isStencilOk = (refStencil == cmpStencil);
|
|
allStencilOk = allStencilOk && isStencilOk;
|
|
isOk = isOk && isStencilOk;
|
|
}
|
|
|
|
errorMask.setPixel(isOk ? IVec4(0, 0xff, 0, 0xff) : IVec4(0xff, 0, 0, 0xff), x, y, z);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool compareOk = (maxDiff <= threshold) && allStencilOk;
|
|
|
|
if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
|
|
{
|
|
if (!compareOk)
|
|
{
|
|
if (maxDiff > threshold)
|
|
log << TestLog::Message << "Depth comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage;
|
|
if (!allStencilOk)
|
|
log << TestLog::Message << "Stencil comparison failed" << TestLog::EndMessage;
|
|
}
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
// TODO: Convert depth/stencil buffers into separate depth & stencil for logging?
|
|
// << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
// << TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
|
|
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
#if 0
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
#endif
|
|
}
|
|
|
|
return compareOk;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel threshold-based deviation-ignoring comparison
|
|
*
|
|
* This compare computes per-pixel differences between result and reference
|
|
* image. Comparison fails if there is no pixel matching the given threshold
|
|
* value in the search volume.
|
|
*
|
|
* If the search volume contains out-of-bounds pixels, comparison can be set
|
|
* to either ignore these pixels in search or to accept any pixel that has
|
|
* out-of-bounds pixels in its search volume.
|
|
*
|
|
* This comparison can be used for integer- and fixed-point texture formats.
|
|
* Difference is computed in integer space.
|
|
*
|
|
* On failure error image is generated that shows where the failing pixels
|
|
* are.
|
|
*
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Maximum allowed difference
|
|
* \param maxPositionDeviation Maximum allowed distance in the search
|
|
* volume.
|
|
* \param acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool intThresholdPositionDeviationCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, const tcu::IVec3& maxPositionDeviation, bool acceptOutOfBoundsAsAnyValue, CompareLogMode logMode)
|
|
{
|
|
const int width = reference.getWidth();
|
|
const int height = reference.getHeight();
|
|
const int depth = reference.getDepth();
|
|
TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
|
|
PixelBufferAccess errorMask = errorMaskStorage.getAccess();
|
|
const int numFailingPixels = findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue);
|
|
const bool compareOk = numFailingPixels == 0;
|
|
Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
|
|
{
|
|
// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
|
|
if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
|
|
tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
|
|
{
|
|
computeScaleAndBias(reference, result, pixelScale, pixelBias);
|
|
log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
|
|
}
|
|
|
|
if (!compareOk)
|
|
log << TestLog::Message
|
|
<< "Image comparison failed:\n"
|
|
<< "\tallowed position deviation = " << maxPositionDeviation << "\n"
|
|
<< "\tcolor threshold = " << threshold
|
|
<< TestLog::EndMessage;
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
|
|
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
|
|
return compareOk;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel threshold-based deviation-ignoring comparison
|
|
*
|
|
* This compare computes per-pixel differences between result and reference
|
|
* image. Pixel fails the test if there is no pixel matching the given
|
|
* threshold value in the search volume. Comparison fails if the number of
|
|
* failing pixels exceeds the given limit.
|
|
*
|
|
* If the search volume contains out-of-bounds pixels, comparison can be set
|
|
* to either ignore these pixels in search or to accept any pixel that has
|
|
* out-of-bounds pixels in its search volume.
|
|
*
|
|
* This comparison can be used for integer- and fixed-point texture formats.
|
|
* Difference is computed in integer space.
|
|
*
|
|
* On failure error image is generated that shows where the failing pixels
|
|
* are.
|
|
*
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Maximum allowed difference
|
|
* \param maxPositionDeviation Maximum allowed distance in the search
|
|
* volume.
|
|
* \param acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region
|
|
* \param maxAllowedFailingPixels Maximum number of failing pixels
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool intThresholdPositionDeviationErrorThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const UVec4& threshold, const tcu::IVec3& maxPositionDeviation, bool acceptOutOfBoundsAsAnyValue, int maxAllowedFailingPixels, CompareLogMode logMode)
|
|
{
|
|
const int width = reference.getWidth();
|
|
const int height = reference.getHeight();
|
|
const int depth = reference.getDepth();
|
|
TextureLevel errorMaskStorage (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), width, height, depth);
|
|
PixelBufferAccess errorMask = errorMaskStorage.getAccess();
|
|
const int numFailingPixels = findNumPositionDeviationFailingPixels(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue);
|
|
const bool compareOk = numFailingPixels <= maxAllowedFailingPixels;
|
|
Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
if (!compareOk || logMode == COMPARE_LOG_EVERYTHING)
|
|
{
|
|
// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
|
|
if (tcu::getTextureChannelClass(reference.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
|
|
tcu::getTextureChannelClass(result.getFormat().type) != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
|
|
{
|
|
computeScaleAndBias(reference, result, pixelScale, pixelBias);
|
|
log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
|
|
}
|
|
|
|
if (!compareOk)
|
|
log << TestLog::Message
|
|
<< "Image comparison failed:\n"
|
|
<< "\tallowed position deviation = " << maxPositionDeviation << "\n"
|
|
<< "\tcolor threshold = " << threshold
|
|
<< TestLog::EndMessage;
|
|
log << TestLog::Message << "Number of failing pixels = " << numFailingPixels << ", max allowed = " << maxAllowedFailingPixels << TestLog::EndMessage;
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
|
|
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
|
|
return compareOk;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Per-pixel threshold-based comparison
|
|
*
|
|
* This compare computes per-pixel differences between result and reference
|
|
* image. Comparison fails if any pixels exceed the given threshold value.
|
|
*
|
|
* On failure error image is generated that shows where the failing pixels
|
|
* are.
|
|
*
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Maximum allowed difference
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool pixelThresholdCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const Surface& reference, const Surface& result, const RGBA& threshold, CompareLogMode logMode)
|
|
{
|
|
return intThresholdCompare(log, imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold.toIVec().cast<deUint32>(), logMode);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Bilinear image comparison
|
|
*
|
|
* \todo [pyry] Describe
|
|
*
|
|
* On failure error image is generated that shows where the failing pixels
|
|
* are.
|
|
*
|
|
* \note Currently supports only RGBA, UNORM_INT8 formats
|
|
* \param log Test log for results
|
|
* \param imageSetName Name for image set when logging results
|
|
* \param imageSetDesc Description for image set
|
|
* \param reference Reference image
|
|
* \param result Result image
|
|
* \param threshold Maximum local difference
|
|
* \param logMode Logging mode
|
|
* \return true if comparison passes, false otherwise
|
|
*//*--------------------------------------------------------------------*/
|
|
bool bilinearCompare (TestLog& log, const char* imageSetName, const char* imageSetDesc, const ConstPixelBufferAccess& reference, const ConstPixelBufferAccess& result, const RGBA threshold, CompareLogMode logMode)
|
|
{
|
|
TextureLevel errorMask (TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8), reference.getWidth(), reference.getHeight());
|
|
bool isOk = bilinearCompare(reference, result, errorMask, threshold);
|
|
Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
|
|
Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
if (!isOk || logMode == COMPARE_LOG_EVERYTHING)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8) && reference.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computeScaleAndBias(reference, result, pixelScale, pixelBias);
|
|
|
|
if (!isOk)
|
|
log << TestLog::Message << "Image comparison failed, threshold = " << threshold << TestLog::EndMessage;
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::Image("Reference", "Reference", reference, pixelScale, pixelBias)
|
|
<< TestLog::Image("ErrorMask", "Error mask", errorMask)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
else if (logMode == COMPARE_LOG_RESULT)
|
|
{
|
|
if (result.getFormat() != TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8))
|
|
computePixelScaleBias(result, pixelScale, pixelBias);
|
|
|
|
log << TestLog::ImageSet(imageSetName, imageSetDesc)
|
|
<< TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
|
|
<< TestLog::EndImageSet;
|
|
}
|
|
|
|
return isOk;
|
|
}
|
|
|
|
} // tcu
|