Fixed non zero mip compressed texture tests failure
authorTomasz Owczarek <tomasz.owczarek@arm.com>
Tue, 5 Apr 2022 13:13:31 +0000 (14:13 +0100)
committerMatthew Netsch <quic_mnetsch@quicinc.com>
Thu, 14 Apr 2022 20:52:55 +0000 (20:52 +0000)
Fixed non zero mip compressed texture tests failure
when sampling coordinates at the edge of pixels.

Components: Vulkan

VK-GL-CTS Issue: 3619

Affects:
dEQP-VK.texture.compressed*_npot_mip1

Change-Id: I4bbc80831233ebcecc34612b7fa488e94dde630a

external/vulkancts/modules/vulkan/texture/vktTextureCompressedFormatTests.cpp

index 07bdf02..d5e220f 100644 (file)
 #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"
@@ -191,12 +193,180 @@ Compressed2DTestInstance::Compressed2DTestInstance (Context&                             context,
        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());
@@ -208,8 +378,8 @@ tcu::TestStatus Compressed2DTestInstance::iterate (void)
        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)
@@ -245,8 +415,6 @@ tcu::TestStatus Compressed2DTestInstance::iterate (void)
        // 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;
@@ -258,7 +426,8 @@ tcu::TestStatus Compressed2DTestInstance::iterate (void)
        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");
 }
@@ -322,6 +491,7 @@ tcu::TestStatus Compressed3DTestInstance::iterate (void)
        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());
@@ -333,8 +503,8 @@ tcu::TestStatus Compressed3DTestInstance::iterate (void)
        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)
@@ -386,16 +556,12 @@ tcu::TestStatus Compressed3DTestInstance::iterate (void)
                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;