summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js757
1 files changed, 757 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js
new file mode 100644
index 0000000000..3a8138ef23
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuImageCompare.js
@@ -0,0 +1,757 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES Utilities
+ * ------------------------------------------------
+ *
+ * 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.
+ *
+ */
+
+'use strict';
+goog.provide('framework.common.tcuImageCompare');
+goog.require('framework.common.tcuBilinearImageCompare');
+goog.require('framework.common.tcuFloat');
+goog.require('framework.common.tcuFuzzyImageCompare');
+goog.require('framework.common.tcuLogImage');
+goog.require('framework.common.tcuRGBA');
+goog.require('framework.common.tcuSurface');
+goog.require('framework.common.tcuTexture');
+goog.require('framework.common.tcuTextureUtil');
+goog.require('framework.delibs.debase.deMath');
+
+goog.scope(function() {
+
+var tcuImageCompare = framework.common.tcuImageCompare;
+var tcuSurface = framework.common.tcuSurface;
+var deMath = framework.delibs.debase.deMath;
+var tcuTexture = framework.common.tcuTexture;
+var tcuTextureUtil = framework.common.tcuTextureUtil;
+var tcuFloat = framework.common.tcuFloat;
+var tcuFuzzyImageCompare = framework.common.tcuFuzzyImageCompare;
+var tcuBilinearImageCompare = framework.common.tcuBilinearImageCompare;
+var tcuRGBA = framework.common.tcuRGBA;
+var tcuLogImage = framework.common.tcuLogImage;
+
+/**
+ * @enum
+ */
+tcuImageCompare.CompareLogMode = {
+ EVERYTHING: 0,
+ RESULT: 1,
+ ON_ERROR: 2
+};
+
+/**
+ * @param {framework.common.tcuTexture.ConstPixelBufferAccess} result
+ * @param {framework.common.tcuTexture.ConstPixelBufferAccess} reference
+ * @param {framework.common.tcuTexture.ConstPixelBufferAccess=} diff
+ */
+tcuImageCompare.displayImages = function(result, reference, diff) {
+ var limits = tcuImageCompare.computeScaleAndBias(reference, result);
+ tcuLogImage.logImage('Result', '', result, limits.scale, limits.bias);
+ tcuLogImage.logImage('Reference', '', reference, limits.scale, limits.bias);
+ if (diff)
+ tcuLogImage.logImage('Error', 'error mask', diff);
+};
+
+/**
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @return {{scale: Array<number>, bias: Array<number>}}
+ */
+tcuImageCompare.computeScaleAndBias = function(reference, result) {
+ var minVal = [];
+ var maxVal = [];
+ var scale = [];
+ var bias = [];
+
+ var eps = 0.0001;
+ var referenceRange = tcuTextureUtil.estimatePixelValueRange(reference);
+ var resultRange = tcuTextureUtil.estimatePixelValueRange(result);
+
+ minVal[0] = Math.min(referenceRange[0][0], resultRange[0][0]);
+ minVal[1] = Math.min(referenceRange[0][1], resultRange[0][1]);
+ minVal[2] = Math.min(referenceRange[0][2], resultRange[0][2]);
+ minVal[3] = Math.min(referenceRange[0][3], resultRange[0][3]);
+
+ maxVal[0] = Math.max(referenceRange[1][0], resultRange[1][0]);
+ maxVal[1] = Math.max(referenceRange[1][1], resultRange[1][1]);
+ maxVal[2] = Math.max(referenceRange[1][2], resultRange[1][2]);
+ maxVal[3] = Math.max(referenceRange[1][3], resultRange[1][3]);
+
+ for (var c = 0; c < 4; c++) {
+ if (maxVal[c] - minVal[c] < eps) {
+ scale[c] = (maxVal[c] < eps) ? 1 : (1 / maxVal[c]);
+ bias[c] = (c == 3) ? (1 - maxVal[c] * scale[c]) : (0 - minVal[c] * scale[c]);
+ } else {
+ scale[c] = 1 / (maxVal[c] - minVal[c]);
+ bias[c] = 0 - minVal[c] * scale[c];
+ }
+ }
+ return {
+ scale: scale,
+ bias: bias
+ };
+};
+
+/**
+ * \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 {string} imageSetName Name for image set when logging results
+ * @param {string} imageSetDesc Description for image set
+ * @param {tcuTexture.ConstPixelBufferAccess} reference Reference image
+ * @param {tcuTexture.ConstPixelBufferAccess} result Result image
+ * @param {Array<number>} threshold Maximum allowed difference
+ * @param {tcuImageCompare.CompareLogMode=} logMode
+ * @param {Array< Array<number> >} skipPixels pixels that are skipped comparison
+ * @return {boolean} true if comparison passes, false otherwise
+ */
+ tcuImageCompare.intThresholdCompare = function(imageSetName, imageSetDesc, reference, result, threshold, logMode, skipPixels) {
+ var width = reference.getWidth();
+ var height = reference.getHeight();
+ var depth = reference.getDepth();
+ var errorMask = new tcuSurface.Surface(width, height);
+
+ var maxDiff = [0, 0, 0, 0];
+ // var pixelBias = [0, 0, 0, 0]; // Vec4 // TODO: check, only used in computeScaleAndBias, which is not included
+ // var pixelScale = [1, 1, 1, 1]; // Vec4 // TODO: check, only used in computeScaleAndBias
+
+ assertMsgOptions(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth,
+ 'Reference and result images have different dimensions', false, true);
+
+ for (var z = 0; z < depth; z++) {
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ if (skipPixels && skipPixels.length > 0) {
+ var skip = false;
+ for (var ii = 0; ii < skipPixels.length; ++ii) {
+ var refZ = (skipPixels[ii].length > 2 ? skipPixels[ii][2] : 0);
+ if (x == skipPixels[ii][0] && y == skipPixels[ii][1] && z == refZ) {
+ skip = true;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+ }
+ var refPix = reference.getPixelInt(x, y, z);
+ var cmpPix = result.getPixelInt(x, y, z);
+
+ var diff = deMath.absDiff(refPix, cmpPix);
+ var isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ maxDiff = deMath.max(maxDiff, diff);
+ var color = [0, 255, 0, 255];
+ if (!isOk)
+ color = [255, 0, 0, 255];
+ errorMask.setPixel(x, y, color);
+ }
+ }
+ }
+
+ var compareOk = deMath.boolAll(deMath.lessThanEqual(maxDiff, threshold));
+
+ if (!compareOk) {
+ debug('Image comparison failed: max difference = ' + maxDiff + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ 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 {string} imageSetName Name for image set when logging results
+ * @param {string} imageSetDesc Description for image set
+ * @param {tcuTexture.ConstPixelBufferAccess} reference Reference image
+ * @param {tcuTexture.ConstPixelBufferAccess} result Result image
+ * @param {Array<number>} threshold Maximum allowed difference
+ * @param {Array<number>} maxPositionDeviation Maximum allowed distance in the search volume.
+ * @param {boolean} acceptOutOfBoundsAsAnyValue Accept any pixel in the boundary region
+ * @param {number} maxAllowedFailingPixels Maximum number of failing pixels
+ * @return {boolean} true if comparison passes, false otherwise
+ */
+tcuImageCompare.intThresholdPositionDeviationErrorThresholdCompare = function(
+ imageSetName, imageSetDesc, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue, maxAllowedFailingPixels) {
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @type {number} */ var depth = reference.getDepth();
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
+ /** @type {number} */ var numFailingPixels = tcuImageCompare.findNumPositionDeviationFailingPixels(errorMask.getAccess(), reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue);
+ var compareOk = numFailingPixels <= maxAllowedFailingPixels;
+ /** @type {Array<number>} */ var pixelBias = [0.0, 0.0, 0.0, 0.0];
+ /** @type {Array<number>} */ var pixelScale = [1.0, 1.0, 1.0, 1.0];
+
+ if (!compareOk) {
+ debug('Position deviation error threshold image comparison failed: failed pixels = ' + numFailingPixels + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ } else
+ tcuLogImage.logImage('Result', '', result);
+
+ /*if (!compareOk) {
+ // All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
+ if (tcuTexture.getTextureChannelClass(reference.getFormat().type) != tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT ||
+ tcuTexture.getTextureChannelClass(result.getFormat().type) != tcuTexture.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;
+};
+
+/**
+ * tcuImageCompare.floatUlpThresholdCompare
+ * @param {string} imageSetName
+ * @param {string} imageSetDesc
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {Array<number>} threshold - previously used as an Uint32Array
+ * @return {boolean}
+ */
+tcuImageCompare.floatUlpThresholdCompare = function(imageSetName, imageSetDesc, reference, result, threshold) {
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @type {number} */ var depth = reference.getDepth();
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
+
+ /** @type {Array<number>} */ var maxDiff = [0, 0, 0, 0]; // UVec4
+ // var pixelBias = [0, 0, 0, 0]; // Vec4
+ // var pixelScale = [1, 1, 1, 1]; // Vec4
+
+ assertMsgOptions(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth,
+ 'Reference and result images have different dimensions', false, true);
+
+ for (var z = 0; z < depth; z++) {
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ /** @type {ArrayBuffer} */ var arrayBufferRef = new ArrayBuffer(4 * 4);
+ /** @type {ArrayBuffer} */ var arrayBufferCmp = new ArrayBuffer(4 * 4);
+
+ /** @type {Array<number>} */ var refPix = reference.getPixel(x, y, z); // getPixel returns a Vec4 pixel color
+
+ /** @type {Array<number>} */ var cmpPix = result.getPixel(x, y, z); // getPixel returns a Vec4 pixel color
+
+ /** @type {Uint32Array} */ var refBits = new Uint32Array(arrayBufferRef); // UVec4
+ /** @type {Uint32Array} */ var cmpBits = new Uint32Array(arrayBufferCmp); // UVec4
+
+ // Instead of memcpy(), which is the way to do float->uint32 reinterpretation in C++
+ for (var i = 0; i < refPix.length; i++) {
+ refBits[i] = tcuFloat.convertFloat32Inline(refPix[i], tcuFloat.description32);
+ cmpBits[i] = tcuFloat.convertFloat32Inline(cmpPix[i], tcuFloat.description32);
+ }
+
+ /** @type {Array<number>} */ var diff = deMath.absDiff(refBits, cmpBits); // UVec4
+ /** @type {boolean} */ var isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ maxDiff = deMath.max(maxDiff, diff);
+
+ errorMask.setPixel(x, y, isOk ? [0, 255, 0, 255] : [255, 0, 0, 255]);
+ }
+ }
+ }
+
+ /** @type {boolean} */ var compareOk = deMath.boolAll(deMath.lessThanEqual(maxDiff, threshold));
+
+ if (!compareOk) {
+ debug('Image comparison failed: max difference = ' + maxDiff + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ /*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;
+};
+
+/**
+ * tcuImageCompare.floatThresholdCompare
+ * @param {string} imageSetName
+ * @param {string} imageSetDesc
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {Array<number>} threshold
+ * @return {boolean}
+ */
+tcuImageCompare.floatThresholdCompare = function(imageSetName, imageSetDesc, reference, result, threshold) {
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @type {number} */ var depth = reference.getDepth();
+ /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(width, height);
+
+ /** @type {Array<number>} */ var maxDiff = [0, 0, 0, 0]; // Vec4
+ // var pixelBias = [0, 0, 0, 0]; // Vec4
+ // var pixelScale = [1, 1, 1, 1]; // Vec4
+
+ assertMsgOptions(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth,
+ 'Reference and result images have different dimensions', false, true);
+
+ for (var z = 0; z < depth; z++) {
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ var refPix = reference.getPixel(x, y, z); // Vec4
+ var cmpPix = result.getPixel(x, y, z); // Vec4
+
+ /** @type {Array<number>} */ var diff = deMath.absDiff(refPix, cmpPix); // Vec4
+ /** @type {boolean} */ var isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ maxDiff = deMath.max(maxDiff, diff);
+
+ errorMask.setPixel(x, y, isOk ? [0, 255, 0, 255] : [255, 0, 0, 255]);
+ }
+ }
+ }
+
+ /** @type {boolean} */ var compareOk = deMath.boolAll(deMath.lessThanEqual(maxDiff, threshold));
+
+ if (!compareOk) {
+ debug('Image comparison failed: max difference = ' + maxDiff + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ /*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.
+ *
+ * On failure error image is generated that shows where the failing pixels
+ * are.
+ *
+ * @param {string} imageSetName Name for image set when logging results
+ * @param {string} imageSetDesc Description for image set
+ * @param {tcuSurface.Surface} reference Reference image
+ * @param {tcuSurface.Surface} result Result image
+ * @param {Array<number>} threshold Maximum allowed difference
+ * @param {tcuImageCompare.CompareLogMode=} logMode
+ * @param {Array< Array<number> >} skipPixels pixels that are skipped comparison
+ * @return {boolean} true if comparison passes, false otherwise
+ */
+tcuImageCompare.pixelThresholdCompare = function(imageSetName, imageSetDesc, reference, result, threshold, logMode, skipPixels) {
+ return tcuImageCompare.intThresholdCompare(imageSetName, imageSetDesc, reference.getAccess(), result.getAccess(), threshold, logMode, skipPixels);
+};
+
+/**
+ * @param {tcuTexture.PixelBufferAccess} errorMask
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {Array<number>} threshold
+ * @param {Array<number>} maxPositionDeviation
+ * @param {boolean} acceptOutOfBoundsAsAnyValue
+ * @return {number}
+ */
+tcuImageCompare.findNumPositionDeviationFailingPixels = function(errorMask, reference, result, threshold, maxPositionDeviation, acceptOutOfBoundsAsAnyValue) {
+ /** @type {number} */ var width = reference.getWidth();
+ /** @type {number} */ var height = reference.getHeight();
+ /** @type {number} */ var depth = reference.getDepth();
+ /** @type {number} */ var numFailingPixels = 0;
+
+ checkMessage(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth, 'Surfaces have different dimensions');
+
+ for (var z = 0; z < depth; z++) {
+ for (var y = 0; y < height; y++) {
+ for (var x = 0; x < width; x++) {
+ /** @type {Array<number>} */ var refPix = reference.getPixelInt(x, y, z);
+ /** @type {Array<number>} */ var cmpPix = result.getPixelInt(x, y, z);
+
+ // Exact match
+ /** @type {Array<number>} */ var diff = deMath.absDiff(refPix, cmpPix);
+ /** @type {boolean} */ var isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ if (isOk) {
+ errorMask.setPixel([0, 0xff, 0, 0xff], x, y, z);
+ continue;
+ }
+
+ // Accept over the image bounds pixels since they could be anything
+
+ if (acceptOutOfBoundsAsAnyValue &&
+ (x < maxPositionDeviation[0] || x + maxPositionDeviation[0] >= width ||
+ y < maxPositionDeviation[1] || y + maxPositionDeviation[1] >= height ||
+ z < maxPositionDeviation[2] || z + maxPositionDeviation[2] >= depth)) {
+ errorMask.setPixel([0, 0xff, 0, 0xff], x, y, z);
+ continue;
+ }
+
+ // Find matching pixels for both result and reference pixel
+
+ var pixelFoundForReference = false;
+ var pixelFoundForResult = false;
+
+ // Find deviated result pixel for reference
+
+ for (var sz = Math.max(0, z - maxPositionDeviation[2]); sz <= Math.min(depth - 1, z + maxPositionDeviation[2]) && !pixelFoundForReference; ++sz)
+ for (var sy = Math.max(0, y - maxPositionDeviation[1]); sy <= Math.min(height - 1, y + maxPositionDeviation[1]) && !pixelFoundForReference; ++sy)
+ for (var sx = Math.max(0, x - maxPositionDeviation[0]); sx <= Math.min(width - 1, x + maxPositionDeviation[0]) && !pixelFoundForReference; ++sx) {
+ /** @type {Array<number>} */ var deviatedCmpPix = result.getPixelInt(sx, sy, sz);
+ diff = deMath.absDiff(refPix, deviatedCmpPix);
+ isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ pixelFoundForReference |= isOk;
+ }
+
+ // Find deviated reference pixel for result
+
+ for (var sz = Math.max(0, z - maxPositionDeviation[2]); sz <= Math.min(depth - 1, z + maxPositionDeviation[2]) && !pixelFoundForResult; ++sz)
+ for (var sy = Math.max(0, y - maxPositionDeviation[1]); sy <= Math.min(height - 1, y + maxPositionDeviation[1]) && !pixelFoundForResult; ++sy)
+ for (var sx = Math.max(0, x - maxPositionDeviation[0]); sx <= Math.min(width - 1, x + maxPositionDeviation[0]) && !pixelFoundForResult; ++sx) {
+ /** @type {Array<number>} */ var deviatedRefPix = reference.getPixelInt(sx, sy, sz);
+ diff = deMath.absDiff(cmpPix, deviatedRefPix);
+ isOk = deMath.boolAll(deMath.lessThanEqual(diff, threshold));
+
+ pixelFoundForResult |= isOk;
+ }
+
+ if (pixelFoundForReference && pixelFoundForResult)
+ errorMask.setPixel([0, 0xff, 0, 0xff], x, y, z);
+ else {
+ errorMask.setPixel([0xff, 0, 0, 0xff], x, y, z);
+ ++numFailingPixels;
+ }
+ }
+ }
+ }
+
+ return numFailingPixels;
+};
+
+ /**
+ * tcuImageCompare.fuzzyCompare
+ * @param {string} imageSetName
+ * @param {string} imageSetDesc
+ * @param {tcuTexture.ConstPixelBufferAccess} reference
+ * @param {tcuTexture.ConstPixelBufferAccess} result
+ * @param {number} threshold
+ * @param {tcuImageCompare.CompareLogMode=} logMode
+ * @return {boolean}
+ */
+tcuImageCompare.fuzzyCompare = function(imageSetName, imageSetDesc, reference, result, threshold, logMode) {
+ /** @type {tcuFuzzyImageCompare.FuzzyCompareParams} */ var params = new tcuFuzzyImageCompare.FuzzyCompareParams(); // Use defaults.
+ /** @type {tcuTexture.TextureLevel} */ var errorMask = new tcuTexture.TextureLevel(
+ new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGB,
+ tcuTexture.ChannelType.UNORM_INT8),
+ reference.getWidth(),
+ reference.getHeight()
+ );
+ /** @type {number} */ var difference = tcuFuzzyImageCompare.fuzzyCompare(
+ params,
+ reference,
+ result,
+ tcuTexture.PixelBufferAccess.newFromTextureLevel(errorMask)
+ );
+ /** @type {boolean} */ var isOk = difference <= threshold;
+ /** @type {Array<number>} */ var pixelBias = [0.0, 0.0, 0.0, 0.0];
+ /** @type {Array<number>} */ var pixelScale = [1.0, 1.0, 1.0, 1.0];
+
+ if (!isOk) {
+ debug('Fuzzy image comparison failed: difference = ' + difference + ', threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ /*
+ if (!isOk || logMode == COMPARE_LOG_EVERYTHING) {
+ // Generate more accurate error mask.
+ params.maxSampleSkip = 0;
+ tcuImageCompare.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;
+};
+
+tcuImageCompare.unitTest = function() {
+ var width = 128;
+ var height = 128;
+
+ var weirdLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RG, tcuTexture.ChannelType.SNORM_INT32), width, height);
+ var access = weirdLevel.getAccess();
+ access.clear([0.1, 0.5, 0, 0]);
+ access.clear([0.11, 0.52, 0, 0], [0, width], [0, height / 2]);
+ access.clear([0.12, 0.52, 0, 0], [0, width], [height / 2, height / 2 + height / 8]);
+ var limits = tcuTextureUtil.computePixelScaleBias(access);
+ debug('Scale: ' + limits.scale);
+ debug('Bias: ' + limits.bias);
+ tcuLogImage.logImage('Weird', 'weird format without scaling', access);
+ tcuLogImage.logImage('Weird', 'weird format', access, limits.scale, limits.bias);
+
+ var srcLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+ var dstLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+ var src = srcLevel.getAccess();
+ var dst = dstLevel.getAccess();
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 1; i++) {
+ for (var j = 0; j < height - 1; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ dst.setPixelInt([i, j, 90, 255], i + 1, j + 1);
+ }
+ }
+
+ debug('Src format: ' + src.getFormat());
+ debug('Destination: ' + dst);
+ debug(src);
+ tcuLogImage.logImage('Source', 'Source image', src);
+
+ if (!tcuImageCompare.fuzzyCompare('compare', 'compare similar images', src, dst, 0.05))
+ throw new Error('Compare should return true');
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 2; i++) {
+ for (var j = 0; j < height - 2; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ dst.setPixelInt([i, j, 90, 255], i + 2, j + 2);
+ }
+ }
+
+ if (tcuImageCompare.fuzzyCompare('compare', 'compare different images', src, dst, 0.05))
+ throw new Error('Compare should return false');
+
+ debug('Passed');
+};
+
+tcuImageCompare.unitTest2 = function() {
+ var width = 128;
+ var height = 128;
+ var srcLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+ var dstLevel = new tcuTexture.TextureLevel(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_INT8), width, height);
+ var src = srcLevel.getAccess();
+ var dst = dstLevel.getAccess();
+ var threshold = tcuRGBA.newRGBAComponents(1, 1, 1, 1);
+ debug('Threshold: ' + threshold);
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 1; i++) {
+ for (var j = 0; j < height - 1; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ dst.setPixelInt([i, j, 90, 255], i, j);
+ }
+ }
+ if (!tcuImageCompare.bilinearCompare('compare', 'compare similar images', src, dst, threshold))
+ throw new Error('Compare should return true');
+ debug('bilinear compare the same images passed');
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 1; i++) {
+ for (var j = 0; j < height - 1; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ dst.setPixelInt([i, j + 1, 90, 255], i, j + 1);
+ }
+ }
+ if (!tcuImageCompare.bilinearCompare('compare', 'compare similar images', src, dst, threshold))
+ throw new Error('Compare should return true');
+ debug('bilinear compare very similar images passed');
+
+ src.clear();
+ dst.clear();
+
+ for (var i = 0; i < width - 2; i++) {
+ for (var j = 0; j < height - 2; j++) {
+ src.setPixelInt([i, j, 90, 255], i, j);
+ // dst.setPixelInt([i, j, 90, 255], i + 2, j + 2);
+ }
+ }
+
+ if (tcuImageCompare.bilinearCompare('compare', 'compare different images', src, dst, threshold))
+ throw new Error('Compare should return false');
+
+ debug('bilinear compare very different images passed');
+};
+
+/**
+ * Bilinear image comparison
+ * On failure error image is generated that shows where the failing pixels
+ * are.
+ * Currently supports only RGBA, UNORM_INT8 formats
+ *
+ * @param {string} imageSetName Name for image set when logging results
+ * @param {string} imageSetDesc Description for image set
+ * @param {tcuTexture.ConstPixelBufferAccess} reference Reference image
+ * @param {tcuTexture.ConstPixelBufferAccess} result Result image
+ * @param {tcuRGBA.RGBA} threshold Maximum local difference
+ * @param {tcuImageCompare.CompareLogMode=} logMode Logging mode
+ * @return {boolean} if comparison passes, false otherwise
+ */
+tcuImageCompare.bilinearCompare = function(imageSetName, imageSetDesc, reference, result, threshold, logMode) {
+ /** @type {tcuTexture.TextureLevel} */
+ var errorMask = new tcuTexture.TextureLevel(
+ new tcuTexture.TextureFormat(
+ tcuTexture.ChannelOrder.RGB,
+ tcuTexture.ChannelType.UNORM_INT8),
+ reference.getWidth(),
+ reference.getHeight());
+
+ /** @type {boolean} */
+ var isOk = tcuBilinearImageCompare.bilinearCompare(
+ reference,
+ result,
+ tcuTexture.PixelBufferAccess.newFromTextureLevel(errorMask),
+ threshold);
+
+ if (!isOk) {
+ debug('Image comparison failed: threshold = ' + threshold);
+ tcuImageCompare.displayImages(result, reference, errorMask.getAccess());
+ }
+
+ // /* @type {Array<number>} */ var pixelBias = [0.0, 0.0, 0.0, 0.0];
+ // /* @type {Array<number>} */ var pixelScale = [1.0, 1.0, 1.0, 1.0];
+ // 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;
+};
+
+});