#include "deString.h"
#include "deStringUtil.hpp"
#include "tcuCompressedTexture.hpp"
+#include "tcuImageCompare.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
+#include "tcuVectorUtil.hpp"
#include "tcuAstcUtil.hpp"
#include "vkImageUtil.hpp"
#include "vktTestGroupUtil.hpp"
m_renderer.add2DTexture(m_texture, testParameters.aspectMask, testParameters.backingMode);
}
+static void computeScaleAndBias (const tcu::ConstPixelBufferAccess& reference, const tcu::ConstPixelBufferAccess& result, tcu::Vec4& scale, tcu::Vec4& bias)
+{
+ tcu::Vec4 minVal;
+ tcu::Vec4 maxVal;
+ const float eps = 0.0001f;
+
+ {
+ tcu::Vec4 refMin;
+ tcu::Vec4 refMax;
+ estimatePixelValueRange(reference, refMin, refMax);
+
+ minVal = refMin;
+ maxVal = refMax;
+ }
+
+ {
+ tcu::Vec4 resMin;
+ tcu::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 inline tcu::UVec4 min (tcu::UVec4 a, tcu::UVec4 b)
+{
+ return tcu::UVec4( deMin32(a[0], b[0]),
+ deMin32(a[1], b[1]),
+ deMin32(a[2], b[2]),
+ deMin32(a[3], b[3]));
+}
+
+static bool compareColor (tcu::RGBA reference, tcu::RGBA result, tcu::RGBA threshold, tcu::UVec4& diff)
+{
+ const tcu::IVec4 refPix = reference.toIVec();
+ const tcu::IVec4 cmpPix = result.toIVec();
+ const tcu::UVec4 thresholdVec = threshold.toIVec().cast<deUint32>();
+ diff = abs(refPix - cmpPix).cast<deUint32>();
+
+ return boolAll(lessThanEqual(diff, thresholdVec));
+}
+
+template <typename TextureType>
+static bool validateTexture (tcu::TestLog& log, const tcu::Surface& rendered, const TextureType& texture, const vector<float> &texCoord, deUint32 mipLevel,
+ const tcu::PixelFormat &pixelFormat, const tcu::RGBA& colorThreshold, float coordThreshold, const ReferenceParams sampleParams)
+{
+ const deUint32 textureWidth = texture.getWidth() >> mipLevel;
+ const deUint32 textureHeight = texture.getHeight() >> mipLevel;
+ const deUint32 renderWidth = rendered.getWidth();
+ const deUint32 renderHeight = rendered.getHeight();
+
+ tcu::TextureLevel errorMaskStorage (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), renderWidth, renderHeight, 1);
+ tcu::PixelBufferAccess errorMask = errorMaskStorage.getAccess();
+
+ tcu::UVec4 maxDiff (0u, 0u, 0u, 0u);
+ tcu::UVec4 smpDiff (0u, 0u, 0u, 0u);
+ tcu::UVec4 diff (0u, 0u, 0u, 0u);
+ bool isOk = true;
+
+ // Compute reference.
+ tcu::Surface referenceFrame (textureWidth, textureHeight);
+ glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat), texture, &texCoord[0], sampleParams);
+
+ for (deUint32 x = 0; x < renderWidth; ++x)
+ {
+ for (deUint32 y = 0; y < renderHeight; ++y)
+ {
+ bool matchFound = false;
+ const tcu::RGBA rendered_color = rendered.getPixel(x, y);
+
+ const float fragX = ((float)x + 0.5f) / (float)renderWidth;
+ const float fragY = ((float)y + 0.5f) / (float)renderHeight;
+ const float samplePixX = fragX * (float)(textureWidth);
+ const float samplePixY = fragY * (float)(textureHeight);
+
+ const deUint32 sampleXMin = (int)(samplePixX - coordThreshold);
+ const deUint32 sampleXMax = (int)(samplePixX + coordThreshold);
+ const deUint32 sampleYMin = (int)(samplePixY - coordThreshold);
+ const deUint32 sampleYMax = (int)(samplePixY + coordThreshold);
+
+ // Compare color within given sample coordinates tolerance and return from included loops when match is found
+ for (deUint32 smpX = sampleXMin; smpX <= sampleXMax; ++smpX)
+ {
+ for (deUint32 smpY = sampleYMin; smpY <= sampleYMax; ++smpY)
+ {
+ const tcu::RGBA reference_color = referenceFrame.getPixel(smpX, smpY);
+
+ if (compareColor(reference_color, rendered_color, colorThreshold, diff))
+ matchFound = true;
+
+ smpDiff = min(smpDiff, diff);
+ }
+ }
+
+ maxDiff = tcu::max(maxDiff, smpDiff);
+ errorMask.setPixel(matchFound ? tcu::IVec4(0, 0xff, 0, 0xff) : tcu::IVec4(0xff, 0, 0, 0xff), x, y);
+
+ // Color mismatch
+ if (!matchFound)
+ {
+ isOk = false;
+ }
+ }
+ }
+
+ const tcu::ConstPixelBufferAccess result = rendered.getAccess();
+ const tcu::ConstPixelBufferAccess reference = referenceFrame.getAccess();
+ const char* imageSetName = "Result";
+ const char* imageSetDesc = "Image comparison result";
+ tcu::Vec4 pixelBias (0.0f, 0.0f, 0.0f, 0.0f);
+ tcu::Vec4 pixelScale (1.0f, 1.0f, 1.0f, 1.0f);
+
+ if (!isOk)
+ {
+ // 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;
+ }
+
+ log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", color threshold = " << colorThreshold.toIVec().cast<deUint32>()
+ << ", coordinates threshold = " << coordThreshold << TestLog::EndMessage;
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result)
+ << TestLog::Image("ErrorMask", "Error mask", errorMask)
+ << TestLog::EndImageSet;
+ }
+ else
+ {
+ if (result.getFormat() != tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))
+ computePixelScaleBias(result, pixelScale, pixelBias);
+
+ log << TestLog::ImageSet(imageSetName, imageSetDesc)
+ << TestLog::Image("Result", "Result", result, pixelScale, pixelBias)
+ << TestLog::EndImageSet;
+ }
+
+
+ return true;
+}
+
tcu::TestStatus Compressed2DTestInstance::iterate (void)
{
tcu::TestLog& log = m_context.getTestContext().getLog();
const pipeline::TestTexture2D& texture = m_renderer.get2DTexture(0);
const tcu::TextureFormat textureFormat = texture.getTextureFormat();
const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(textureFormat);
+ const deUint32 mipLevel = m_testParameters.mipmaps ? 1 : 0;
ReferenceParams sampleParams (TEXTURETYPE_2D);
tcu::Surface rendered (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
sampleParams.lodMode = LODMODE_EXACT;
if (m_testParameters.mipmaps) {
- sampleParams.minLod = 1;
- sampleParams.maxLod = 1;
+ sampleParams.minLod = (float)mipLevel;
+ sampleParams.maxLod = (float)mipLevel;
}
if (isAstcFormat(m_compressedFormat)
// Compute reference.
const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
const tcu::PixelFormat pixelFormat (formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
- tcu::Surface referenceFrame (m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
- sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat), m_texture->getTexture(), &texCoord[0], sampleParams);
// Compare and log.
tcu::RGBA threshold;
else
threshold = pixelFormat.getColorThreshold() + tcu::RGBA(2, 2, 2, 2);
- const bool isOk = compareImages(log, referenceFrame, rendered, threshold);
+ constexpr float coordThreshold = 0.01f;
+ const bool isOk = validateTexture(log, rendered, texture.getTexture(), texCoord, mipLevel, pixelFormat, threshold, coordThreshold, sampleParams);
return isOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Image verification failed");
}
const pipeline::TestTexture3D& texture = m_renderer3D.get3DTexture(0);
const tcu::TextureFormat textureFormat = texture.getTextureFormat();
const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(textureFormat);
+ const deUint32 mipLevel = m_testParameters.mipmaps ? 1 : 0;
ReferenceParams sampleParams (TEXTURETYPE_3D);
tcu::Surface rendered (m_renderer3D.getRenderWidth(), m_renderer3D.getRenderHeight());
sampleParams.lodMode = LODMODE_EXACT;
if (m_testParameters.mipmaps) {
- sampleParams.minLod = 1;
- sampleParams.maxLod = 1;
+ sampleParams.minLod = (float)mipLevel;
+ sampleParams.maxLod = (float)mipLevel;
}
if (isAstcFormat(m_compressedFormat)
sliceNdx = (m_testParameters.depth - 1) * s / (slices - 1);
// Render texture.
- z = ((float)sliceNdx + 0.5f) / (float)m_testParameters.depth;
+ z = (((float)sliceNdx + 0.5f) / (float)(m_testParameters.depth >> mipLevel));
computeQuadTexCoord3D(texCoord, tcu::Vec3(0.0f, 0.0f, z), tcu::Vec3(1.0f, 1.0f, z), tcu::IVec3(0,1,2));
m_renderer3D.renderQuad(rendered, 0, &texCoord[0], sampleParams);
- // Compute reference.
- tcu::Surface referenceFrame (m_renderer3D.getRenderWidth(), m_renderer3D.getRenderHeight());
- sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat), m_texture3D->getTexture(), &texCoord[0], sampleParams);
-
- // Compare and log.
- isOk = compareImages(log, referenceFrame, rendered, threshold);
+ constexpr float coordThreshold = 0.01f;
+ isOk = validateTexture(log, rendered, m_texture3D->getTexture(), texCoord, mipLevel, pixelFormat, threshold, coordThreshold, sampleParams);
if (!isOk)
break;