| /*------------------------------------------------------------------------- |
| * 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 = 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 |