Improve precision handling in texture.explicit_lod
authorPyry Haulos <phaulos@google.com>
Mon, 13 Feb 2017 21:11:53 +0000 (13:11 -0800)
committerPyry Haulos <phaulos@google.com>
Thu, 9 Mar 2017 23:28:51 +0000 (15:28 -0800)
This change improves precision requirement handling in
dEQP-VK.texture.explicit_lod test group by adding separate controls for
format conversion and filtering math.

Changed tests:
dEQP-VK.texture.explicit_lod.*

Components: Vulkan

Change-Id: Id64da1d63d87d02c73c757a3f2d5d50f2fbc19c0
(cherry picked from commit 4269dc0c1e513c550d3d45c16f2760450dfcef5c)

external/vulkancts/modules/vulkan/texture/vktSampleVerifier.cpp
external/vulkancts/modules/vulkan/texture/vktSampleVerifier.hpp
external/vulkancts/modules/vulkan/texture/vktSampleVerifierUtil.cpp
external/vulkancts/modules/vulkan/texture/vktTextureFilteringExplicitLodTests.cpp

index 8e99e63..0c26d37 100644 (file)
@@ -67,16 +67,18 @@ SampleVerifier::SampleVerifier (const ImageViewParameters&                                          imParams,
                                                                const SampleLookupSettings&                                             sampleLookupSettings,
                                                                int                                                                                             coordBits,
                                                                int                                                                                             mipmapBits,
-                                                               const std::vector<tcu::ConstPixelBufferAccess>& pba)
-// \todo [2016-07-29 collinbaker] Get rid of magic numbers
-       : m_internalFormat                      (-14, 15, 10, true) // fp16 format
-       , m_imParams                            (imParams)
+                                                               const tcu::FloatFormat&                                                 conversionPrecision,
+                                                               const tcu::FloatFormat&                                                 filteringPrecision,
+                                                               const std::vector<tcu::ConstPixelBufferAccess>& levels)
+       : m_imParams                            (imParams)
        , m_samplerParams                       (samplerParams)
        , m_sampleLookupSettings        (sampleLookupSettings)
        , m_coordBits                           (coordBits)
        , m_mipmapBits                          (mipmapBits)
+       , m_conversionPrecision         (conversionPrecision)
+       , m_filteringPrecision          (filteringPrecision)
        , m_unnormalizedDim                     (calcUnnormalizedDim(imParams.dim))
-       , m_pba                                         (pba)
+       , m_levels                                      (levels)
 {
 
 }
@@ -85,7 +87,7 @@ bool SampleVerifier::coordOutOfRange (const IVec3& coord, int compNdx, int level
 {
        DE_ASSERT(compNdx >= 0 && compNdx < 3);
 
-       return coord[compNdx] < 0 || coord[compNdx] >= m_pba[level].getSize()[compNdx];
+       return coord[compNdx] < 0 || coord[compNdx] >= m_levels[level].getSize()[compNdx];
 }
 
 void SampleVerifier::fetchTexelWrapped (const IVec3&   coord,
@@ -98,18 +100,29 @@ void SampleVerifier::fetchTexelWrapped (const IVec3&       coord,
 
        if (m_imParams.dim == IMG_DIM_1D)
        {
-           pixelPtr = m_pba[level].getPixelPtr(coord[0], layer, 0);
+           pixelPtr = m_levels[level].getPixelPtr(coord[0], layer, 0);
        }
        else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
        {
-               pixelPtr = m_pba[level].getPixelPtr(coord[0], coord[1], layer);
+               pixelPtr = m_levels[level].getPixelPtr(coord[0], coord[1], layer);
        }
        else
        {
-               pixelPtr = m_pba[level].getPixelPtr(coord[0], coord[1], coord[2]);
+               pixelPtr = m_levels[level].getPixelPtr(coord[0], coord[1], coord[2]);
        }
 
-       convertFormat(pixelPtr, mapVkFormat(m_imParams.format), m_internalFormat, resultMin, resultMax);
+       convertFormat(pixelPtr, mapVkFormat(m_imParams.format), m_conversionPrecision, resultMin, resultMax);
+
+#if defined(DE_DEBUG)
+       // Make sure tcuTexture agrees
+       const tcu::ConstPixelBufferAccess&      levelAccess     = m_levels[level];
+       const tcu::Vec4                                         refPix          = (m_imParams.dim == IMG_DIM_1D) ? levelAccess.getPixel(coord[0], layer, 0)
+                                                                                                       : (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE) ? levelAccess.getPixel(coord[0], coord[1], layer)
+                                                                                                       : levelAccess.getPixel(coord[0], coord[1], coord[2]);
+
+       for (int c = 0; c < 4; c++)
+               DE_ASSERT(de::inRange(refPix[c], resultMin[c], resultMax[c]));
+#endif
 }
 
 void SampleVerifier::fetchTexel (const IVec3&  coordIn,
@@ -148,7 +161,7 @@ void SampleVerifier::fetchTexel (const IVec3&       coordIn,
                        int             newFace = 0;
 
                        wrapCubemapEdge(coord.swizzle(0, 1),
-                                                       m_pba[level].getSize().swizzle(0, 1),
+                                                       m_levels[level].getSize().swizzle(0, 1),
                                                        arrayFace,
                                                        newCoord,
                                                        newFace);
@@ -164,7 +177,7 @@ void SampleVerifier::fetchTexel (const IVec3&       coordIn,
                        IVec2 cornerCoords[3];
 
                        wrapCubemapCorner(coord.swizzle(0, 1),
-                                                         m_pba[level].getSize().swizzle(0, 1),
+                                                         m_levels[level].getSize().swizzle(0, 1),
                                                          arrayFace,
                                                          faces[1],
                                                          faces[2],
@@ -182,11 +195,11 @@ void SampleVerifier::fetchTexel (const IVec3&     coordIn,
 
                                if (isSrgb)
                                {
-                                   cornerTexels[ndx] += sRGBToLinear(m_pba[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer));
+                                   cornerTexels[ndx] += sRGBToLinear(m_levels[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer));
                                }
                                else
                                {
-                                       cornerTexels[ndx] += m_pba[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer);
+                                       cornerTexels[ndx] += m_levels[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer);
                                }
                        }
 
@@ -225,7 +238,7 @@ void SampleVerifier::fetchTexel (const IVec3&       coordIn,
 
                for (int compNdx = 0; compNdx < 3; ++compNdx)
                {
-                       const int size = m_pba[level].getSize()[compNdx];
+                       const int size = m_levels[level].getSize()[compNdx];
 
                        coord[compNdx] = wrapTexelCoord(coord[compNdx], size, wrappingModes[compNdx]);
                }
@@ -298,13 +311,13 @@ void SampleVerifier::getFilteredSample1D (const IVec3&    texelBase,
 
     for (int i = 0; i < 2; ++i)
        {
-               const Interval weightInterval = m_internalFormat.roundOut(Interval(i == 0 ? 1.0f - weight : weight), false);
+               const Interval weightInterval = m_filteringPrecision.roundOut(Interval(i == 0 ? 1.0f - weight : weight), false);
 
                for (int compNdx = 0; compNdx < 4; ++compNdx)
                {
                        const Interval texelInterval(false, texelsMin[i][compNdx], texelsMax[i][compNdx]);
 
-                       resultIntervals[compNdx] = m_internalFormat.roundOut(resultIntervals[compNdx] + weightInterval * texelInterval, false);
+                       resultIntervals[compNdx] = m_filteringPrecision.roundOut(resultIntervals[compNdx] + weightInterval * texelInterval, false);
                }
        }
 
@@ -343,17 +356,17 @@ void SampleVerifier::getFilteredSample2D (const IVec3&    texelBase,
 
        for (int i = 0; i < 2; ++i)
        {
-               const Interval iWeightInterval = m_internalFormat.roundOut(Interval(i == 0 ? 1.0f - weights[1] : weights[1]), false);
+               const Interval iWeightInterval = m_filteringPrecision.roundOut(Interval(i == 0 ? 1.0f - weights[1] : weights[1]), false);
 
                for (int j = 0; j < 2; ++j)
                {
-                   const Interval jWeightInterval = m_internalFormat.roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[0] : weights[0]), false);
+                   const Interval jWeightInterval = m_filteringPrecision.roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[0] : weights[0]), false);
 
                        for (int compNdx = 0; compNdx < 4; ++compNdx)
                        {
                                const Interval texelInterval(false, texelsMin[2 * i + j][compNdx], texelsMax[2 * i + j][compNdx]);
 
-                               resultIntervals[compNdx] = m_internalFormat.roundOut(resultIntervals[compNdx] + jWeightInterval * texelInterval, false);
+                               resultIntervals[compNdx] = m_filteringPrecision.roundOut(resultIntervals[compNdx] + jWeightInterval * texelInterval, false);
                        }
                }
        }
@@ -395,21 +408,21 @@ void SampleVerifier::getFilteredSample3D (const IVec3&    texelBase,
 
        for (int i = 0; i < 2; ++i)
        {
-           const Interval iWeightInterval = m_internalFormat.roundOut(Interval(i == 0 ? 1.0f - weights[2] : weights[2]), false);
+           const Interval iWeightInterval = m_filteringPrecision.roundOut(Interval(i == 0 ? 1.0f - weights[2] : weights[2]), false);
 
                for (int j = 0; j < 2; ++j)
                {
-                   const Interval jWeightInterval = m_internalFormat.roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[1] : weights[1]), false);
+                   const Interval jWeightInterval = m_filteringPrecision.roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[1] : weights[1]), false);
 
                        for (int k = 0; k < 2; ++k)
                        {
-                           const Interval kWeightInterval = m_internalFormat.roundOut(jWeightInterval * Interval(k == 0 ? 1.0f - weights[0] : weights[0]), false);
+                           const Interval kWeightInterval = m_filteringPrecision.roundOut(jWeightInterval * Interval(k == 0 ? 1.0f - weights[0] : weights[0]), false);
 
                                for (int compNdx = 0; compNdx < 4; ++compNdx)
                                {
                                        const Interval texelInterval(false, texelsMin[4 * i + 2 * j + k][compNdx], texelsMax[4 * i + 2 * j + k][compNdx]);
 
-                                       resultIntervals[compNdx] = m_internalFormat.roundOut(resultIntervals[compNdx] + kWeightInterval * texelInterval, false);
+                                       resultIntervals[compNdx] = m_filteringPrecision.roundOut(resultIntervals[compNdx] + kWeightInterval * texelInterval, false);
                                }
                        }
                }
@@ -556,7 +569,7 @@ bool SampleVerifier::verifySampleFiltered (const Vec4&                      result,
                                const Interval idealSampleHi(false, idealSampleHiMin[compNdx], idealSampleHiMax[compNdx]);
 
                                const Interval idealSample
-                                       = m_internalFormat.roundOut(Interval(weight) * idealSampleLo + Interval(1.0f - weight) * idealSampleHi, false);
+                                       = m_filteringPrecision.roundOut(Interval(weight) * idealSampleLo + Interval(1.0f - weight) * idealSampleHi, false);
 
                                idealSampleMin[compNdx] = (float)idealSample.lo();
                                idealSampleMax[compNdx] = (float)idealSample.hi();
@@ -704,7 +717,7 @@ bool SampleVerifier::verifySampleMipmapLevel (const SampleArguments&        args,
        const FloatFormat coordFormat(-32, 32, 16, true);
 
        calcUnnormalizedCoordRange(coord,
-                                                          m_pba[level].getSize(),
+                                                          m_levels[level].getSize(),
                                                           coordFormat,
                                                           unnormalizedCoordMin[0],
                                                           unnormalizedCoordMax[0]);
@@ -721,7 +734,7 @@ bool SampleVerifier::verifySampleMipmapLevel (const SampleArguments&        args,
        if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
        {
                calcUnnormalizedCoordRange(coord,
-                                                                  m_pba[level+1].getSize(),
+                                                                  m_levels[level+1].getSize(),
                                                                   coordFormat,
                                                                   unnormalizedCoordMin[1],
                                                                   unnormalizedCoordMax[1]);
index e68107a..6b84601 100644 (file)
@@ -127,7 +127,9 @@ public:
                                                                                 const SampleLookupSettings&                                            sampleLookupSettings,
                                                                                 int                                                                                            coordBits,
                                                                                 int                                                                                            mipmapBits,
-                                                                                const std::vector<tcu::ConstPixelBufferAccess>&        pba);
+                                                                                const tcu::FloatFormat&                                                        conversionPrecision,
+                                                                                const tcu::FloatFormat&                                                        filteringPrecision,
+                                                                                const std::vector<tcu::ConstPixelBufferAccess>&        levels);
 
        bool verifySample                                       (const SampleArguments&                                                         args,
                                                                                 const tcu::Vec4&                                                                       result) const;
@@ -227,18 +229,18 @@ private:
                                                                                 deInt32&                                                                                       stepMin,
                                                                                 deInt32&                                                                                       stepMax) const;
 
-       const tcu::FloatFormat                                                  m_internalFormat;
-
        const ImageViewParameters&                                              m_imParams;
        const SamplerParameters&                                                m_samplerParams;
        const SampleLookupSettings&                                             m_sampleLookupSettings;
 
     const int                                                                          m_coordBits;
        const int                                                                               m_mipmapBits;
+       const tcu::FloatFormat                                                  m_conversionPrecision;
+       const tcu::FloatFormat                                                  m_filteringPrecision;
 
        const int                                                                               m_unnormalizedDim;
 
-       const std::vector<tcu::ConstPixelBufferAccess>& m_pba;
+       const std::vector<tcu::ConstPixelBufferAccess>& m_levels;
 };
 
 } // texture
index c7ad274..b26c315 100644 (file)
@@ -751,7 +751,7 @@ deUint64 unpackBits (const BaseType pack,
 
        const BaseType mask = (BaseType) (((BaseType) 1 << (BaseType) numBits) - (BaseType) 1);
 
-    return mask & (pack >> (BaseType) (8 * (int) sizeof(BaseType) - bitOffset - numBits));
+       return mask & (pack >> (BaseType) (8 * (int) sizeof(BaseType) - bitOffset - numBits));
 }
 
 deUint64 readChannel (const void* ptr,
index c9c6941..fd080d3 100644 (file)
@@ -35,6 +35,8 @@
 #include "vkRef.hpp"
 #include "vkRefUtil.hpp"
 #include "vkStrUtil.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkQueryUtil.hpp"
 
 #include "tcuTexLookupVerifier.hpp"
 #include "tcuTestLog.hpp"
@@ -63,6 +65,89 @@ using std::string;
 namespace
 {
 
+tcu::FloatFormat getConversionPrecision (VkFormat format)
+{
+       const tcu::FloatFormat  reallyLow       (0, 0, 8, false, tcu::YES);
+       const tcu::FloatFormat  fp16            (-14, 15, 10, false);
+       const tcu::FloatFormat  fp32            (-126, 127, 23, true);
+
+       switch (format)
+       {
+           case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
+               case VK_FORMAT_R5G6B5_UNORM_PACK16:
+               case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
+                       return reallyLow;
+
+               case VK_FORMAT_R8_UNORM:
+               case VK_FORMAT_R8_SNORM:
+               case VK_FORMAT_R8G8_UNORM:
+               case VK_FORMAT_R8G8_SNORM:
+               case VK_FORMAT_R8G8B8A8_UNORM:
+               case VK_FORMAT_R8G8B8A8_SNORM:
+               case VK_FORMAT_B8G8R8A8_UNORM:
+               case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
+               case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
+               case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+                       return fp16;
+
+               case VK_FORMAT_R16_SFLOAT:
+               case VK_FORMAT_R16G16_SFLOAT:
+               case VK_FORMAT_R16G16B16A16_SFLOAT:
+                       return fp16;
+
+               case VK_FORMAT_R32_SFLOAT:
+               case VK_FORMAT_R32G32_SFLOAT:
+               case VK_FORMAT_R32G32B32A32_SFLOAT:
+                       return fp32;
+
+               default:
+                       DE_FATAL("Precision not defined for format");
+                       return fp32;
+       }
+}
+
+tcu::FloatFormat getFilteringPrecision (VkFormat format)
+{
+       const tcu::FloatFormat  reallyLow       (0, 0, 6, false, tcu::YES);
+       const tcu::FloatFormat  low                     (0, 0, 7, false, tcu::YES);
+       const tcu::FloatFormat  fp16            (-14, 15, 10, false);
+       const tcu::FloatFormat  fp32            (-126, 127, 23, true);
+
+       switch (format)
+       {
+           case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
+               case VK_FORMAT_R5G6B5_UNORM_PACK16:
+               case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
+                       return reallyLow;
+
+               case VK_FORMAT_R8_UNORM:
+               case VK_FORMAT_R8_SNORM:
+               case VK_FORMAT_R8G8_UNORM:
+               case VK_FORMAT_R8G8_SNORM:
+               case VK_FORMAT_R8G8B8A8_UNORM:
+               case VK_FORMAT_R8G8B8A8_SNORM:
+               case VK_FORMAT_B8G8R8A8_UNORM:
+               case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
+               case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
+               case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+                       return low;
+
+               case VK_FORMAT_R16_SFLOAT:
+               case VK_FORMAT_R16G16_SFLOAT:
+               case VK_FORMAT_R16G16B16A16_SFLOAT:
+                       return fp16;
+
+               case VK_FORMAT_R32_SFLOAT:
+               case VK_FORMAT_R32G32_SFLOAT:
+               case VK_FORMAT_R32G32B32A32_SFLOAT:
+                       return fp32;
+
+               default:
+                       DE_FATAL("Precision not defined for format");
+                       return fp32;
+       }
+}
+
 using namespace shaderexecutor;
 
 string genSamplerDeclaration(const ImageViewParameters& imParams,
@@ -568,104 +653,78 @@ public:
        virtual std::vector<SampleArguments>            getSampleArgs   (void) const = 0;
 
 protected:
-       DataGenerator (void) {}
+                                                                                               DataGenerator   (void) {}
 };
 
 class TextureFilteringTestInstance : public TestInstance
 {
 public:
-       TextureFilteringTestInstance (Context&                                          ctx,
-                                                                 const TestCaseData&                   testCaseData,
-                                                                 ShaderExecutor&                               shaderExecutor,
-                                                                 de::MovePtr<DataGenerator>    gen)
-
-               : TestInstance                          (ctx)
-               , m_imParams                            (testCaseData.imParams)
-               , m_samplerParams                       (testCaseData.samplerParams)
-               , m_sampleLookupSettings        (testCaseData.sampleLookupSettings)
-               , m_shaderExecutor                      (shaderExecutor)
-               , m_ctx                                         (ctx)
-               , m_vki                                         (m_ctx.getInstanceInterface())
-               , m_vkd                                         (m_ctx.getDeviceInterface())
-               , m_instance                            (m_ctx.getInstance())
-               , m_physicalDevice                      (m_ctx.getPhysicalDevice())
-               , m_device                                      (m_ctx.getDevice())
-               , m_uqfi                                        (m_ctx.getUniversalQueueFamilyIndex())
-               , m_pba                                         (testCaseData.pba)
-               , m_gen                                         (gen.release())
-       {
-               for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
-               {
-                       DE_ASSERT(m_imParams.size[compNdx] > 0);
-               }
+                                                                               TextureFilteringTestInstance    (Context&                                       ctx,
+                                                                                                                                                const TestCaseData&            testCaseData,
+                                                                                                                                                ShaderExecutor&                        shaderExecutor,
+                                                                                                                                                de::MovePtr<DataGenerator>     gen);
 
-               m_imExtent.width  = m_imParams.size[0];
-               m_imExtent.height = m_imParams.size[1];
-               m_imExtent.depth  = m_imParams.size[2];
-       }
-
-       virtual TestStatus iterate (void)
-       {
-               return runTest();
-       }
+       virtual TestStatus                                      iterate                                                 (void) { return runTest(); }
 
 protected:
-       TestStatus      runTest                 (void);
-       bool            isSupported             (void);
-       void            createResources (void);
-       void            execute                 (void);
-       bool            verify                  (void);
+       TestStatus                                                      runTest                                                 (void);
+       bool                                                            isSupported                                             (void);
+       void                                                            createResources                                 (void);
+       void                                                            execute                                                 (void);
+       bool                                                            verify                                                  (void);
 
-       tcu::Sampler mapTcuSampler      (void);
+       tcu::Sampler                                            mapTcuSampler                                   (void) const;
 
-       const ImageViewParameters&                      m_imParams;
-       const SamplerParameters&                        m_samplerParams;
-       const SampleLookupSettings&                     m_sampleLookupSettings;
+       const ImageViewParameters                       m_imParams;
+       const SamplerParameters                         m_samplerParams;
+       const SampleLookupSettings                      m_sampleLookupSettings;
 
        std::vector<SampleArguments>            m_sampleArguments;
        deUint32                                                        m_numSamples;
 
        ShaderExecutor&                                         m_shaderExecutor;
-       Context&                                                        m_ctx;
-       const InstanceInterface&                        m_vki;
-       const DeviceInterface&                          m_vkd;
-       VkInstance                                                      m_instance;
-       VkPhysicalDevice                                        m_physicalDevice;
-       VkDevice                                                        m_device;
-       deUint32                                                        m_uqfi;
-
-       VkExtent3D                                                      m_imExtent;
-
-    int                                                                        m_coordBits;
-       int                                                                     m_mipmapBits;
 
        de::MovePtr<Allocation>                         m_imAllocation;
        Move<VkImage>                                           m_im;
        Move<VkImageView>                                       m_imView;
        Move<VkSampler>                                         m_sampler;
 
-       std::vector<ConstPixelBufferAccess> m_pba;
+       std::vector<ConstPixelBufferAccess> m_levels;
        de::MovePtr<DataGenerator>                      m_gen;
 
        std::vector<Vec4>                                       m_resultSamples;
        std::vector<Vec4>                                       m_resultCoords;
 };
 
+TextureFilteringTestInstance::TextureFilteringTestInstance (Context&                                   ctx,
+                                                                                                                       const TestCaseData&                     testCaseData,
+                                                                                                                       ShaderExecutor&                         shaderExecutor,
+                                                                                                                       de::MovePtr<DataGenerator>      gen)
+       : TestInstance                          (ctx)
+       , m_imParams                            (testCaseData.imParams)
+       , m_samplerParams                       (testCaseData.samplerParams)
+       , m_sampleLookupSettings        (testCaseData.sampleLookupSettings)
+       , m_shaderExecutor                      (shaderExecutor)
+       , m_levels                                      (testCaseData.pba)
+       , m_gen                                         (gen.release())
+{
+       for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
+               DE_ASSERT(m_imParams.size[compNdx] > 0);
+}
+
 TestStatus TextureFilteringTestInstance::runTest (void)
 {
        if (!isSupported())
-       {
            TCU_THROW(NotSupportedError, "Unsupported combination of filtering and image format");
-       }
 
        TCU_CHECK(m_gen->generate());
-       m_pba =   m_gen->getPba();
+       m_levels = m_gen->getPba();
 
        m_sampleArguments = m_gen->getSampleArgs();
        m_numSamples = (deUint32)m_sampleArguments.size();
 
        createResources();
-       initializeImage(m_ctx, m_im.get(), &m_pba[0], m_imParams);
+       initializeImage(m_context, m_im.get(), &m_levels[0], m_imParams);
 
        m_shaderExecutor.addSamplerUniform(0, m_imView.get(), m_sampler.get());
 
@@ -675,21 +734,21 @@ TestStatus TextureFilteringTestInstance::runTest (void)
        execute();
        endTime = deGetMicroseconds();
 
-       m_ctx.getTestContext().getLog() << TestLog::Message
-                                                                       << "Execution time: "
-                                                                       << endTime - startTime
-                                                                       << "us"
-                                                                       << TestLog::EndMessage;
+       m_context.getTestContext().getLog() << TestLog::Message
+                                                                               << "Execution time: "
+                                                                               << endTime - startTime
+                                                                               << "us"
+                                                                               << TestLog::EndMessage;
 
     startTime = deGetMicroseconds();
        bool result = verify();
     endTime = deGetMicroseconds();
 
-       m_ctx.getTestContext().getLog() << TestLog::Message
-                                                                       << "Verification time: "
-                                                                       << endTime - startTime
-                                                                       << "us"
-                                                                       << TestLog::EndMessage;
+       m_context.getTestContext().getLog() << TestLog::Message
+                                                                               << "Verification time: "
+                                                                               << endTime - startTime
+                                                                               << "us"
+                                                                               << TestLog::EndMessage;
 
        if (result)
        {
@@ -706,18 +765,20 @@ bool TextureFilteringTestInstance::verify (void)
 {
        // \todo [2016-06-24 collinbaker] Handle cubemaps
 
-       m_coordBits  = (deUint8) m_ctx.getDeviceProperties().limits.subTexelPrecisionBits;
-       m_mipmapBits = (deUint8) m_ctx.getDeviceProperties().limits.mipmapPrecisionBits;
+       const int                               coordBits                       = (int)m_context.getDeviceProperties().limits.subTexelPrecisionBits;
+       const int                               mipmapBits                      = (int)m_context.getDeviceProperties().limits.mipmapPrecisionBits;
+       const int                               maxPrintedFailures      = 5;
+       int                                             failCount                       = 0;
 
-       SampleVerifier verifier(m_imParams,
-                                                       m_samplerParams,
-                                                       m_sampleLookupSettings,
-                                                       m_coordBits,
-                                                       m_mipmapBits,
-                                                       m_pba);
+       const SampleVerifier    verifier                        (m_imParams,
+                                                                                                m_samplerParams,
+                                                                                                m_sampleLookupSettings,
+                                                                                                coordBits,
+                                                                                                mipmapBits,
+                                                                                                getConversionPrecision(m_imParams.format),
+                                                                                                getFilteringPrecision(m_imParams.format),
+                                                                                                m_levels);
 
-       const int maxPrintedFailures = 5;
-       int failCount = 0;
 
        for (deUint32 sampleNdx = 0; sampleNdx < m_numSamples; ++sampleNdx)
        {
@@ -729,7 +790,7 @@ bool TextureFilteringTestInstance::verify (void)
                                std::string report;
                                verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report);
 
-                               m_ctx.getTestContext().getLog()
+                               m_context.getTestContext().getLog()
                                        << TestLog::Section("Failed sample", "Failed sample")
                                        << TestLog::Message
                                        << "Sample " << sampleNdx << ".\n"
@@ -743,7 +804,7 @@ bool TextureFilteringTestInstance::verify (void)
                }
        }
 
-       m_ctx.getTestContext().getLog()
+       m_context.getTestContext().getLog()
                << TestLog::Message
                << "Passed " << m_numSamples - failCount << " out of " << m_numSamples << "."
                << TestLog::EndMessage;
@@ -793,7 +854,7 @@ void TextureFilteringTestInstance::execute (void)
                reinterpret_cast<void*>(&resultCoordsTemp[0])
        };
 
-       m_shaderExecutor.execute(m_ctx, m_numSamples, inputs, outputs);
+       m_shaderExecutor.execute(m_context, m_numSamples, inputs, outputs);
 
        m_resultSamples.resize(m_numSamples);
        m_resultCoords .resize(m_numSamples);
@@ -816,42 +877,46 @@ void TextureFilteringTestInstance::createResources (void)
 {
        // Create VkImage
 
-       const VkImageCreateFlags imCreateFlags =
-               (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
-
-       const VkImageCreateInfo imCreateInfo =
-       {
-               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                    // sType
-               DE_NULL,                                                                                                                // pNext
-               imCreateFlags,                                                                                                  // flags
-           mapImageType(m_imParams.dim),                                                                       // imageType
-           m_imParams.format,                                                                                          // format
-               m_imExtent,                                                                                                             // extent
-           (deUint32)m_imParams.levels,                                                                        // mipLevels
-           (deUint32)m_imParams.arrayLayers,                                                           // arrayLayers
-               VK_SAMPLE_COUNT_1_BIT,                                                                                  // samples
-               VK_IMAGE_TILING_OPTIMAL,                                                                                // tiling
-               VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,   // usage
-               VK_SHARING_MODE_EXCLUSIVE,                                                                              // sharingMode
-               1,                                                                                                                              // queueFamilyIndexCount
-               &m_uqfi,                                                                                                                // pQueueFamilyIndices
-               VK_IMAGE_LAYOUT_UNDEFINED                                                                               // initialLayout
+       const DeviceInterface&          vkd                             = m_context.getDeviceInterface();
+       const VkDevice                          device                  = m_context.getDevice();
+
+       const deUint32                          queueFamily             = m_context.getUniversalQueueFamilyIndex();
+       const VkImageCreateFlags        imCreateFlags   =(m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
+
+       const VkImageCreateInfo         imCreateInfo    =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+               DE_NULL,
+               imCreateFlags,
+           mapImageType(m_imParams.dim),
+           m_imParams.format,
+               makeExtent3D(m_imParams.size[0], m_imParams.size[1], m_imParams.size[2]),
+           (deUint32)m_imParams.levels,
+           (deUint32)m_imParams.arrayLayers,
+               VK_SAMPLE_COUNT_1_BIT,
+               VK_IMAGE_TILING_OPTIMAL,
+               VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+               VK_SHARING_MODE_EXCLUSIVE,
+               1,
+               &queueFamily,
+               VK_IMAGE_LAYOUT_UNDEFINED
        };
 
-    m_im = createImage(m_vkd, m_device, &imCreateInfo);
+    m_im = createImage(vkd, device, &imCreateInfo);
 
        // Allocate memory for image
 
        VkMemoryRequirements imMemReq;
-       m_vkd.getImageMemoryRequirements(m_device, m_im.get(), &imMemReq);
+       vkd.getImageMemoryRequirements(device, m_im.get(), &imMemReq);
 
-       m_imAllocation = m_ctx.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any);
-       VK_CHECK(m_vkd.bindImageMemory(m_device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset()));
+       m_imAllocation = m_context.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any);
+       VK_CHECK(vkd.bindImageMemory(device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset()));
 
        // Create VkImageView
 
        // \todo [2016-06-23 collinbaker] Pick aspectMask based on image type (i.e. support depth and/or stencil images)
-       VkImageSubresourceRange imViewSubresourceRange =
+       DE_ASSERT(m_imParams.dim != IMG_DIM_CUBE); // \todo Support cube maps
+       const VkImageSubresourceRange imViewSubresourceRange =
        {
                VK_IMAGE_ASPECT_COLOR_BIT,                      // aspectMask
                0,                                                                      // baseMipLevel
@@ -860,11 +925,6 @@ void TextureFilteringTestInstance::createResources (void)
                (deUint32)m_imParams.arrayLayers        // layerCount
        };
 
-       if (m_imParams.dim == IMG_DIM_CUBE)
-       {
-               imViewSubresourceRange.layerCount *= 6;
-       }
-
        const VkComponentMapping imViewCompMap =
        {
                VK_COMPONENT_SWIZZLE_R,
@@ -885,44 +945,46 @@ void TextureFilteringTestInstance::createResources (void)
                imViewSubresourceRange                                          // subresourceRange
        };
 
-       m_imView = createImageView(m_vkd, m_device, &imViewCreateInfo);
+       m_imView = createImageView(vkd, device, &imViewCreateInfo);
 
        // Create VkSampler
 
        const VkSamplerCreateInfo samplerCreateInfo = mapSamplerCreateInfo(m_samplerParams);
-       m_sampler = createSampler(m_vkd, m_device, &samplerCreateInfo);
+       m_sampler = createSampler(vkd, device, &samplerCreateInfo);
 }
 
-bool TextureFilteringTestInstance::isSupported (void)
+VkFormatFeatureFlags getRequiredFormatFeatures (const SamplerParameters& samplerParams)
 {
-       const VkImageCreateFlags imCreateFlags =
-               (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
+       VkFormatFeatureFlags    features        = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
 
-       VkImageFormatProperties imFormatProperties;
-       VkFormatProperties              formatProperties;
+       if (samplerParams.minFilter      == VK_FILTER_LINEAR ||
+               samplerParams.magFilter  == VK_FILTER_LINEAR ||
+               samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+       {
+               features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
+       }
 
-       m_vki.getPhysicalDeviceImageFormatProperties(m_physicalDevice,
-                                                                                                m_imParams.format,
-                                                                                                mapImageType(m_imParams.dim),
-                                                                                                VK_IMAGE_TILING_OPTIMAL,
-                                                                                                VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
-                                                                                                imCreateFlags,
-                                                                                                &imFormatProperties);
+       return features;
+}
 
-       m_vki.getPhysicalDeviceFormatProperties(         m_physicalDevice,
-                                                                                                m_imParams.format,
-                                                                                                &formatProperties);
+bool TextureFilteringTestInstance::isSupported (void)
+{
+       const VkImageCreateFlags                imCreateFlags           = (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
+       const VkFormatFeatureFlags              reqImFeatures           = getRequiredFormatFeatures(m_samplerParams);
+
+       const VkImageFormatProperties   imFormatProperties      = getPhysicalDeviceImageFormatProperties(m_context.getInstanceInterface(),
+                                                                                                                                                                                                m_context.getPhysicalDevice(),
+                                                                                                                                                                                                m_imParams.format,
+                                                                                                                                                                                                mapImageType(m_imParams.dim),
+                                                                                                                                                                                                VK_IMAGE_TILING_OPTIMAL,
+                                                                                                                                                                                                VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+                                                                                                                                                                                                imCreateFlags);
+       const VkFormatProperties                formatProperties        = getPhysicalDeviceFormatProperties(m_context.getInstanceInterface(),
+                                                                                                                                                                                       m_context.getPhysicalDevice(),
+                                                                                                                                                                                       m_imParams.format);
 
        // \todo [2016-06-23 collinbaker] Check image parameters against imFormatProperties
-
-       VkFormatFeatureFlags reqImFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
-
-       if (m_samplerParams.minFilter    == VK_FILTER_LINEAR ||
-               m_samplerParams.magFilter        == VK_FILTER_LINEAR ||
-               m_samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
-       {
-               reqImFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
-       }
+       DE_UNREF(imFormatProperties);
 
        return (formatProperties.optimalTilingFeatures & reqImFeatures) == reqImFeatures;
 }
@@ -930,9 +992,9 @@ bool TextureFilteringTestInstance::isSupported (void)
 class TextureFilteringTestCase : public TestCase
 {
 public:
-       TextureFilteringTestCase (tcu::TestContext& testCtx,
-                                                         const char* name,
-                                                         const char* description)
+       TextureFilteringTestCase (tcu::TestContext&     testCtx,
+                                                         const char*           name,
+                                                         const char*           description)
                : TestCase(testCtx, name, description)
        {
        }
@@ -988,16 +1050,16 @@ void TextureFilteringTestCase::init (void)
 class Texture2DGradientTestCase : public TextureFilteringTestCase
 {
 public:
-       Texture2DGradientTestCase (TestContext& testCtx,
-                                                          const char* name,
-                                                          const char* desc,
-                                                          TextureFormat format,
-                                                          IVec3 dimensions,
-                                                          VkFilter magFilter,
-                                                          VkFilter minFilter,
-                                                          VkSamplerMipmapMode mipmapFilter,
-                                                          VkSamplerAddressMode wrappingMode,
-                                                          bool useDerivatives)
+       Texture2DGradientTestCase (TestContext&                 testCtx,
+                                                          const char*                  name,
+                                                          const char*                  desc,
+                                                          TextureFormat                format,
+                                                          IVec3                                dimensions,
+                                                          VkFilter                             magFilter,
+                                                          VkFilter                             minFilter,
+                                                          VkSamplerMipmapMode  mipmapFilter,
+                                                          VkSamplerAddressMode wrappingMode,
+                                                          bool                                 useDerivatives)
 
                : TextureFilteringTestCase      (testCtx, name, desc)
                , m_format                                      (format)
@@ -1030,18 +1092,18 @@ protected:
 
                const SamplerParameters samplerParameters =
                {
-                       m_magFilter, // magFilter
-                       m_minFilter, // minFilter
-                       m_mipmapFilter, // mipmapFilter
-                   m_wrappingMode, // wrappingModeU
-                       m_wrappingMode, // wrappingModeV
-                       m_wrappingMode, // wrappingModeW
-                       VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, // borderColor
-                       0.0f, // lodBias
-                       -1.0f, // minLod
-                       50.0f, // maxLod
-                       false, // isUnnormalized
-                       false // isCompare
+                       m_magFilter,
+                       m_minFilter,
+                       m_mipmapFilter,
+                       m_wrappingMode,
+                       m_wrappingMode,
+                       m_wrappingMode,
+                       VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
+                       0.0f,
+                       -1.0f,
+                       50.0f,
+                       false,
+                       false
                };
 
                const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_dimensions[0],
@@ -1049,12 +1111,12 @@ protected:
 
                const ImageViewParameters imParameters =
                {
-                       IMG_DIM_2D, // dim
-                       mapTextureFormat(m_format), // format
-                       m_dimensions, // size
-                       numLevels, // levels
-                       false, // isArrayed
-                       1, // arrayLayers
+                       IMG_DIM_2D,
+                       mapTextureFormat(m_format),
+                       m_dimensions,
+                       numLevels,
+                       false,
+                       1,
                };
 
                const TestCaseData data =
@@ -1207,7 +1269,7 @@ TestCaseGroup* create2DFormatTests (TestContext& testCtx)
        de::MovePtr<TestCaseGroup> tests(
                new TestCaseGroup(testCtx, "formats", "Various image formats"));
 
-    VkFormat formats[] =
+    const VkFormat formats[] =
        {
            VK_FORMAT_B4G4R4A4_UNORM_PACK16,
                VK_FORMAT_R5G6B5_UNORM_PACK16,