Improvements to sample verification code
authorCollin Baker <collinbaker@google.com>
Mon, 25 Jul 2016 21:35:03 +0000 (14:35 -0700)
committerCollin Baker <collinbaker@google.com>
Wed, 10 Aug 2016 17:48:12 +0000 (10:48 -0700)
Refactoring and improvements to code in vktSampleVerifier.cpp;
Moved much functionality into separate functions and cleaned up some
quick fixes I had made previously.

Change-Id: I7a02ee0cbe009946ec1126e1e77141596cf1c028

12 files changed:
Android.mk
android/cts/master/com.drawelements.deqp.vk.xml
android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/texture_filtering/CMakeLists.txt
external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifier.cpp
external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifier.hpp
external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifierUtil.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifierUtil.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/texture_filtering/vktTextureFilteringExplicitLodTests.cpp
framework/common/tcuInterval.hpp
framework/common/tcuTexture.cpp
framework/common/tcuTexture.hpp

index 7a51356..e5c7836 100644 (file)
@@ -853,6 +853,7 @@ LOCAL_SRC_FILES := \
        external/vulkancts/modules/vulkan/tessellation/vktTessellationUtil.cpp \
        external/vulkancts/modules/vulkan/tessellation/vktTessellationWindingTests.cpp \
        external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifier.cpp \
+       external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifierUtil.cpp \
        external/vulkancts/modules/vulkan/texture_filtering/vktTextureFilteringTests.cpp \
        external/vulkancts/modules/vulkan/texture_filtering/vktTextureFilteringExplicitLodTests.cpp \
        external/vulkancts/modules/vulkan/ubo/vktRandomUniformBlockCase.cpp \
index d6b493f..0edc7c0 100644 (file)
                                                </Test>
                                        </TestCase>
                                        <TestCase name="formats">
-                                               <Test name="VK_FORMAT_B4G4R4A4_UNORM_PACK16_nearest">
+                                               <Test name="b4g4r4a4_unorm_pack16_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_B4G4R4A4_UNORM_PACK16_linear">
+                                               <Test name="b4g4r4a4_unorm_pack16_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R5G6B5_UNORM_PACK16_nearest">
+                                               <Test name="r5g6b5_unorm_pack16_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R5G6B5_UNORM_PACK16_linear">
+                                               <Test name="r5g6b5_unorm_pack16_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A1R5G5B5_UNORM_PACK16_nearest">
+                                               <Test name="a1r5g5b5_unorm_pack16_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A1R5G5B5_UNORM_PACK16_linear">
+                                               <Test name="a1r5g5b5_unorm_pack16_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8_UNORM_nearest">
+                                               <Test name="r8_unorm_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8_UNORM_linear">
+                                               <Test name="r8_unorm_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8_SNORM_nearest">
+                                               <Test name="r8_snorm_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8_SNORM_linear">
+                                               <Test name="r8_snorm_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8_UNORM_nearest">
+                                               <Test name="r8g8_unorm_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8_UNORM_linear">
+                                               <Test name="r8g8_unorm_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8_SNORM_nearest">
+                                               <Test name="r8g8_snorm_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8_SNORM_linear">
+                                               <Test name="r8g8_snorm_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8B8A8_UNORM_nearest">
+                                               <Test name="r8g8b8a8_unorm_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8B8A8_UNORM_linear">
+                                               <Test name="r8g8b8a8_unorm_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8B8A8_SNORM_nearest">
+                                               <Test name="r8g8b8a8_snorm_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8B8A8_SNORM_linear">
+                                               <Test name="r8g8b8a8_snorm_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8B8A8_SRGB_nearest">
+                                               <Test name="b8g8r8a8_unorm_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R8G8B8A8_SRGB_linear">
+                                               <Test name="b8g8r8a8_unorm_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_B8G8R8A8_UNORM_nearest">
+                                               <Test name="a8b8g8r8_unorm_pack32_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_B8G8R8A8_UNORM_linear">
+                                               <Test name="a8b8g8r8_unorm_pack32_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_B8G8R8A8_SRGB_nearest">
+                                               <Test name="a8b8g8r8_snorm_pack32_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_B8G8R8A8_SRGB_linear">
+                                               <Test name="a8b8g8r8_snorm_pack32_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A8B8G8R8_UNORM_PACK32_nearest">
+                                               <Test name="a2b10g10r10_unorm_pack32_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A8B8G8R8_UNORM_PACK32_linear">
+                                               <Test name="a2b10g10r10_unorm_pack32_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A8B8G8R8_SNORM_PACK32_nearest">
+                                               <Test name="r16_sfloat_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A8B8G8R8_SNORM_PACK32_linear">
+                                               <Test name="r16_sfloat_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A8B8G8R8_SRGB_PACK32_nearest">
+                                               <Test name="r16g16_sfloat_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A8B8G8R8_SRGB_PACK32_linear">
+                                               <Test name="r16g16_sfloat_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A2B10G10R10_UNORM_PACK32_nearest">
+                                               <Test name="r16g16b16a16_sfloat_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_A2B10G10R10_UNORM_PACK32_linear">
+                                               <Test name="r16g16b16a16_sfloat_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R16_SFLOAT_nearest">
+                                               <Test name="r32_sfloat_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R16_SFLOAT_linear">
+                                               <Test name="r32_sfloat_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R16G16_SFLOAT_nearest">
+                                               <Test name="r32g32_sfloat_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R16G16_SFLOAT_linear">
+                                               <Test name="r32g32_sfloat_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R16G16B16A16_SFLOAT_nearest">
+                                               <Test name="r32g32b32a32_sfloat_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_R16G16B16A16_SFLOAT_linear">
+                                               <Test name="r32g32b32a32_sfloat_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_B10G11R11_UFLOAT_PACK32_nearest">
+                                       </TestCase>
+                                       <TestCase name="derivatives">
+                                               <Test name="nearest_nearest_mipmap_nearest">
+                                                       <TestInstance/>
+                                               </Test>
+                                               <Test name="nearest_nearest_mipmap_linear">
+                                                       <TestInstance/>
+                                               </Test>
+                                               <Test name="nearest_linear_mipmap_nearest">
+                                                       <TestInstance/>
+                                               </Test>
+                                               <Test name="nearest_linear_mipmap_linear">
+                                                       <TestInstance/>
+                                               </Test>
+                                               <Test name="linear_nearest_mipmap_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_B10G11R11_UFLOAT_PACK32_linear">
+                                               <Test name="linear_nearest_mipmap_linear">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_E5B9G9R9_UFLOAT_PACK32_nearest">
+                                               <Test name="linear_linear_mipmap_nearest">
                                                        <TestInstance/>
                                                </Test>
-                                               <Test name="VK_FORMAT_E5B9G9R9_UFLOAT_PACK32_linear">
+                                               <Test name="linear_linear_mipmap_linear">
                                                        <TestInstance/>
                                                </Test>
                                        </TestCase>
index ba66e88..e5d26d0 100644 (file)
@@ -114527,45 +114527,49 @@ dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_linear_linear_mipmap_nea
 dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_linear_linear_mipmap_nearest_clamp
 dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_linear_linear_mipmap_linear_repeat
 dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_linear_linear_mipmap_linear_clamp
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_B4G4R4A4_UNORM_PACK16_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_B4G4R4A4_UNORM_PACK16_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R5G6B5_UNORM_PACK16_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R5G6B5_UNORM_PACK16_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A1R5G5B5_UNORM_PACK16_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A1R5G5B5_UNORM_PACK16_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8_UNORM_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8_UNORM_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8_SNORM_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8_SNORM_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8_UNORM_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8_UNORM_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8_SNORM_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8_SNORM_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8B8A8_UNORM_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8B8A8_UNORM_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8B8A8_SNORM_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8B8A8_SNORM_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8B8A8_SRGB_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R8G8B8A8_SRGB_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_B8G8R8A8_UNORM_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_B8G8R8A8_UNORM_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_B8G8R8A8_SRGB_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_B8G8R8A8_SRGB_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A8B8G8R8_UNORM_PACK32_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A8B8G8R8_UNORM_PACK32_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A8B8G8R8_SNORM_PACK32_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A8B8G8R8_SNORM_PACK32_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A8B8G8R8_SRGB_PACK32_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A8B8G8R8_SRGB_PACK32_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A2B10G10R10_UNORM_PACK32_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_A2B10G10R10_UNORM_PACK32_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R16_SFLOAT_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R16_SFLOAT_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R16G16_SFLOAT_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R16G16_SFLOAT_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R16G16B16A16_SFLOAT_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_R16G16B16A16_SFLOAT_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_B10G11R11_UFLOAT_PACK32_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_B10G11R11_UFLOAT_PACK32_linear
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_E5B9G9R9_UFLOAT_PACK32_nearest
-dEQP-VK.texture_filtering.explicit_lod.2d.formats.VK_FORMAT_E5B9G9R9_UFLOAT_PACK32_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.b4g4r4a4_unorm_pack16_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.b4g4r4a4_unorm_pack16_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r5g6b5_unorm_pack16_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r5g6b5_unorm_pack16_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.a1r5g5b5_unorm_pack16_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.a1r5g5b5_unorm_pack16_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8_unorm_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8_unorm_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8_snorm_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8_snorm_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8g8_unorm_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8g8_unorm_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8g8_snorm_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8g8_snorm_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8g8b8a8_unorm_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8g8b8a8_unorm_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8g8b8a8_snorm_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r8g8b8a8_snorm_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.b8g8r8a8_unorm_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.b8g8r8a8_unorm_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.a8b8g8r8_unorm_pack32_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.a8b8g8r8_unorm_pack32_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.a8b8g8r8_snorm_pack32_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.a8b8g8r8_snorm_pack32_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.a2b10g10r10_unorm_pack32_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.a2b10g10r10_unorm_pack32_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r16_sfloat_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r16_sfloat_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r16g16_sfloat_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r16g16_sfloat_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r16g16b16a16_sfloat_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r16g16b16a16_sfloat_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r32_sfloat_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r32_sfloat_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r32g32_sfloat_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r32g32_sfloat_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r32g32b32a32_sfloat_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.formats.r32g32b32a32_sfloat_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.nearest_nearest_mipmap_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.nearest_nearest_mipmap_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.nearest_linear_mipmap_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.nearest_linear_mipmap_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.linear_nearest_mipmap_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.linear_nearest_mipmap_linear
+dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.linear_linear_mipmap_nearest
+dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.linear_linear_mipmap_linear
index 41a40be..01861e9 100644 (file)
@@ -5,6 +5,8 @@ set(DEQP_VK_TEXTURE_FILTERING_SRCS
   vktTextureFilteringTests.hpp
   vktSampleVerifier.cpp
   vktSampleVerifier.hpp
+  vktSampleVerifierUtil.cpp
+  vktSampleVerifierUtil.hpp
   vktTextureFilteringExplicitLodTests.cpp
   vktTextureFilteringExplicitLodTests.hpp
 )
index dd01b1a..5e6e7c1 100644 (file)
@@ -22,6 +22,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "vktSampleVerifier.hpp"
+#include "vktSampleVerifierUtil.hpp"
 
 #include "deMath.h"
 #include "tcuFloat.hpp"
@@ -38,180 +39,27 @@ namespace texture_filtering
 
 using namespace vk;
 using namespace tcu;
+using namespace util;
 
 namespace
 {
 
-bool isEqualRelEpsilon (const float a, const float b, const float epsilon)
+int calcUnnormalizedDim (const ImgDim dim)
 {
-       const float diff = de::abs(a - b);
-
-       const float largest = de::max(de::abs(a), de::abs(b));
-
-       return diff <= largest * epsilon;
-}
-
-template <int Size>
-bool isEqualRelEpsilon (const Vector<float, Size>& a, const Vector<float, Size>& b, const float epsilon)
-{
-       for (deUint8 compNdx = 0; compNdx < Size; ++compNdx)
+       if (dim == IMG_DIM_1D)
        {
-               if (!isEqualRelEpsilon(a[compNdx], b[compNdx], epsilon))
-               {
-                       return false;
-               }
+           return 1;
        }
-
-       return true;
-}
-
-float calcRelEpsilon (VkFormat format, VkFilter filter, VkSamplerMipmapMode mipmapFilter)
-{
-       // This should take into account the format at some point, but doesn't now
-       DE_UNREF(format);
-
-       // fp16 format approximates the minimum precision for internal calculations mandated by spec
-       const float fp16MachineEpsilon = 0.0009765625f;
-
-       // \todo [2016-07-06 collinbaker] Pick the epsilon more
-       // scientifically
-       float relEpsilon = fp16MachineEpsilon;
-
-       if (filter == VK_FILTER_LINEAR)
-       {
-               relEpsilon *= 3.0f;
-       }
-
-       if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
-       {
-               relEpsilon *= 2.0f;
-       }
-
-       return relEpsilon;
-}
-
-deInt32 mod (const deInt32 a, const deInt32 n)
-{
-       const deInt32 result = a % n;
-
-       return (result < 0) ? result + n : result;
-}
-
-deInt32 mirror (const deInt32 n)
-{
-       if (n >= 0)
+       else if (dim == IMG_DIM_2D || dim == IMG_DIM_CUBE)
        {
-               return n;
+           return 2;
        }
        else
        {
-               return -(1 + n);
+           return 3;
        }
 }
 
-template <int Size>
-Vector<float, Size> floor (const Vector<float, Size>& v)
-{
-       Vector<float, Size> result;
-
-       for (int compNdx = 0; compNdx < Size; ++compNdx)
-       {
-               result[compNdx] = (float)deFloor(v[compNdx]);
-       }
-
-       return result;
-}
-
-template <int Size>
-Vector<float, Size> ceil (const Vector<float, Size>& v)
-{
-       Vector<float, Size> result;
-
-       for (int compNdx = 0; compNdx < Size; ++compNdx)
-       {
-               result[compNdx] = (float)deCeil(v[compNdx]);
-       }
-
-       return result;
-}
-
-template <int Size>
-Vector<float, Size> abs (const Vector<float, Size>& v)
-{
-       Vector<float, Size> result;
-
-       for (int compNdx = 0; compNdx < Size; ++compNdx)
-       {
-               result[compNdx] = de::abs(v[compNdx]);
-       }
-
-       return result;
-}
-
-Vec2 computeLevelLodBounds (const Vec2& lodBounds, deUint8 level)
-{
-       Vec2 levelLodBounds;
-
-       if (lodBounds[0] <= 0.0f)
-       {
-               levelLodBounds[0] = lodBounds[0];
-       }
-       else
-       {
-               levelLodBounds[0] = de::max(lodBounds[0], (float) level);
-       }
-
-       levelLodBounds[1] = de::min(lodBounds[1], (float) level + 1.0f);
-
-       return levelLodBounds;
-}
-
-float addUlp (float num, deInt32 ulp)
-{
-       // Note: adding positive ulp always moves float away from zero
-
-       tcu::Float32 f(num);
-
-       DE_ASSERT(!f.isNaN() && !f.isInf());
-       DE_ASSERT(num > FLT_MIN * (float) ulp || num < FLT_MIN * (float) ulp);
-
-       deUint32 bits = f.bits();
-       bits += ulp;
-
-       return tcu::Float32(bits).asFloat();
-}
-
-deInt32 wrapTexelCoord (const deInt32 coord,
-                                               const deUint32 size,
-                                               const VkSamplerAddressMode wrap)
-{
-       deInt32 wrappedCoord = 0;
-
-       switch (wrap)
-       {
-               case VK_SAMPLER_ADDRESS_MODE_REPEAT:
-                       wrappedCoord = mod(coord, size);
-                       break;
-               case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
-                       wrappedCoord = (size - 1) - mirror(mod(coord, 2 * size) - size);
-                       break;
-               case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
-                       wrappedCoord = de::clamp(coord, 0, (deInt32) size - 1);
-                       break;
-               case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
-                       wrappedCoord = de::clamp(coord, -1, (deInt32) size);
-                       break;
-               case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
-                       wrappedCoord = de::clamp(mirror(coord), 0, (deInt32) size - 1);
-                       break;
-               default:
-                       DE_FATAL("Invalid VkSamplerAddressMode");
-                       break;
-       }
-
-       return wrappedCoord;
-}
-
 } // anonymous
 
 SampleVerifier::SampleVerifier (const ImageViewParameters&                                             imParams,
@@ -220,36 +68,56 @@ SampleVerifier::SampleVerifier (const ImageViewParameters&                                         imParams,
                                                                int                                                                                             coordBits,
                                                                int                                                                                             mipmapBits,
                                                                const std::vector<tcu::ConstPixelBufferAccess>& pba)
-
-       : m_imParams                            (imParams)
+// \todo [2016-07-29 collinbaker] Get rid of magic numbers
+       : m_internalFormat                      (-14, 15, 10, true) // fp16 format
+       , m_imParams                            (imParams)
        , m_samplerParams                       (samplerParams)
        , m_sampleLookupSettings        (sampleLookupSettings)
        , m_coordBits                           (coordBits)
        , m_mipmapBits                          (mipmapBits)
+       , m_unnormalizedDim                     (calcUnnormalizedDim(imParams.dim))
        , m_pba                                         (pba)
 {
+
+}
+
+bool SampleVerifier::coordOutOfRange (const IVec3& coord, int compNdx, int level) const
+{
+       DE_ASSERT(compNdx >= 0 && compNdx < 3);
+
+       return coord[compNdx] < 0 || coord[compNdx] >= m_pba[level].getSize()[compNdx];
+}
+
+void SampleVerifier::fetchTexelWrapped (const IVec3&   coord,
+                                                                               int                             layer,
+                                                                               int                             level,
+                                                                               Vec4&                   resultMin,
+                                                                               Vec4&                   resultMax) const
+{
+    const void* pixelPtr = DE_NULL;
+
        if (m_imParams.dim == IMG_DIM_1D)
        {
-               m_unnormalizedDim = 1;
+           pixelPtr = m_pba[level].getPixelPtr(coord[0], layer, 0);
        }
        else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
        {
-               m_unnormalizedDim = 2;
+               pixelPtr = m_pba[level].getPixelPtr(coord[0], coord[1], layer);
        }
        else
        {
-               m_unnormalizedDim = 3;
+               pixelPtr = m_pba[level].getPixelPtr(coord[0], coord[1], coord[2]);
        }
-}
-
-bool SampleVerifier::coordOutOfRange (const IVec3& coord, int compNdx, int level) const
-{
-       DE_ASSERT(compNdx >= 0 && compNdx < 3);
 
-       return coord[compNdx] < 0 || coord[compNdx] >= m_pba[level].getSize()[compNdx];
+       convertFormat(pixelPtr, mapVkFormat(m_imParams.format), m_internalFormat, resultMin, resultMax);
 }
 
-Vec4 SampleVerifier::fetchTexel (const IVec3& coordIn, deUint32 layer, deUint8 level, VkFilter filter) const
+void SampleVerifier::fetchTexel (const IVec3&  coordIn,
+                                                                int                    layer,
+                                                                int                    level,
+                                                                VkFilter               filter,
+                                                                Vec4&                  resultMin,
+                                                                Vec4&                  resultMax) const
 {
        IVec3 coord = coordIn;
 
@@ -264,206 +132,100 @@ Vec4 SampleVerifier::fetchTexel (const IVec3& coordIn, deUint32 layer, deUint8 l
 
        // Wrapping operations
 
+
        if (m_imParams.dim == IMG_DIM_CUBE && filter == VK_FILTER_LINEAR)
        {
-               const deUint32  arrayLayer = layer / 6;
-               deUint8                 arrayFace  = (deUint8) (layer % 6);
-
-               // Cube map adjacent faces ordered clockwise from top
-
-               // \todo [2016-07-07 collinbaker] Verify these are correct
-               static const deUint8 adjacentFaces[6][4] =
-               {
-                   {3, 5, 2, 4},
-                       {3, 4, 2, 5},
-                       {4, 0, 5, 1},
-                       {5, 0, 4, 1},
-                       {3, 0, 2, 1},
-                       {3, 1, 2, 0}
-               };
-
-               static const deUint8 adjacentEdges[6][4] =
-               {
-                       {1, 3, 1, 1},
-                       {3, 3, 3, 1},
-                       {2, 2, 2, 2},
-                       {0, 0, 0, 0},
-                       {2, 3, 0, 1},
-                       {0, 3, 2, 1}
-               };
-
-               static const deInt8 adjacentEdgeDirs[6][4] =
-               {
-                       {-1, +1, +1, +1},
-                       {+1, +1, -1, +1},
-                       {+1, +1, -1, -1},
-                       {-1, -1, +1, +1},
-                       {+1, +1, +1, +1},
-                       {-1, +1, -1, +1}
-               };
-
-               static const deUint8 edgeComponent[4] = {0, 1, 0, 1};
+               // If the image is a cubemap and we are using linear filtering, we do edge or corner wrapping
 
-               static const deUint8 edgeFactors[4][2] =
-               {
-                       {0, 0},
-                       {1, 0},
-                       {0, 1},
-                       {0, 0}
-               };
+               const int       arrayLayer = layer / 6;
+               int                     arrayFace  = layer % 6;
 
                if (coordOutOfRange(coord, 0, level) != coordOutOfRange(coord, 1, level))
                {
-                       // Handle edge
-
-                       deUint8 edgeNdx;
-
-                       if (coord[1] < 0)
-                       {
-                               edgeNdx = 0;
-                       }
-                       else if (coord[0] > 0)
-                       {
-                               edgeNdx = 1;
-                       }
-                       else if (coord[1] > 0)
-                       {
-                               edgeNdx = 2;
-                       }
-                       else
-                       {
-                               edgeNdx = 3;
-                       }
+                       // Wrap around edge
 
-                       const deUint8   adjacentEdgeNdx = adjacentEdges[arrayFace][edgeNdx];
-                       const IVec2             edgeFactor              = IVec2(edgeFactors[adjacentEdgeNdx][0],
-                                                                                                       edgeFactors[adjacentEdgeNdx][1]);
-                       const IVec2             edgeOffset              = edgeFactor * (m_pba[level].getSize().swizzle(0, 1) - IVec2(1));
+                       IVec2   newCoord(0);
+                       int             newFace = 0;
 
-                       IVec2 newCoord;
+                       wrapCubemapEdge(coord.swizzle(0, 1),
+                                                       m_pba[level].getSize().swizzle(0, 1),
+                                                       arrayFace,
+                                                       newCoord,
+                                                       newFace);
 
-                       if (adjacentEdgeDirs[arrayFace][edgeNdx] > 0)
-                       {
-                               newCoord[edgeComponent[adjacentEdgeNdx]] = coord[edgeComponent[edgeNdx]];
-                       }
-                       else
-                       {
-                               newCoord[edgeComponent[adjacentEdgeNdx]] =
-                                       m_pba[level].getSize()[edgeComponent[edgeNdx]] - coord[edgeComponent[edgeNdx]] - 1;
-                       }
-
-                       newCoord[1 - edgeComponent[adjacentEdgeNdx]] = 0;
-                       coord.xy() = newCoord + edgeOffset;
-
-                       arrayFace = adjacentFaces[arrayFace][edgeNdx];
-                       layer = arrayLayer * 6 + arrayFace;
+                       coord.xy()      = newCoord;
+                       layer           = arrayLayer * 6 + newFace;
                }
                else if (coordOutOfRange(coord, 0, level) && coordOutOfRange(coord, 1, level))
                {
-                       // Handle corner; corners are numbered clockwise starting
-                       // from top left
-
-                       deUint8 cornerNdx;
-
-                       if (coord[0] < 0 && coord[1] < 0)
-                       {
-                               cornerNdx = 0;
-                       }
-                       else if (coord[0] > 0 && coord[1] < 0)
-                       {
-                               cornerNdx = 1;
-                       }
-                       else if (coord[0] > 0 && coord[1] > 0)
-                       {
-                               cornerNdx = 2;
-                       }
-                       else
-                       {
-                               cornerNdx = 3;
-                       }
+                       // Wrap corner
 
-                       // Calculate faces and corners thereof adjacent to sampled corner
+                       int   faces[3] = {arrayFace, 0, 0};
+                       IVec2 cornerCoords[3];
 
-                       const deUint8 cornerEdges[2] = {cornerNdx, (deUint8) ((cornerNdx + 3) % 4)};
+                       wrapCubemapCorner(coord.swizzle(0, 1),
+                                                         m_pba[level].getSize().swizzle(0, 1),
+                                                         arrayFace,
+                                                         faces[1],
+                                                         faces[2],
+                                                         cornerCoords[0],
+                                                         cornerCoords[1],
+                                                         cornerCoords[2]);
 
-                   const deUint8 faces[3]               = {arrayFace,
-                                                                                       adjacentFaces[arrayFace][cornerEdges[0]],
-                                                                                       adjacentFaces[arrayFace][cornerEdges[1]]};
+                       // \todo [2016-08-01 collinbaker] Call into fetchTexelWrapped instead
 
-                       deUint8           faceCorners[3] = {cornerNdx, 0, 0};
+                       Vec4 cornerTexels[3];
 
-                   for (deUint8 edgeNdx = 0; edgeNdx < 2; ++edgeNdx)
+                       for (int ndx = 0; ndx < 3; ++ndx)
                        {
-                               const deUint8 faceEdge = adjacentEdges[arrayFace][cornerEdges[edgeNdx]];
-
-                               bool isFlipped = (adjacentEdgeDirs[arrayFace][cornerEdges[edgeNdx]]);
-
-                               if ((cornerEdges[edgeNdx] > 1) != (faceEdge > 1))
-                               {
-                                       isFlipped = !isFlipped;
-                               }
+                               int cornerLayer = faces[ndx] + arrayLayer * 6;
 
-                               if (isFlipped)
+                               if (isSrgb)
                                {
-                                       faceCorners[edgeNdx + 1] = (deUint8) ((faceEdge + 1) % 4);
+                                   cornerTexels[ndx] += sRGBToLinear(m_pba[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer));
                                }
                                else
                                {
-                                       faceCorners[edgeNdx + 1] = faceEdge;
+                                       cornerTexels[ndx] += m_pba[level].getPixel(cornerCoords[ndx][0], cornerCoords[ndx][1], cornerLayer);
                                }
                        }
 
-                       // Compute average of corners and return
-
-                       Vec4 result(0.0f);
-
-                       for (deUint8 faceNdx = 0; faceNdx < 3; ++faceNdx)
+                       for (int compNdx = 0; compNdx < 4; ++compNdx)
                        {
-                               IVec2 cornerFactor;
+                               float compMin = cornerTexels[0][compNdx];
+                               float compMax = cornerTexels[0][compNdx];
 
-                               switch (faceCorners[faceNdx])
+                               for (int ndx = 1; ndx < 3; ++ndx)
                                {
-                                       case 0:
-                                               cornerFactor = IVec2(0, 0);
-                                               break;
-                                       case 1:
-                                               cornerFactor = IVec2(1, 0);
-                                               break;
-                                       case 2:
-                                               cornerFactor = IVec2(1, 1);
-                                               break;
-                                       case 3:
-                                               cornerFactor = IVec2(0, 1);
-                               }
-
-                               const IVec2 cornerCoord = cornerFactor * (m_pba[level].getSize().swizzle(0, 1) - IVec2(1));
-                               const deUint32 cornerLayer = arrayLayer * 6 + faces[faceNdx];
+                                       const float comp = cornerTexels[ndx][compNdx];
 
-                               if (isSrgb)
-                               {
-                                       result += sRGBToLinear(m_pba[level].getPixel(cornerCoord[0], cornerCoord[1], cornerLayer));
-                               }
-                               else
-                               {
-                                       result += m_pba[level].getPixel(cornerCoord[0], cornerCoord[1], cornerLayer);
+                                       compMin = de::min(comp, compMin);
+                                       compMax = de::max(comp, compMax);
                                }
-                       }
 
-                       result = result / 3.0f;
+                               resultMin[compNdx] = compMin;
+                               resultMax[compNdx] = compMax;
+                       }
 
-                       return result;
+                       return;
+               }
+               else
+               {
+                       // If no wrapping is necessary, just do nothing
                }
        }
        else
        {
+               // Otherwise, we do normal wrapping
+
                if (m_imParams.dim == IMG_DIM_CUBE)
                {
                        wrappingModes[0] = wrappingModes[1] = wrappingModes[2] = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
                }
 
-               for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
+               for (int compNdx = 0; compNdx < 3; ++compNdx)
                {
-                       const deUint32 size = m_pba[level].getSize()[compNdx];
+                       const int size = m_pba[level].getSize()[compNdx];
 
                        coord[compNdx] = wrapTexelCoord(coord[compNdx], size, wrappingModes[compNdx]);
                }
@@ -473,168 +235,214 @@ Vec4 SampleVerifier::fetchTexel (const IVec3& coordIn, deUint32 layer, deUint8 l
                coordOutOfRange(coord, 1, level) ||
                coordOutOfRange(coord, 2, level))
        {
+               // If after wrapping coordinates are still out of range, perform texel replacement
+
                switch (m_samplerParams.borderColor)
                {
                        case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
-                               return Vec4(0.0f, 0.0f, 0.0f, 0.0f);
+                       {
+                               resultMin = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
+                               resultMax = Vec4(0.0f, 0.0f, 0.0f, 0.0f);
+                               return;
+                       }
                        case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
-                               return Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+                       {
+                               resultMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+                               resultMax = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+                               return;
+                       }
                        case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
-                               return Vec4(1.0f, 1.0f, 1.0f, 1.0f);
+                       {
+                               resultMin = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
+                               resultMax = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
+                               return;
+                       }
                        default:
+                       {
                                // \\ [2016-07-07 collinbaker] Handle
                                // VK_BORDER_COLOR_INT_* borders
                                DE_FATAL("Not implemented");
                                break;
+                       }
                }
        }
        else
        {
-               Vec4 result;
-
-           if (m_imParams.dim == IMG_DIM_1D)
-               {
-                       result = m_pba[level].getPixel(coord[0], layer, 0);
-               }
-               else if (m_imParams.dim == IMG_DIM_2D)
-               {
-                       result = m_pba[level].getPixel(coord[0], coord[1], layer);
-               }
-               else
-               {
-                       result = m_pba[level].getPixel(coord[0], coord[1], coord[2]);
-               }
-
-               // Do sRGB conversion if necessary
+               // Otherwise, actually fetch a texel
 
-               if (isSrgb)
-               {
-                       return sRGBToLinear(result);
-               }
-               else
-               {
-                       return result;
-               }
+           fetchTexelWrapped(coord, layer, level, resultMin, resultMax);
        }
-
-       return Vec4(0.0f);
 }
 
-Vec4 SampleVerifier::getFilteredSample1D (const IVec3& texelBase,
+void SampleVerifier::getFilteredSample1D (const IVec3& texelBase,
                                                                                  float                 weight,
-                                                                                 deUint32              layer,
-                                                                                 deUint8               level) const
+                                                                                 int                   layer,
+                                                                                 int                   level,
+                                                                                 Vec4&                 resultMin,
+                                                                                 Vec4&                 resultMax) const
 {
-       Vec4 texels[2];
+       Vec4 texelsMin[2];
+       Vec4 texelsMax[2];
+
+       for (int i = 0; i < 2; ++i)
+       {
+           fetchTexel(texelBase + IVec3(i, 0, 0), layer, level, VK_FILTER_LINEAR, texelsMin[i], texelsMax[i]);
+       }
 
-       for (deUint8 i = 0; i < 2; ++i)
+       Interval resultIntervals[4];
+
+       for (int ndx = 0; ndx < 4; ++ndx)
        {
-               texels[i] = fetchTexel(texelBase + IVec3(i, 0, 0), layer, level, VK_FILTER_LINEAR);
+               resultIntervals[ndx] = Interval(0.0);
+       }
+
+    for (int i = 0; i < 2; ++i)
+       {
+               const Interval weightInterval = m_internalFormat.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);
+               }
        }
 
-       return (1.0f - weight) * texels[0] + weight * texels[1];
+       for (int compNdx = 0; compNdx < 4; ++compNdx)
+       {
+               resultMin[compNdx] = (float)resultIntervals[compNdx].lo();
+               resultMax[compNdx] = (float)resultIntervals[compNdx].hi();
+       }
 }
 
 
-Vec4 SampleVerifier::getFilteredSample2D (const IVec3& texelBase,
+void SampleVerifier::getFilteredSample2D (const IVec3& texelBase,
                                                                                  const Vec2&   weights,
-                                                                                 deUint32              layer,
-                                                                                 deUint8               level) const
+                                                                                 int                   layer,
+                                                                                 int                   level,
+                                                                                 Vec4&                 resultMin,
+                                                                                 Vec4&                 resultMax) const
 {
-       Vec4 texels[4];
+       Vec4 texelsMin[4];
+       Vec4 texelsMax[4];
+
+       for (int i = 0; i < 2; ++i)
+       {
+               for (int j = 0; j < 2; ++j)
+               {
+                   fetchTexel(texelBase + IVec3(i, j, 0), layer, level, VK_FILTER_LINEAR, texelsMin[2 * j + i], texelsMax[2 * j + i]);
+               }
+       }
+
+       Interval resultIntervals[4];
+
+       for (int ndx = 0; ndx < 4; ++ndx)
+       {
+               resultIntervals[ndx] = Interval(0.0);
+       }
 
-       for (deUint8 i = 0; i < 2; ++i)
+       for (int i = 0; i < 2; ++i)
        {
-               for (deUint8 j = 0; j < 2; ++j)
+               const Interval iWeightInterval = m_internalFormat.roundOut(Interval(i == 0 ? 1.0f - weights[1] : weights[1]), false);
+
+               for (int j = 0; j < 2; ++j)
                {
-                       texels[2 * j + i] = fetchTexel(texelBase + IVec3(i, j, 0), layer, level, VK_FILTER_LINEAR);
+                   const Interval jWeightInterval = m_internalFormat.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);
+                       }
                }
        }
 
-       return (1.0f - weights[0]) * (1.0f - weights[1]) * texels[0]
-               + weights[0] * (1.0f - weights[1]) * texels[1]
-               + (1.0f - weights[0]) * weights[1] * texels[2]
-               + weights[0] * weights[1] * texels[3];
+       for (int compNdx = 0; compNdx < 4; ++compNdx)
+       {
+               resultMin[compNdx] = (float)resultIntervals[compNdx].lo();
+               resultMax[compNdx] = (float)resultIntervals[compNdx].hi();
+       }
 }
 
-Vec4 SampleVerifier::getFilteredSample3D (const IVec3& texelBase,
+void SampleVerifier::getFilteredSample3D (const IVec3& texelBase,
                                                                                  const Vec3&   weights,
-                                                                                 deUint32              layer,
-                                                                                 deUint8               level) const
+                                                                                 int                   layer,
+                                                                                 int                   level,
+                                                                                 Vec4&                 resultMin,
+                                                                                 Vec4&                 resultMax) const
 {
-       Vec4 texels[8];
+       Vec4 texelsMin[8];
+       Vec4 texelsMax[8];
+
+       for (int i = 0; i < 2; ++i)
+       {
+               for (int j = 0; j < 2; ++j)
+               {
+                       for (int k = 0; k < 2; ++k)
+                       {
+                           fetchTexel(texelBase + IVec3(i, j, k), layer, level, VK_FILTER_LINEAR, texelsMin[4 * k + 2 * j + i], texelsMax[4 * k + 2 * j + i]);
+                       }
+               }
+       }
 
-       for (deUint8 i = 0; i < 2; ++i)
+    Interval resultIntervals[4];
+
+       for (int ndx = 0; ndx < 4; ++ndx)
+       {
+               resultIntervals[ndx] = Interval(0.0);
+       }
+
+       for (int i = 0; i < 2; ++i)
        {
-               for (deUint8 j = 0; j < 2; ++j)
+           const Interval iWeightInterval = m_internalFormat.roundOut(Interval(i == 0 ? 1.0f - weights[2] : weights[2]), false);
+
+               for (int j = 0; j < 2; ++j)
                {
-                       for (deUint8 k = 0; k < 2; ++k)
+                   const Interval jWeightInterval = m_internalFormat.roundOut(iWeightInterval * Interval(j == 0 ? 1.0f - weights[1] : weights[1]), false);
+
+                       for (int k = 0; k < 2; ++k)
                        {
-                               texels[4 * k + 2 * j + i] = fetchTexel(texelBase + IVec3(i, j, k), layer, level, VK_FILTER_LINEAR);
+                           const Interval kWeightInterval = m_internalFormat.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);
+                               }
                        }
                }
        }
 
-       return (1.0f - weights[0]) * (1.0f - weights[1]) * (1.0f - weights[2]) * texels[0]
-               + weights[0] * (1.0f - weights[1]) * (1.0f - weights[2]) * texels[1]
-               + (1.0f - weights[0]) * weights[1] * (1.0f - weights[2]) * texels[2]
-               + weights[0] * weights[1] * (1.0f - weights[2]) * texels[3]
-               + (1.0f - weights[0]) * (1.0f - weights[1]) * weights[2] * texels[4]
-               + weights[0] * (1.0f - weights[1]) * weights[2] * texels[5]
-               + (1.0f - weights[0]) * weights[1] * weights[2] * texels[6]
-               + weights[0] * weights[1] * weights[3] * texels[7];
+       for (int compNdx = 0; compNdx < 4; ++compNdx)
+       {
+               resultMin[compNdx] = (float)resultIntervals[compNdx].lo();
+               resultMax[compNdx] = (float)resultIntervals[compNdx].hi();
+       }
 }
 
-Vec4 SampleVerifier::getFilteredSample (const IVec3&   texelBase,
+void SampleVerifier::getFilteredSample (const IVec3&   texelBase,
                                                                                const Vec3&             weights,
-                                                                               deUint32                layer,
-                                                                               deUint8                 level) const
+                                                                               int                             layer,
+                                                                               int                             level,
+                                                                               Vec4&                   resultMin,
+                                                                               Vec4&                   resultMax) const
 {
        DE_ASSERT(layer < m_imParams.arrayLayers);
        DE_ASSERT(level < m_imParams.levels);
 
        if (m_imParams.dim == IMG_DIM_1D)
        {
-               return getFilteredSample1D(texelBase, weights.x(), layer, level);
+               getFilteredSample1D(texelBase, weights.x(), layer, level, resultMin, resultMax);
        }
        else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
        {
-               return getFilteredSample2D(texelBase, weights.swizzle(0, 1), layer, level);
+               getFilteredSample2D(texelBase, weights.swizzle(0, 1), layer, level, resultMin, resultMax);
        }
        else
        {
-               return getFilteredSample3D(texelBase, weights, layer, level);
-       }
-}
-
-void SampleVerifier::getWeightStepBounds (const Vec3&  unnormalizedCoord,
-                                                                                 IVec3&                weightStepMin,
-                                                                                 IVec3&                weightStepMax,
-                                                                                 IVec3&                texelBase) const
-{
-       DE_ASSERT(m_coordBits < 32);
-       const deUint32 coordSteps = ((deUint32) 1) << m_coordBits;
-
-    for (deUint8 compNdx = 0; compNdx < m_unnormalizedDim; ++compNdx)
-       {
-               const float component = unnormalizedCoord[compNdx];
-               double intPart;
-
-               float weight = (float) modf((double) component - 0.5, &intPart);
-
-               if (weight < 0.0f)
-               {
-                       weight = 1.0f + weight;
-                       intPart -= 1.0;
-               }
-
-               texelBase[compNdx] = (deInt32) intPart;
-
-               weightStepMin[compNdx] = deCeilFloatToInt32 (weight * (float) coordSteps - 1.5f);
-               weightStepMax[compNdx] = deFloorFloatToInt32(weight * (float) coordSteps + 1.5f);
-
-               weightStepMin[compNdx] = de::max(weightStepMin[compNdx], (deInt32) 0);
-               weightStepMax[compNdx] = de::min(weightStepMax[compNdx], (deInt32) coordSteps);
+               getFilteredSample3D(texelBase, weights, layer, level, resultMin, resultMax);
        }
 }
 
@@ -643,20 +451,22 @@ void SampleVerifier::getMipmapStepBounds (const Vec2&     lodFracBounds,
                                                                                  deInt32&              stepMax) const
 {
        DE_ASSERT(m_mipmapBits < 32);
-       const deUint32 mipmapSteps = ((deUint32) 1) << m_mipmapBits;
+       const int mipmapSteps = ((int)1) << m_mipmapBits;
 
-       stepMin = deFloorFloatToInt32(lodFracBounds[0] * (float) mipmapSteps);
-       stepMax = deCeilFloatToInt32 (lodFracBounds[1] * (float) mipmapSteps);
+       stepMin = deFloorFloatToInt32(lodFracBounds[0] * (float)mipmapSteps);
+       stepMax = deCeilFloatToInt32 (lodFracBounds[1] * (float)mipmapSteps);
 
-       stepMin = de::max(stepMin, (deInt32) 0);
-       stepMax = de::min(stepMax, (deInt32) mipmapSteps);
+       stepMin = de::max(stepMin, (deInt32)0);
+       stepMax = de::min(stepMax, (deInt32)mipmapSteps);
 }
 
 bool SampleVerifier::verifySampleFiltered (const Vec4&                 result,
-                                                                                  const Vec3&                  unnormalizedCoordHi,
-                                                                                  const Vec3&                  unnormalizedCoordLo,
-                                                                                  deUint32                             layer,
-                                                                                  deUint8                              levelHi,
+                                                                                  const IVec3&                 baseTexelHiIn,
+                                                                                  const IVec3&                 baseTexelLoIn,
+                                                                                  const IVec3&                 texelGridOffsetHiIn,
+                                                                                  const IVec3&                 texelGridOffsetLoIn,
+                                                                                  int                                  layer,
+                                                                                  int                                  levelHi,
                                                                                   const Vec2&                  lodFracBounds,
                                                                                   VkFilter                             filter,
                                                                                   VkSamplerMipmapMode  mipmapFilter,
@@ -665,120 +475,96 @@ bool SampleVerifier::verifySampleFiltered (const Vec4&                   result,
        DE_ASSERT(layer < m_imParams.arrayLayers);
        DE_ASSERT(levelHi < m_imParams.levels);
 
-       const float             epsilon    = calcRelEpsilon(m_imParams.format, filter, mipmapFilter);
+       const int       coordSteps                      = 1 << m_coordBits;
+       const int       lodSteps                        = 1 << m_mipmapBits;
+       const int       levelLo                         = (levelHi < m_imParams.levels - 1) ? levelHi + 1 : levelHi;
 
-       const deUint32  coordSteps = ((deUint32) 1) << m_coordBits;
-       const deUint32  lodSteps   = ((deUint32) 1) << m_mipmapBits;
+       IVec3           baseTexelHi                     = baseTexelHiIn;
+       IVec3           baseTexelLo                     = baseTexelLoIn;
+       IVec3           texelGridOffsetHi       = texelGridOffsetHiIn;
+       IVec3           texelGridOffsetLo       = texelGridOffsetLoIn;
+       deInt32         lodStepsMin                     = 0;
+       deInt32         lodStepsMax                     = 0;
 
-       IVec3                   texelBase[2];
-       IVec3                   weightStepsMin[2];
-       IVec3                   weightStepsMax[2];
-       deInt32                 lodStepsMin;
-       deInt32                 lodStepsMax;
+       getMipmapStepBounds(lodFracBounds, lodStepsMin, lodStepsMax);
 
-       int                             levels;
-       int                             levelLo;
+       report << "Testing at base texel " << baseTexelHi << ", " << baseTexelLo << " offset " << texelGridOffsetHi << ", " << texelGridOffsetLo << "\n";
 
-       if (levelHi == m_imParams.levels - 1 || mipmapFilter == VK_SAMPLER_MIPMAP_MODE_NEAREST)
-       {
-               levels = 1;
-               levelLo = levelHi;
-               mipmapFilter = VK_SAMPLER_MIPMAP_MODE_NEAREST;
-       }
-       else
-       {
-               levels = 2;
-               levelLo = 1 + levelHi;
-       }
+       Vec4 idealSampleHiMin;
+       Vec4 idealSampleHiMax;
+       Vec4 idealSampleLoMin;
+       Vec4 idealSampleLoMax;
 
-       getWeightStepBounds(unnormalizedCoordHi, weightStepsMin[0], weightStepsMax[0], texelBase[0]);
+       // Get ideal samples at steps at each mipmap level
 
-       if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
-       {
-               getWeightStepBounds(unnormalizedCoordLo, weightStepsMin[1], weightStepsMax[1], texelBase[1]);
-               getMipmapStepBounds(lodFracBounds, lodStepsMin, lodStepsMax);
-       }
-       else
+       if (filter == VK_FILTER_LINEAR)
        {
-               texelBase[1] = IVec3(0);
-               weightStepsMin[1] = IVec3(0);
-               weightStepsMax[1] = IVec3(0);
-       }
+               // Adjust texel grid coordinates for linear filtering
+               wrapTexelGridCoordLinear(baseTexelHi, texelGridOffsetHi, m_coordBits, m_imParams.dim);
 
-       IVec3 weightSteps[2] = {weightStepsMin[0], weightStepsMin[1]};
+               if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+               {
+                       wrapTexelGridCoordLinear(baseTexelLo, texelGridOffsetLo, m_coordBits, m_imParams.dim);
+               }
 
-       bool done = false;
+               const Vec3 roundedWeightsHi = texelGridOffsetHi.asFloat() / (float)coordSteps;
+               const Vec3 roundedWeightsLo = texelGridOffsetLo.asFloat() / (float)coordSteps;
 
-       while (!done)
-       {
-               report << "Testing at base texel " << texelBase[0] << ", " << texelBase[1] << " with weight steps " << weightSteps[0] << ", " << weightSteps[1] << "\n";
+               report << "Computed weights: " << roundedWeightsHi << ", " << roundedWeightsLo << "\n";
 
-               Vec4 idealSampleHi, idealSampleLo;
+           getFilteredSample(baseTexelHi, roundedWeightsHi, layer, levelHi, idealSampleHiMin, idealSampleHiMax);
 
-               // Get ideal samples at steps at each mipmap level
+               report << "Ideal hi sample: " << idealSampleHiMin << " through " << idealSampleHiMax << "\n";
 
-               if (filter == VK_FILTER_LINEAR)
+               if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
                {
-                       Vec3 roundedWeightsHi, roundedWeightsLo;
+                   getFilteredSample(baseTexelLo, roundedWeightsLo, layer, levelLo, idealSampleLoMin, idealSampleLoMax);
 
-                       roundedWeightsHi = weightSteps[0].asFloat() / (float) coordSteps;
-                       roundedWeightsLo = weightSteps[1].asFloat() / (float) coordSteps;
-
-                       report << "Computed weights: " << roundedWeightsHi << ", " << roundedWeightsLo << "\n";
-
-                       idealSampleHi = getFilteredSample(texelBase[0], roundedWeightsHi, layer, levelHi);
+                       report << "Ideal lo sample: " << idealSampleLoMin << " through " << idealSampleLoMax << "\n";
+               }
+       }
+       else
+       {
+           fetchTexel(baseTexelHi, layer, levelHi, VK_FILTER_NEAREST, idealSampleHiMin, idealSampleHiMax);
 
-                       report << "Ideal hi sample: " << idealSampleHi << "\n";
+               report << "Ideal hi sample: " << idealSampleHiMin << " through " << idealSampleHiMax << "\n";
 
-                       if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
-                       {
-                               idealSampleLo = getFilteredSample(texelBase[1], roundedWeightsLo, layer, (deUint8)levelLo);
+               if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+               {
+                   fetchTexel(baseTexelLo, layer, levelLo, VK_FILTER_NEAREST, idealSampleLoMin, idealSampleLoMax);
 
-                               report << "Ideal lo sample: " << idealSampleLo << "\n";
-                       }
+                       report << "Ideal lo sample: " << idealSampleLoMin << " through " << idealSampleLoMax << "\n";
                }
-               else
-               {
-                       // \todo [2016-07-14 collinbaker] fix this because this is definitely wrong
-                       idealSampleHi = fetchTexel(floor(unnormalizedCoordHi).cast<deInt32>(), layer, levelHi, VK_FILTER_NEAREST);
+       }
 
-                       report << "Ideal hi sample: " << idealSampleHi << "\n";
+       // Test ideal samples based on mipmap filtering mode
 
-                       if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
-                       {
-                               idealSampleLo = fetchTexel(floor(unnormalizedCoordLo).cast<deInt32>(), layer, (deUint8)levelLo, VK_FILTER_NEAREST);
+       if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+       {
+               for (deInt32 lodStep = lodStepsMin; lodStep <= lodStepsMax; ++lodStep)
+               {
+                       float weight = (float)lodStep / (float)lodSteps;
 
-                               report << "Ideal lo sample: " << idealSampleLo << "\n";
-                       }
-               }
+                       report << "Testing at mipmap weight " << weight << "\n";
 
-               // Test ideal samples based on mipmap filtering mode
+                       Vec4 idealSampleMin;
+                       Vec4 idealSampleMax;
 
-               if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
-               {
-                       for (deInt32 lodStep = lodStepsMin; lodStep <= lodStepsMax; ++lodStep)
+                       for (int compNdx = 0; compNdx < 4; ++compNdx)
                        {
-                               float weight = (float) lodStep / (float) lodSteps;
+                               const Interval idealSampleLo(false, idealSampleLoMin[compNdx], idealSampleLoMax[compNdx]);
+                               const Interval idealSampleHi(false, idealSampleHiMin[compNdx], idealSampleHiMax[compNdx]);
 
-                               report << "Testing at mipmap weight " << weight << "\n";
+                               const Interval idealSample
+                                       = m_internalFormat.roundOut(Interval(weight) * idealSampleLo + Interval(1.0f - weight) * idealSampleHi, false);
 
-                               Vec4 idealSample = weight * idealSampleLo + (1.0f - weight) * idealSampleHi;
+                               idealSampleMin[compNdx] = (float)idealSample.lo();
+                               idealSampleMax[compNdx] = (float)idealSample.hi();
+                       }
 
-                               report << "Ideal sample: " << idealSample << "\n";
+                       report << "Ideal sample: " << idealSampleMin << " through " << idealSampleMax << "\n";
 
-                               if (isEqualRelEpsilon(idealSample, result, epsilon))
-                               {
-                                       return true;
-                               }
-                               else
-                               {
-                                       report << "Failed comparison\n";
-                               }
-                       }
-               }
-               else if (filter == VK_FILTER_LINEAR)
-               {
-                       if (isEqualRelEpsilon(idealSampleHi, result, epsilon))
+                       if (isInRange(result, idealSampleMin, idealSampleMax))
                        {
                                return true;
                        }
@@ -787,70 +573,44 @@ bool SampleVerifier::verifySampleFiltered (const Vec4&                    result,
                                report << "Failed comparison\n";
                        }
                }
-               else
-               {
-                       if (idealSampleHi == result)
-                       {
-                               return true;
-                       }
-               }
-
-               // Increment step
-
-               // Represents whether the increment at a position wraps and should "carry" to the next place
-               bool carry = true;
-
-               for (deUint8 levelNdx = 0; levelNdx < levels; ++levelNdx)
+       }
+       else
+       {
+               if (isInRange(result, idealSampleHiMin, idealSampleHiMax))
                {
-                       for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
-                       {
-                               if (carry)
-                               {
-                                       carry = false;
-                                       deInt32& n = weightSteps[levelNdx][compNdx];
-
-                                       if (n++ == weightStepsMax[levelNdx][compNdx])
-                                       {
-                                               n = weightStepsMin[levelNdx][compNdx];
-                                               carry = true;
-                                       }
-                               }
-                               else
-                               {
-                                       break;
-                               }
-                       }
-
-                       if (!carry)
-                       {
-                               break;
-                       }
+                       return true;
                }
-
-               if (carry)
+               else
                {
-                       done = true;
+                       report << "Failed comparison\n";
                }
        }
 
-       report << "Failed comparison against all possible weights\n\n";
-
        return false;
 }
 
-bool SampleVerifier::verifySampleUnnormalizedCoords (const SampleArguments&    args,
-                                                                                                        const Vec4&                    result,
-                                                                                                        const Vec3&                    unnormalizedCoord,
-                                                                                                        const Vec3&                    unnormalizedCoordLo,
-                                                                                                        const Vec2&                    lodBounds,
-                                                                                                        deUint8                                level,
-                                                                                                        VkSamplerMipmapMode    mipmapFilter,
-                                                                                                        std::ostream&                  report) const
+bool SampleVerifier::verifySampleTexelGridCoords (const SampleArguments&       args,
+                                                                                                 const Vec4&                           result,
+                                                                                                 const IVec3&                          gridCoordHi,
+                                                                                                 const IVec3&                          gridCoordLo,
+                                                                                                 const Vec2&                           lodBounds,
+                                                                                                 int                                           level,
+                                                                                                 VkSamplerMipmapMode           mipmapFilter,
+                                                                                                 std::ostream&                         report) const
 {
-       const deUint8 layer = m_imParams.isArrayed ? (deUint8) deRoundEven(args.layer) : 0U;
+       const int       layer            = m_imParams.isArrayed ? (int)deRoundEven(args.layer) : 0U;
+       const IVec3 gridCoord[2] = {gridCoordHi, gridCoordLo};
 
-       const bool canBeMinified = lodBounds[1] > 0.0f;
-       const bool canBeMagnified = lodBounds[0] <= 0.0f;
+       IVec3 baseTexel[2];
+       IVec3 texelGridOffset[2];
+
+    for (int levelNdx = 0; levelNdx < 2; ++levelNdx)
+       {
+               calcTexelBaseOffset(gridCoord[levelNdx], m_coordBits, baseTexel[levelNdx], texelGridOffset[levelNdx]);
+       }
+
+       const bool      canBeMinified  = lodBounds[1] > 0.0f;
+       const bool      canBeMagnified = lodBounds[0] <= 0.0f;
 
        if (canBeMagnified)
        {
@@ -858,22 +618,25 @@ bool SampleVerifier::verifySampleUnnormalizedCoords (const SampleArguments&       args
 
                if (m_samplerParams.magFilter == VK_FILTER_NEAREST)
                {
-                       report << "Testing against nearest texel at " << floor(unnormalizedCoord).cast<deInt32>() << "\n";
+                       report << "Testing against nearest texel at " << baseTexel[0] << "\n";
 
-                       const Vec4 ideal = fetchTexel(floor(unnormalizedCoord).cast<deInt32>(), layer, level, VK_FILTER_NEAREST);
+                       Vec4 idealMin;
+                       Vec4 idealMax;
 
-                       if (result == ideal)
+                       fetchTexel(baseTexel[0], layer, level, VK_FILTER_NEAREST, idealMin, idealMax);
+
+                       if (isInRange(result, idealMin, idealMax))
                    {
                                return true;
                        }
                        else
                        {
-                               report << "Failed against " << ideal << "\n";
+                               report << "Failed against " << idealMin << " through " << idealMax << "\n";
                        }
                }
                else
                {
-                       if  (verifySampleFiltered(result, unnormalizedCoord, Vec3(0.0f), layer, level, Vec2(0.0f, 0.0f), VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, report))
+                       if  (verifySampleFiltered(result, baseTexel[0], baseTexel[1], texelGridOffset[0], texelGridOffset[1], layer, level, Vec2(0.0f, 0.0f), VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, report))
                                return true;
                }
        }
@@ -884,29 +647,32 @@ bool SampleVerifier::verifySampleUnnormalizedCoords (const SampleArguments&       args
 
                if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
                {
-                       const Vec2 lodFracBounds = lodBounds - Vec2(level);
+                       const Vec2 lodFracBounds = lodBounds - Vec2((float)level);
 
-                       if (verifySampleFiltered(result, unnormalizedCoord, unnormalizedCoordLo, layer, level, lodFracBounds, m_samplerParams.minFilter, VK_SAMPLER_MIPMAP_MODE_LINEAR, report))
+                       if (verifySampleFiltered(result, baseTexel[0], baseTexel[1], texelGridOffset[0], texelGridOffset[1], layer, level, lodFracBounds, m_samplerParams.minFilter, VK_SAMPLER_MIPMAP_MODE_LINEAR, report))
                                return true;
                }
                else if (m_samplerParams.minFilter == VK_FILTER_LINEAR)
                {
-                   if (verifySampleFiltered(result, unnormalizedCoord, Vec3(0.0f), layer, level, Vec2(0.0f, 0.0f), VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, report))
+                   if (verifySampleFiltered(result, baseTexel[0], baseTexel[1], texelGridOffset[0], texelGridOffset[1], layer, level, Vec2(0.0f, 0.0f), VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST, report))
                                return true;
                }
                else
                {
-                       report << "Testing against nearest texel at " << floor(unnormalizedCoord).cast<deInt32>() << "\n";
+                       report << "Testing against nearest texel at " << baseTexel[0] << "\n";
+
+                       Vec4 idealMin;
+                       Vec4 idealMax;
 
-                       Vec4 ideal = fetchTexel(floor(unnormalizedCoord).cast<deInt32>(), layer, level, VK_FILTER_NEAREST);
+                   fetchTexel(baseTexel[0], layer, level, VK_FILTER_NEAREST, idealMin, idealMax);
 
-                       if (result == ideal)
+                       if (isInRange(result, idealMin, idealMax))
                    {
                                return true;
                        }
                        else
                        {
-                               report << "Failed against " << ideal << "\n";
+                               report << "Failed against " << idealMin << " through " << idealMax << "\n";
                        }
                }
        }
@@ -918,7 +684,7 @@ bool SampleVerifier::verifySampleMipmapLevel (const SampleArguments&        args,
                                                                                          const Vec4&                           result,
                                                                                          const Vec4&                           coord,
                                                                                          const Vec2&                           lodBounds,
-                                                                                         deUint8                                       level,
+                                                                                         int                                           level,
                                                                                          std::ostream&                         report) const
 {
        DE_ASSERT(level < m_imParams.levels);
@@ -930,136 +696,88 @@ bool SampleVerifier::verifySampleMipmapLevel (const SampleArguments&     args,
                mipmapFilter = VK_SAMPLER_MIPMAP_MODE_NEAREST;
        }
 
-       Vector<double, 3> unnormalizedCoordHiDbl, unnormalizedCoordLoDbl;
+       Vec3    unnormalizedCoordMin[2];
+       Vec3    unnormalizedCoordMax[2];
+       IVec3   gridCoordMin[2];
+       IVec3   gridCoordMax[2];
 
-       unnormalizedCoordHiDbl = coord.cast<double>().swizzle(0, 1, 2) * m_pba[level].getSize().cast<double>();
+       const FloatFormat coordFormat(-32, 32, 16, true);
 
-       if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
-       {
-               unnormalizedCoordLoDbl = coord.cast<double>().swizzle(0, 1, 2) * m_pba[level + 1].getSize().cast<double>();
-       }
+       calcUnnormalizedCoordRange(coord,
+                                                          m_pba[level].getSize(),
+                                                          coordFormat,
+                                                          unnormalizedCoordMin[0],
+                                                          unnormalizedCoordMax[0]);
 
-       // Check if result(s) will be rounded
+       calcTexelGridCoordRange(unnormalizedCoordMin[0],
+                                                       unnormalizedCoordMax[0],
+                                                       m_coordBits,
+                                                       gridCoordMin[0],
+                                                       gridCoordMax[0]);
 
-       bool hiIsRounded[3] = {false};
-       bool loIsRounded[3] = {false};
+       report << "Level " << level << " computed unnormalized coordinate range: [" << unnormalizedCoordMin[0] << ", " << unnormalizedCoordMax[0] << "]\n";
+       report << "Level " << level << " computed texel grid coordinate range: [" << gridCoordMin[0] << ", " << gridCoordMax[0] << "]\n";
 
-       for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
+       if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
        {
-               hiIsRounded[compNdx] = ((double) (float) unnormalizedCoordHiDbl[compNdx]) != unnormalizedCoordHiDbl[compNdx];
+               calcUnnormalizedCoordRange(coord,
+                                                                  m_pba[level+1].getSize(),
+                                                                  coordFormat,
+                                                                  unnormalizedCoordMin[1],
+                                                                  unnormalizedCoordMax[1]);
 
-               if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
-               {
-                       loIsRounded[compNdx] = ((double) (float) unnormalizedCoordLoDbl[compNdx]) != unnormalizedCoordLoDbl[compNdx];
-               }
-       }
+               calcTexelGridCoordRange(unnormalizedCoordMin[1],
+                                                               unnormalizedCoordMax[1],
+                                                               m_coordBits,
+                                                               gridCoordMin[1],
+                                                               gridCoordMax[1]);
 
-       const deInt32 ulpEpsilon        = (deInt32) (2.0e-5f / FLT_EPSILON);
-       const deInt32 ulpOffsets[3] = {0, -ulpEpsilon, ulpEpsilon};
 
-       deUint8 roundTypesHi[3] = {0, 0, 0};
-       deUint8 roundTypesLo[3] = {0, 0, 0};
+               report << "Level " << level+1 << " computed unnormalized coordinate range: [" << unnormalizedCoordMin[1] << " - " << unnormalizedCoordMax[1] << "]\n";
+               report << "Level " << level+1 << " computed texel grid coordinate range: [" << gridCoordMin[1] << " - " << gridCoordMax[1] << "]\n";
+       }
+       else
+       {
+               unnormalizedCoordMin[1] = unnormalizedCoordMax[1] = Vec3(0.0f);
+               gridCoordMin[1] = gridCoordMax[1] = IVec3(0);
+       }
 
        bool done = false;
 
-       // Take into account different possible rounding modes by offsetting rounded result by ULPs
-       // \todo [2016-07-15 collinbaker] This is not 100% correct; should simulate floating point arithmetic with possible rounding modes
+       IVec3 gridCoord[2] = {gridCoordMin[0], gridCoordMin[1]};
+
     while (!done)
        {
-               Vec3 unnormalizedCoordHi;
-               Vec3 unnormalizedCoordLo;
-
-               for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
-               {
-                       float comp = coord[compNdx];
-                       float compHi;
-                       float compLo;
-
-                       if (roundTypesHi[compNdx] != 0 && comp > FLT_MIN * (float) ulpEpsilon)
-                       {
-                               compHi = addUlp(comp, ulpOffsets[roundTypesHi[compNdx]]);
-                       }
-                       else
-                       {
-                               compHi = comp;
-                       }
-
-                       if (roundTypesLo[compNdx] != 0 && comp > FLT_MIN * (float) ulpEpsilon)
-                       {
-                               compLo = addUlp(comp, ulpOffsets[roundTypesLo[compNdx]]);
-                       }
-                       else
-                       {
-                               compLo = comp;
-                       }
-
-                       unnormalizedCoordHi[compNdx] = compHi * (float) m_pba[level].getSize()[compNdx];
-
-                       if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
-                       {
-                           unnormalizedCoordLo[compNdx] = compLo * (float) m_pba[level + 1].getSize()[compNdx];
-                       }
-               }
-
-               report << "Testing at " << unnormalizedCoordHi << ", " << unnormalizedCoordLo << "\n";
-
-               if (verifySampleUnnormalizedCoords(args, result, unnormalizedCoordHi, unnormalizedCoordLo, lodBounds, level, mipmapFilter, report))
+               if (verifySampleTexelGridCoords(args, result, gridCoord[0], gridCoord[1], lodBounds, level, mipmapFilter, report))
                        return true;
 
-               // Increment rounding types
+               // Get next grid coordinate to test at
 
+               // Represents whether the increment at a position wraps and should "carry" to the next place
                bool carry = true;
 
-               for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
+               for (int levelNdx = 0; levelNdx < 2; ++levelNdx)
                {
-                       if (hiIsRounded[compNdx])
+                       for (int compNdx = 0; compNdx < 3; ++compNdx)
                        {
                                if (carry)
                                {
-                                       if (roundTypesHi[compNdx] == 2)
-                                       {
-                                               roundTypesHi[compNdx] = 0;
-                                       }
-                                       else
-                                       {
-                                               roundTypesHi[compNdx]++;
-                                               carry = false;
-                                       }
-                               }
-                               else
-                               {
-                                       break;
-                               }
-                       }
-               }
+                                       deInt32& comp = gridCoord[levelNdx][compNdx];
+                                   ++comp;
 
-               for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
-               {
-                       if (loIsRounded[compNdx])
-                       {
-                               if (carry)
-                               {
-                                       if (roundTypesLo[compNdx] == 2)
+                                       if (comp > gridCoordMax[levelNdx][compNdx])
                                        {
-                                               roundTypesLo[compNdx] = 0;
+                                               comp = gridCoordMin[levelNdx][compNdx];
                                        }
                                        else
                                        {
-                                               roundTypesLo[compNdx]++;
                                                carry = false;
                                        }
                                }
-                               else
-                               {
-                                       break;
-                               }
                        }
                }
 
-               if (carry)
-               {
-                       done = true;
-               }
+               done = carry;
        }
 
        return false;
@@ -1070,7 +788,7 @@ bool SampleVerifier::verifySampleCubemapFace (const SampleArguments&       args,
                                                                                          const Vec4&                           coord,
                                                                                          const Vec4&                           dPdx,
                                                                                          const Vec4&                           dPdy,
-                                                                                         deUint8                                       face,
+                                                                                         int                                           face,
                                                                                          std::ostream&                         report) const
 {
        // Will use this parameter once cubemapping is implemented completely
@@ -1080,36 +798,17 @@ bool SampleVerifier::verifySampleCubemapFace (const SampleArguments&     args,
 
        if (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
        {
-               const Vec3 mx = abs(dPdx.swizzle(0, 1, 2)) * m_imParams.size.asFloat();
-               const Vec3 my = abs(dPdy.swizzle(0, 1, 2)) * m_imParams.size.asFloat();
-
-               Vec2 scaleXBounds;
-               Vec2 scaleYBounds;
-
-               scaleXBounds[0] = de::max(de::abs(mx[0]), de::max(de::abs(mx[1]), de::abs(mx[2])));
-               scaleYBounds[0] = de::max(de::abs(my[0]), de::max(de::abs(my[1]), de::abs(my[2])));
-
-               scaleXBounds[1] = de::abs(mx[0]) + de::abs(mx[1]) + de::abs(mx[2]);
-               scaleYBounds[1] = de::abs(my[0]) + de::abs(my[1]) + de::abs(my[2]);
-
-               Vec2 scaleMaxBounds;
-
-               for (deUint8 compNdx = 0; compNdx < 2; ++compNdx)
-               {
-                       scaleMaxBounds[compNdx] = de::max(scaleXBounds[compNdx], scaleYBounds[compNdx]);
-               }
-
                float lodBias = m_samplerParams.lodBias;
 
                if (m_sampleLookupSettings.hasLodBias)
                        lodBias += args.lodBias;
 
-               for (deUint8 compNdx = 0; compNdx < 2; ++compNdx)
-               {
-                       lodBounds[compNdx] = deFloatLog2(scaleMaxBounds[compNdx]);
-                       lodBounds[compNdx] += lodBias;
-                       lodBounds[compNdx] = de::clamp(lodBounds[compNdx], m_samplerParams.minLod, m_samplerParams.maxLod);
-               }
+               lodBounds = calcLodBounds(dPdx.swizzle(0, 1, 2),
+                                                                 dPdy.swizzle(0, 1, 2),
+                                                                 m_imParams.size,
+                                                                 lodBias,
+                                                                 m_samplerParams.minLod,
+                                                                 m_samplerParams.maxLod);
        }
        else
        {
@@ -1118,73 +817,20 @@ bool SampleVerifier::verifySampleCubemapFace (const SampleArguments&     args,
 
        DE_ASSERT(lodBounds[0] <= lodBounds[1]);
 
-    const float q = (float) (m_imParams.levels - 1);
+    const UVec2 levelBounds = calcLevelBounds(lodBounds, m_imParams.levels, m_samplerParams.mipmapFilter);
 
-       if (m_samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_NEAREST)
+       for (deUint32 level = levelBounds[0]; level <= levelBounds[1]; ++level)
        {
-               UVec2 levelBounds;
-
-           if (lodBounds[0] <= 0.5f)
-               {
-                       levelBounds[0] = 0;
-               }
-               else if (lodBounds[0] < q + 0.5f)
-               {
-                       levelBounds[0] = deCeilFloatToInt32(lodBounds[0] + 0.5f) - 1;
-               }
-               else
-               {
-                       levelBounds[0] = deRoundFloatToInt32(q);
-               }
-
-               if (lodBounds[1] < 0.5f)
-               {
-                       levelBounds[1] = 0;
-               }
-               else if (lodBounds[1] < q + 0.5f)
-               {
-                       levelBounds[1] = deFloorFloatToInt32(lodBounds[1] + 0.5f);
-               }
-               else
-               {
-                       levelBounds[1] = deRoundFloatToInt32(q);
-               }
+               report << "Testing at mipmap level " << level << "...\n";
 
-               for (deUint8 level = (deUint8) levelBounds[0]; level <= (deUint8) levelBounds[1]; ++level)
-               {
-                       const Vec2 levelLodBounds = computeLevelLodBounds(lodBounds, level);
-
-                       if (verifySampleMipmapLevel(args, result, coord, levelLodBounds, level, report))
-                       {
-                               return true;
-                       }
-               }
-       }
-       else
-       {
-               UVec2 levelBounds;
+               const Vec2 levelLodBounds = calcLevelLodBounds(lodBounds, level);
 
-               for (deUint8 compNdx = 0; compNdx < 2; ++compNdx)
+               if (verifySampleMipmapLevel(args, result, coord, levelLodBounds, level, report))
                {
-                       if (lodBounds[compNdx] >= q)
-                       {
-                               levelBounds[compNdx] = deRoundFloatToInt32(q);
-                       }
-                       else
-                       {
-                               levelBounds[compNdx] = lodBounds[compNdx] < 0.0f ? 0 : deFloorFloatToInt32(lodBounds[compNdx]);
-                       }
+                       return true;
                }
 
-               for (deUint8 level = (deUint8) levelBounds[0]; level <= (deUint8) levelBounds[1]; ++level)
-               {
-                       const Vec2 levelLodBounds = computeLevelLodBounds(lodBounds, level);
-
-                       if (verifySampleMipmapLevel(args, result, coord, levelLodBounds, level, report))
-                       {
-                               return true;
-                       }
-               }
+               report << "Done testing mipmap level " << level << ".\n\n";
        }
 
        return false;
@@ -1198,8 +844,8 @@ bool SampleVerifier::verifySampleImpl (const SampleArguments&      args,
        // \todo [2016-07-06 collinbaker] Handle dRef
        DE_ASSERT(m_samplerParams.isCompare == false);
 
-       Vec4 coord = args.coord;
-       deUint8 coordSize = 0;
+       Vec4    coord     = args.coord;
+       int coordSize = 0;
 
        if (m_imParams.dim == IMG_DIM_1D)
        {
@@ -1231,94 +877,39 @@ bool SampleVerifier::verifySampleImpl (const SampleArguments&    args,
 
        if (m_imParams.dim == IMG_DIM_CUBE)
        {
-               const Vec3 r = coord.swizzle(0, 1, 2);
-               const Vec3 drdx = dPdx.swizzle(0, 1, 2);
-               const Vec3 drdy = dPdy.swizzle(0, 1, 2);
-
-               BVec3 isMajor(false);
-               float rMax = de::abs(r[0]);
-
-               for (deUint8 compNdx = 1; compNdx < 3; ++compNdx)
-               {
-                       rMax = de::max(rMax, de::abs(r[compNdx]));
-               }
+               const Vec3      r                  = coord.swizzle(0, 1, 2);
+               const Vec3      drdx       = dPdx.swizzle(0, 1, 2);
+               const Vec3      drdy       = dPdy.swizzle(0, 1, 2);
 
-               for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
-               {
-                       if (de::abs(r[compNdx]) == rMax)
-                       {
-                               isMajor[compNdx] = true;
-                       }
-               }
-
-               DE_ASSERT(isMajor[0] || isMajor[1] || isMajor[2]);
+           int                 faceBitmap = calcCandidateCubemapFaces(r);
 
                // We must test every possible disambiguation order
 
-               for (deUint8 i = 0; i < 3; ++i)
+               for (int faceNdx = 0; faceNdx < 6; ++faceNdx)
                {
-                   if (!isMajor[i])
-                       {
-                               continue;
-                       }
+                       const bool isPossible = faceBitmap & (1U << faceNdx);
 
-                       const deUint8 faceNdx = (deUint8) (2U * i + (r[i] < 0.0f ? 1U : 0U));
-
-                       const deUint8 compMap[6][3] =
-                       {
-                               {2, 1, 0},
-                               {2, 1, 0},
-                               {0, 2, 1},
-                               {0, 2, 1},
-                               {0, 1, 2},
-                               {0, 1, 2}
-                       };
-
-                       const deInt8 signMap[6][3] =
+                   if (!isPossible)
                        {
-                               {-1, -1, +1},
-                               {+1, -1, -1},
-                               {+1, +1, +1},
-                               {+1, -1, -1},
-                               {+1, -1, +1},
-                               {-1, -1, -1}
-                       };
-
-                       Vec3 coordC;
-                       Vec3 dPcdx;
-                       Vec3 dPcdy;
-
-                       for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
-                       {
-                               const deUint8   mappedComp = compMap[faceNdx][compNdx];
-                               const deInt8    mappedSign = signMap[faceNdx][compNdx];
-
-                               coordC[compNdx] = r[mappedComp]         * mappedSign;
-                               dPcdx[compNdx]  = drdx[mappedComp]      * mappedSign;
-                               dPcdy[compNdx]  = drdy[mappedComp]      * mappedSign;
+                               continue;
                        }
 
-                       coordC[2] = de::abs(coordC[2]);
+                       Vec2 coordFace;
+                       Vec2 dPdxFace;
+                       Vec2 dPdyFace;
 
-                       Vec4 coordFace;
-                       Vec4 dPdxFace;
-                       Vec4 dPdyFace;
+                       calcCubemapFaceCoords(r, drdx, drdy, faceNdx, coordFace, dPdxFace, dPdyFace);
 
-                       for (deUint8 compNdx = 0; compNdx < 2; ++compNdx)
+                       if (verifySampleCubemapFace(args,
+                                                                               result,
+                                                                               Vec4(coordFace[0], coordFace[1], 0.0f, 0.0f),
+                                                                               Vec4(dPdxFace[0], dPdxFace[1], 0.0f, 0.0f),
+                                                                               Vec4(dPdyFace[0], dPdyFace[1], 0.0f, 0.0f),
+                                                                               faceNdx,
+                                                                               report))
                        {
-                               coordFace[compNdx] = 0.5f * coordC[compNdx] / de::abs(coordC[2]) + 0.5f;
-
-                               dPdxFace[compNdx]  = 0.5f * (de::abs(coordC[2]) * dPcdx[compNdx] - coordC[compNdx] * dPcdx[2]) / (coordC[2] * coordC[2]);
-                               dPdyFace[compNdx]  = 0.5f * (de::abs(coordC[2]) * dPcdy[compNdx] - coordC[compNdx] * dPcdy[2]) / (coordC[2] * coordC[2]);
-                       }
-
-                       for (deUint8 compNdx = 2; compNdx < 4; ++compNdx)
-                       {
-                               coordFace[compNdx] = dPdxFace[compNdx] = dPdyFace[compNdx] = 0.0f;
-                       }
-
-                       if (verifySampleCubemapFace(args, result, coordFace, dPdxFace, dPdyFace, faceNdx, report))
                                return true;
+                       }
                }
 
                return false;
index 28981d6..7316bac 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "deUniquePtr.hpp"
 
+#include "tcuFloatFormat.hpp"
 #include "tcuTexture.hpp"
 #include "tcuVector.hpp"
 
@@ -112,10 +113,10 @@ struct ImageViewParameters
        ImgDim                  dim;
        vk::VkFormat    format;
        tcu::IVec3              size;
-       deUint8                 levels;
+       int                             levels;
 
        bool                    isArrayed;
-       deUint32                arrayLayers;
+       int                             arrayLayers;
 };
 
 class SampleVerifier
@@ -136,30 +137,25 @@ public:
                                                                                 std::string&                                                                           report) const;
 
 private:
-       bool verifySampleMipmapLinear           (tcu::Vec4                                                                                      result,
-                                                                                tcu::Vec4                                                                                      sampleHi,
-                                                                                tcu::Vec4                                                                                      sampleLo,
-                                                                                deInt32                                                                                        lodStepMin,
-                                                                                deInt32                                                                                        lodStepMax,
-                                                                                deUint32                                                                                       layer,
-                                                                                deUint8                                                                                        levelHi) const;
 
        bool verifySampleFiltered                       (const tcu::Vec4&                                                                       result,
-                                                                                const tcu::Vec3&                                                                       unnormalizedCoordHi,
-                                                                                const tcu::Vec3&                                                                       unnormalizedCoordLo,
-                                                                                deUint32                                                                                       layer,
-                                                                                deUint8                                                                                        levelHi,
+                                                                                const tcu::IVec3&                                                                  baseTexelHi,
+                                                                                const tcu::IVec3&                                                                  baseTexelLo,
+                                                                                const tcu::IVec3&                                                                  texelGridOffsetHi,
+                                                                                const tcu::IVec3&                                                                  texelGridOffsetLo,
+                                                                                int                                                                                            layer,
+                                                                                int                                                                                            levelHi,
                                                                                 const tcu::Vec2&                                                                       lodFracBounds,
                                                                                 vk::VkFilter                                                                           filter,
                                                                                 vk::VkSamplerMipmapMode                                                        mipmapFilter,
                                                                                 std::ostream&                                                                          report) const;
 
-       bool verifySampleUnnormalizedCoords (const SampleArguments&                                                             args,
+       bool verifySampleTexelGridCoords        (const SampleArguments&                                                         args,
                                                                                 const tcu::Vec4&                                                                       result,
-                                                                                const tcu::Vec3&                                                                       unnormalizedCoord,
-                                                                                const tcu::Vec3&                                                                       unnormalizedCoordLo,
+                                                                                const tcu::IVec3&                                                                      gridCoordHi,
+                                                                                const tcu::IVec3&                                                                      gridCoordLo,
                                                                                 const tcu::Vec2&                                                                       lodBounds,
-                                                                                deUint8                                                                                        level,
+                                                                                int                                                                                            level,
                                                                                 vk::VkSamplerMipmapMode                                                        mipmapFilter,
                                                                                 std::ostream&                                                                          report) const;
 
@@ -167,7 +163,7 @@ private:
                                                                                 const tcu::Vec4&                                                                       result,
                                                                                 const tcu::Vec4&                                                                       coord,
                                                                                 const tcu::Vec2&                                                                       lodFracBounds,
-                                                                                deUint8                                                                                        level,
+                                                                                int                                                                                            level,
                                                                                 std::ostream&                                                                          report) const;
 
        bool verifySampleCubemapFace            (const SampleArguments&                                                         args,
@@ -175,7 +171,7 @@ private:
                                                                                 const tcu::Vec4&                                                                       coord,
                                                                                 const tcu::Vec4&                                                                       dPdx,
                                                                                 const tcu::Vec4&                                                                       dPdy,
-                                                                                deUint8                                                                                        face,
+                                                                                int                                                                                            face,
                                                                                 std::ostream&                                                                          report) const;
 
        bool verifySampleImpl                           (const SampleArguments&                                                         args,
@@ -186,48 +182,61 @@ private:
                                                                                 int                                                                                            compNdx,
                                                                                 int                                                                                            level) const;
 
-       tcu::Vec4 fetchTexel                            (const tcu::IVec3&                                                                      coordIn,
-                                                                                deUint32                                                                                       layer,
-                                                                                deUint8                                                                                        level,
-                                                                                vk::VkFilter                                                                           filter) const;
+       void fetchTexel                                         (const tcu::IVec3&                                                                      coordIn,
+                                                                                int                                                                                            layer,
+                                                                                int                                                                                            level,
+                                                                                vk::VkFilter                                                                           filter,
+                                                                                tcu::Vec4&                                                                             resultMin,
+                                                                                tcu::Vec4&                                                                             resultMax) const;
+
+       void fetchTexelWrapped                          (const tcu::IVec3&                                                                      coord,
+                                                                                int                                                                                            layer,
+                                                                                int                                                                                            level,
+                                                                                tcu::Vec4&                                                                                     resultMin,
+                                                                                tcu::Vec4&                                                                             resultMax) const;
 
-       tcu::Vec4 getFilteredSample1D           (const tcu::IVec3&                                                                      texelBase,
+    void getFilteredSample1D                   (const tcu::IVec3&                                                                      texelBase,
                                                                                 float                                                                                          weight,
-                                                                                deUint32                                                                                       layer,
-                                                                                deUint8                                                                                        level) const;
+                                                                                int                                                                                            layer,
+                                                                                int                                                                                            level,
+                                                                                tcu::Vec4&                                                                             resultMin,
+                                                                                tcu::Vec4&                                                                             resultMax) const;
 
-       tcu::Vec4 getFilteredSample2D           (const tcu::IVec3&                                                                      texelBase,
+       void getFilteredSample2D                        (const tcu::IVec3&                                                                      texelBase,
                                                                                 const tcu::Vec2&                                                                       weights,
-                                                                                deUint32                                                                                       layer,
-                                                                                deUint8                                                                                        level) const;
+                                                                                int                                                                                            layer,
+                                                                                int                                                                                            level,
+                                                                                tcu::Vec4&                                                                             resultMin,
+                                                                                tcu::Vec4&                                                                             resultMax) const;
 
-       tcu::Vec4 getFilteredSample3D           (const tcu::IVec3&                                                                      texelBase,
+       void getFilteredSample3D                        (const tcu::IVec3&                                                                      texelBase,
                                                                                 const tcu::Vec3&                                                                       weights,
-                                                                                deUint32                                                                                       layer,
-                                                                                deUint8                                                                                        level) const;
+                                                                                int                                                                                            layer,
+                                                                                int                                                                                            level,
+                                                                                tcu::Vec4&                                                                             resultMin,
+                                                                                tcu::Vec4&                                                                             resultMax) const;
 
-       tcu::Vec4 getFilteredSample                     (const tcu::IVec3&                                                                      texelBase,
+       void getFilteredSample                          (const tcu::IVec3&                                                                      texelBase,
                                                                                 const tcu::Vec3&                                                                       weights,
-                                                                                deUint32                                                                                       layer,
-                                                                                deUint8                                                                                        level) const;
-
-       void getWeightStepBounds                        (const tcu::Vec3&                                                                       unnormalizedCoord,
-                                                                                tcu::IVec3&                                                                            weightStepMin,
-                                                                                tcu::IVec3&                                                                            weightStepMax,
-                                                                                tcu::IVec3&                                                                            texelBase) const;
+                                                                                int                                                                                            layer,
+                                                                                int                                                                                            level,
+                                                                                tcu::Vec4&                                                                             resultMin,
+                                                                                tcu::Vec4&                                                                             resultMax) const;
 
        void getMipmapStepBounds                        (const tcu::Vec2&                                                                       lodFracBounds,
                                                                                 deInt32&                                                                                       stepMin,
                                                                                 deInt32&                                                                                       stepMax) const;
 
+       const tcu::FloatFormat                                                  m_internalFormat;
+
        const ImageViewParameters&                                              m_imParams;
        const SamplerParameters&                                                m_samplerParams;
        const SampleLookupSettings&                                             m_sampleLookupSettings;
 
-    int                                                                                                m_coordBits;
-       int                                                                                             m_mipmapBits;
+    const int                                                                          m_coordBits;
+       const int                                                                               m_mipmapBits;
 
-       int                                                                                             m_unnormalizedDim;
+       const int                                                                               m_unnormalizedDim;
 
        const std::vector<tcu::ConstPixelBufferAccess>& m_pba;
 };
diff --git a/external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifierUtil.cpp b/external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifierUtil.cpp
new file mode 100644 (file)
index 0000000..9496f2d
--- /dev/null
@@ -0,0 +1,952 @@
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief GPU image sample verification
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSampleVerifierUtil.hpp"
+
+#include "deMath.h"
+#include "tcuDefs.hpp"
+#include "tcuFloat.hpp"
+#include "tcuFloatFormat.hpp"
+#include "tcuInterval.hpp"
+#include "tcuTexture.hpp"
+#include "tcuTextureUtil.hpp"
+
+namespace vkt
+{
+namespace texture_filtering
+{
+namespace util
+{
+
+using namespace tcu;
+using namespace vk;
+
+deInt32 mod (const deInt32 a, const deInt32 n)
+{
+       const deInt32 result = a % n;
+
+       return (result < 0) ? result + n : result;
+}
+
+deInt32 mirror (const deInt32 n)
+{
+       if (n >= 0)
+       {
+               return n;
+       }
+       else
+       {
+               return -(1 + n);
+       }
+}
+
+UVec2 calcLevelBounds (const Vec2&                     lodBounds,
+                                          const int                    levelCount,
+                                          VkSamplerMipmapMode  mipmapFilter)
+{
+       DE_ASSERT(lodBounds[0] <= lodBounds[1]);
+       DE_ASSERT(levelCount > 0);
+
+       const float q = (float) (levelCount - 1);
+
+       UVec2 levelBounds;
+
+       if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_NEAREST)
+       {
+               if (lodBounds[0] <= 0.5f)
+               {
+                       levelBounds[0] = 0;
+               }
+               else if (lodBounds[0] < q + 0.5f)
+               {
+                       levelBounds[0] = deCeilFloatToInt32(lodBounds[0] + 0.5f) - 1;
+               }
+               else
+               {
+                       levelBounds[0] = deRoundFloatToInt32(q);
+               }
+
+               if (lodBounds[1] < 0.5f)
+               {
+                       levelBounds[1] = 0;
+               }
+               else if (lodBounds[1] < q + 0.5f)
+               {
+                       levelBounds[1] = deFloorFloatToInt32(lodBounds[1] + 0.5f);
+               }
+               else
+               {
+                       levelBounds[1] = deRoundFloatToInt32(q);
+               }
+       }
+       else
+       {
+               for (int ndx = 0; ndx < 2; ++ndx)
+               {
+                       if (lodBounds[ndx] >= q)
+                       {
+                               levelBounds[ndx] = deRoundFloatToInt32(q);
+                       }
+                       else
+                       {
+                               levelBounds[ndx] = lodBounds[ndx] < 0.0f ? 0 : deFloorFloatToInt32(lodBounds[ndx]);
+                       }
+               }
+       }
+
+       return levelBounds;
+}
+
+Vec2 calcLevelLodBounds (const Vec2& lodBounds, int level)
+{
+       Vec2 levelLodBounds;
+
+       if (lodBounds[0] <= 0.0f)
+       {
+               levelLodBounds[0] = lodBounds[0];
+       }
+       else
+       {
+               levelLodBounds[0] = de::max(lodBounds[0], (float) level);
+       }
+
+       levelLodBounds[1] = de::min(lodBounds[1], (float) level + 1.0f);
+
+       return levelLodBounds;
+}
+
+float addUlp (float num, deInt32 ulp)
+{
+       // Note: adding positive ulp always moves float away from zero
+
+       const tcu::Float32 f(num);
+
+       DE_ASSERT(!f.isNaN() && !f.isInf());
+       DE_ASSERT(num > FLT_MIN * (float) ulp || num < FLT_MIN * (float) ulp);
+
+       return tcu::Float32(f.bits() + ulp).asFloat();
+}
+
+void wrapTexelGridCoordLinear (IVec3&          baseTexel,
+                                                          IVec3&               texelGridOffset,
+                                                          const int    coordBits,
+                                                          const ImgDim dim)
+{
+       const int subdivisions = 1 << coordBits;
+
+       int numComp;
+
+       switch (dim)
+       {
+               case IMG_DIM_1D:
+                       numComp = 1;
+                       break;
+
+               case IMG_DIM_2D:
+                       numComp = 2;
+                       break;
+
+               case IMG_DIM_CUBE:
+                       numComp = 2;
+                       break;
+
+               case IMG_DIM_3D:
+                       numComp = 3;
+                       break;
+
+               default:
+                       numComp = 0;
+                       break;
+       }
+
+       for (int compNdx = 0; compNdx < numComp; ++compNdx)
+       {
+               texelGridOffset[compNdx] -= subdivisions / (int) 2;
+
+               if (texelGridOffset[compNdx] < 0)
+               {
+                       baseTexel      [compNdx] -= 1;
+                       texelGridOffset[compNdx] += (deInt32) subdivisions;
+               }
+       }
+}
+
+void calcTexelBaseOffset (const IVec3& gridCoord,
+                                                 const int             coordBits,
+                                                 IVec3&                baseTexel,
+                                                 IVec3&                texelGridOffset)
+{
+       const int subdivisions = (int) 1 << coordBits;
+
+       for (int compNdx = 0; compNdx < 3; ++compNdx)
+       {
+               // \todo [2016-07-22 collinbaker] Do floor division to properly handle negative coords
+               baseTexel[compNdx]               = gridCoord[compNdx] / (deInt32) subdivisions;
+               texelGridOffset[compNdx] = gridCoord[compNdx] % (deInt32) subdivisions;
+       }
+}
+
+void calcTexelGridCoordRange (const Vec3&      unnormalizedCoordMin,
+                                                         const Vec3&   unnormalizedCoordMax,
+                                                         const int             coordBits,
+                                                         IVec3&                gridCoordMin,
+                                                         IVec3&                gridCoordMax)
+{
+       const int subdivisions = 1 << coordBits;
+
+       for (int compNdx = 0; compNdx < 3; ++compNdx)
+       {
+               const float comp[2] = {unnormalizedCoordMin[compNdx],
+                                                          unnormalizedCoordMax[compNdx]};
+
+               float   fracPart[2];
+               double  intPart[2];
+
+               for (int ndx = 0; ndx < 2; ++ndx)
+               {
+                       fracPart[ndx] = (float) deModf(comp[ndx], &intPart[ndx]);
+
+                       if (comp[ndx] < 0.0f)
+                       {
+                               intPart [ndx] -= 1.0;
+                               fracPart[ndx] += 1.0f;
+                       }
+               }
+
+               const deInt32   nearestTexelGridOffsetMin = (deInt32) deFloor(intPart[0]);
+               const deInt32   nearestTexelGridOffsetMax = (deInt32) deFloor(intPart[1]);
+
+               const deInt32   subTexelGridCoordMin      = de::max((deInt32) deFloor(fracPart[0] * (float) subdivisions), (deInt32) 0);
+               const deInt32   subTexelGridCoordMax      = de::min((deInt32) deCeil (fracPart[1] * (float) subdivisions), (deInt32) (subdivisions - 1));
+
+           gridCoordMin[compNdx] = nearestTexelGridOffsetMin * (deInt32) subdivisions + subTexelGridCoordMin;
+           gridCoordMax[compNdx] = nearestTexelGridOffsetMax * (deInt32) subdivisions + subTexelGridCoordMax;
+       }
+}
+
+void calcUnnormalizedCoordRange (const Vec4&           coord,
+                                                                const IVec3&           levelSize,
+                                                                const FloatFormat& internalFormat,
+                                                                Vec3&                          unnormalizedCoordMin,
+                                                                Vec3&                          unnormalizedCoordMax)
+{
+    for (int compNdx = 0; compNdx < 3; ++compNdx)
+       {
+               const int size = levelSize[compNdx];
+
+               Interval coordInterval = Interval(coord[compNdx]);
+               coordInterval = internalFormat.roundOut(coordInterval, false);
+
+               Interval unnormalizedCoordInterval = coordInterval * Interval((double) size);
+               unnormalizedCoordInterval = internalFormat.roundOut(unnormalizedCoordInterval, false);
+
+               unnormalizedCoordMin[compNdx] = (float)unnormalizedCoordInterval.lo();
+               unnormalizedCoordMax[compNdx] = (float)unnormalizedCoordInterval.hi();
+       }
+}
+
+Vec2 calcLodBounds (const Vec3& dPdx,
+                                       const Vec3& dPdy,
+                                       const IVec3 size,
+                                       const float lodBias,
+                                       const float lodMin,
+                                       const float lodMax)
+{
+       Vec2 lodBounds;
+
+       const Vec3 mx = abs(dPdx) * size.asFloat();
+       const Vec3 my = abs(dPdy) * size.asFloat();
+
+       Vec2 scaleXBounds;
+       Vec2 scaleYBounds;
+
+       scaleXBounds[0] = de::max(de::abs(mx[0]), de::max(de::abs(mx[1]), de::abs(mx[2])));
+       scaleYBounds[0] = de::max(de::abs(my[0]), de::max(de::abs(my[1]), de::abs(my[2])));
+
+       scaleXBounds[1] = de::abs(mx[0]) + de::abs(mx[1]) + de::abs(mx[2]);
+       scaleYBounds[1] = de::abs(my[0]) + de::abs(my[1]) + de::abs(my[2]);
+
+       Vec2 scaleMaxBounds;
+
+       for (int compNdx = 0; compNdx < 2; ++compNdx)
+       {
+               scaleMaxBounds[compNdx] = de::max(scaleXBounds[compNdx], scaleYBounds[compNdx]);
+       }
+
+       for (int ndx = 0; ndx < 2; ++ndx)
+       {
+               lodBounds[ndx] = deFloatLog2(scaleMaxBounds[ndx]);
+               lodBounds[ndx] += lodBias;
+               lodBounds[ndx] = de::clamp(lodBounds[ndx], lodMin, lodMax);
+       }
+
+       return lodBounds;
+}
+
+void calcCubemapFaceCoords (const Vec3& r,
+                                                       const Vec3& drdx,
+                                                       const Vec3& drdy,
+                                                       const int       faceNdx,
+                                                       Vec2&           coordFace,
+                                                       Vec2&           dPdxFace,
+                                                       Vec2&           dPdyFace)
+{
+       DE_ASSERT(faceNdx >= 0 && faceNdx < 6);
+
+       static const int compMap[6][3] =
+       {
+               {2, 1, 0},
+               {2, 1, 0},
+               {0, 2, 1},
+               {0, 2, 1},
+               {0, 1, 2},
+               {0, 1, 2}
+       };
+
+       static const int signMap[6][3] =
+       {
+               {-1, -1, +1},
+               {+1, -1, -1},
+               {+1, +1, +1},
+               {+1, -1, -1},
+               {+1, -1, +1},
+               {-1, -1, -1}
+       };
+
+       Vec3 coordC;
+       Vec3 dPcdx;
+       Vec3 dPcdy;
+
+       for (int compNdx = 0; compNdx < 3; ++compNdx)
+       {
+               const int       mappedComp = compMap[faceNdx][compNdx];
+               const int       mappedSign = signMap[faceNdx][compNdx];
+
+               coordC[compNdx] = r   [mappedComp]      * (float)mappedSign;
+               dPcdx [compNdx] = drdx[mappedComp]      * (float)mappedSign;
+               dPcdy [compNdx] = drdy[mappedComp]      * (float)mappedSign;
+       }
+
+       DE_ASSERT(coordC[2] != 0.0f);
+       coordC[2] = de::abs(coordC[2]);
+
+       for (int compNdx = 0; compNdx < 2; ++compNdx)
+       {
+               coordFace[compNdx] = 0.5f * coordC[compNdx] / de::abs(coordC[2]) + 0.5f;
+
+               dPdxFace [compNdx] = 0.5f * (de::abs(coordC[2]) * dPcdx[compNdx] - coordC[compNdx] * dPcdx[2]) / (coordC[2] * coordC[2]);
+               dPdyFace [compNdx] = 0.5f * (de::abs(coordC[2]) * dPcdy[compNdx] - coordC[compNdx] * dPcdy[2]) / (coordC[2] * coordC[2]);
+       }
+}
+
+int calcCandidateCubemapFaces (const Vec3& r)
+{
+       deUint8 faceBitmap = 0;
+       float   rMax       = de::abs(r[0]);
+
+       for (int compNdx = 1; compNdx < 3; ++compNdx)
+       {
+               rMax = de::max(rMax, de::abs(r[compNdx]));
+       }
+
+       for (int compNdx = 0; compNdx < 3; ++compNdx)
+       {
+               if (de::abs(r[compNdx]) == rMax)
+               {
+                       const int faceNdx = 2 * compNdx + (r[compNdx] < 0.0f ? 1 : 0);
+
+                       DE_ASSERT(faceNdx < 6);
+
+                       faceBitmap = faceBitmap | (deUint8) (1U << faceNdx);
+               }
+       }
+
+       DE_ASSERT(faceBitmap != 0U);
+
+       return faceBitmap;
+}
+
+deInt32 wrapTexelCoord (const deInt32 coord,
+                                               const int size,
+                                               const VkSamplerAddressMode wrap)
+{
+       deInt32 wrappedCoord = 0;
+
+       switch (wrap)
+       {
+               case VK_SAMPLER_ADDRESS_MODE_REPEAT:
+                       wrappedCoord = mod(coord, size);
+                       break;
+
+               case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
+                       wrappedCoord = (size - 1) - mirror(mod(coord, 2 * size) - size);
+                       break;
+
+               case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
+                       wrappedCoord = de::clamp(coord, 0, (deInt32) size - 1);
+                       break;
+
+               case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
+                       wrappedCoord = de::clamp(coord, -1, (deInt32) size);
+                       break;
+
+               case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
+                       wrappedCoord = de::clamp(mirror(coord), 0, (deInt32) size - 1);
+                       break;
+
+               default:
+                       DE_FATAL("Invalid VkSamplerAddressMode");
+                       break;
+       }
+
+       return wrappedCoord;
+}
+
+namespace
+{
+
+// Cube map adjacent faces ordered clockwise from top
+// \todo [2016-07-07 collinbaker] Verify these are correct
+static const int adjacentFaces[6][4] =
+{
+       {3, 5, 2, 4},
+       {3, 4, 2, 5},
+       {4, 0, 5, 1},
+       {5, 0, 4, 1},
+       {3, 0, 2, 1},
+       {3, 1, 2, 0}
+};
+
+static const int adjacentEdges[6][4] =
+{
+       {1, 3, 1, 1},
+       {3, 3, 3, 1},
+       {2, 2, 2, 2},
+       {0, 0, 0, 0},
+       {2, 3, 0, 1},
+       {0, 3, 2, 1}
+};
+
+static const int adjacentEdgeDirs[6][4] =
+{
+       {-1, +1, +1, +1},
+       {+1, +1, -1, +1},
+       {+1, +1, -1, -1},
+       {-1, -1, +1, +1},
+       {+1, +1, +1, +1},
+       {-1, +1, -1, +1}
+};
+
+static const int edgeComponent[4] = {0, 1, 0, 1};
+
+static const int edgeFactors[4][2] =
+{
+       {0, 0},
+       {1, 0},
+       {0, 1},
+       {0, 0}
+};
+
+} // anonymous
+
+void wrapCubemapEdge (const IVec2&     coord,
+                                         const IVec2&  size,
+                                         const int             faceNdx,
+                                         IVec2&                newCoord,
+                                         int&                  newFaceNdx)
+{
+       int edgeNdx = -1;
+
+       if (coord[1] < 0)
+       {
+               edgeNdx = 0;
+       }
+       else if (coord[0] > 0)
+       {
+               edgeNdx = 1;
+       }
+       else if (coord[1] > 0)
+       {
+               edgeNdx = 2;
+       }
+       else
+       {
+               edgeNdx = 3;
+       }
+
+       const int               adjacentEdgeNdx = adjacentEdges[faceNdx][edgeNdx];
+       const IVec2             edgeFactor              = IVec2(edgeFactors[adjacentEdgeNdx][0],
+                                                                                       edgeFactors[adjacentEdgeNdx][1]);
+       const IVec2             edgeOffset              = edgeFactor * (size - IVec2(1));
+
+       if (adjacentEdgeDirs[faceNdx][edgeNdx] > 0)
+       {
+               newCoord[edgeComponent[adjacentEdgeNdx]] = coord[edgeComponent[edgeNdx]];
+       }
+       else
+       {
+               newCoord[edgeComponent[adjacentEdgeNdx]] =
+                   size[edgeComponent[edgeNdx]] - coord[edgeComponent[edgeNdx]] - 1;
+       }
+
+       newCoord[1 - edgeComponent[adjacentEdgeNdx]] = 0;
+       newCoord += edgeOffset;
+
+       newFaceNdx = adjacentFaces[faceNdx][edgeNdx];
+}
+
+void wrapCubemapCorner (const IVec2&   coord,
+                                               const IVec2&    size,
+                                               const int               faceNdx,
+                                               int&                    adjacentFace1,
+                                               int&                    adjacentFace2,
+                                               IVec2&                  cornerCoord0,
+                                               IVec2&                  cornerCoord1,
+                                               IVec2&                  cornerCoord2)
+{
+       int cornerNdx = -1;
+
+       if (coord[0] < 0 && coord[1] < 0)
+       {
+               cornerNdx = 0;
+       }
+       else if (coord[0] > 0 && coord[1] < 0)
+       {
+               cornerNdx = 1;
+       }
+       else if (coord[0] > 0 && coord[1] > 0)
+       {
+               cornerNdx = 2;
+       }
+       else
+       {
+               cornerNdx = 3;
+       }
+
+       const int cornerEdges[2] = {cornerNdx, (int) ((cornerNdx + 3) % 4)};
+
+       int               faceCorners[3] = {cornerNdx, 0, 0};
+
+       for (int edgeNdx = 0; edgeNdx < 2; ++edgeNdx)
+       {
+               const int faceEdge = adjacentEdges[faceNdx][cornerEdges[edgeNdx]];
+
+               bool isFlipped = (adjacentEdgeDirs[faceNdx][cornerEdges[edgeNdx]]);
+
+               if ((cornerEdges[edgeNdx] > 1) != (faceEdge > 1))
+               {
+                       isFlipped = !isFlipped;
+               }
+
+               if (isFlipped)
+               {
+                       faceCorners[edgeNdx + 1] = (faceEdge + 1) % 4;
+               }
+               else
+               {
+                       faceCorners[edgeNdx + 1] = faceEdge;
+               }
+       }
+
+       adjacentFace1 = adjacentFaces[faceNdx][cornerEdges[0]];
+       adjacentFace2 = adjacentFaces[faceNdx][cornerEdges[1]];
+
+       IVec2* cornerCoords[3] = {&cornerCoord0, &cornerCoord1, &cornerCoord2};
+
+       for (int ndx = 0; ndx < 3; ++ndx)
+       {
+               IVec2 cornerFactor;
+
+               switch (faceCorners[faceNdx])
+               {
+                       case 0:
+                               cornerFactor = IVec2(0, 0);
+                               break;
+
+                       case 1:
+                               cornerFactor = IVec2(1, 0);
+                               break;
+
+                       case 2:
+                               cornerFactor = IVec2(1, 1);
+                               break;
+
+                       case 3:
+                               cornerFactor = IVec2(0, 1);
+                               break;
+
+                       default:
+                               break;
+               }
+
+           *cornerCoords[ndx] = cornerFactor * (size - IVec2(1));
+       }
+}
+
+namespace
+{
+
+deInt64 signExtend (deUint64 src, int bits)
+{
+       const deUint64 signBit = 1u << (bits-1);
+
+       src |= ~((src & signBit) - 1);
+
+       return (deInt64) src;
+}
+
+void convertFP16 (const void*  fp16Ptr,
+                                 FloatFormat   internalFormat,
+                                 float&                resultMin,
+                                 float&                resultMax)
+{
+       const Float16  fp16(*(const deUint16*) fp16Ptr);
+       const Interval fpInterval = internalFormat.roundOut(Interval(fp16.asDouble()), false);
+
+       resultMin = (float) fpInterval.lo();
+       resultMax = (float) fpInterval.hi();
+}
+
+void convertNormalizedInt (deInt64             num,
+                                                  int                  numBits,
+                                                  bool                 isSigned,
+                                                  FloatFormat  internalFormat,
+                                                  float&               resultMin,
+                                                  float&               resultMax)
+{
+       DE_ASSERT(numBits > 0);
+
+       const double    c        = (double) num;
+       deUint64                exp      = numBits;
+
+       if (isSigned)
+               --exp;
+
+       const double div = (double) (((deUint64) 1 << exp) - 1);
+
+       Interval resultInterval(de::max(c / div, -1.0));
+       resultInterval = internalFormat.roundOut(resultInterval, false);
+
+       resultMin = (float) resultInterval.lo();
+       resultMax = (float) resultInterval.hi();
+}
+
+bool isPackedType (const TextureFormat::ChannelType type)
+{
+       DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
+
+       switch (type)
+       {
+               case TextureFormat::UNORM_BYTE_44:
+               case TextureFormat::UNORM_SHORT_565:
+               case TextureFormat::UNORM_SHORT_555:
+               case TextureFormat::UNORM_SHORT_4444:
+               case TextureFormat::UNORM_SHORT_5551:
+               case TextureFormat::UNORM_SHORT_1555:
+               case TextureFormat::UNORM_INT_101010:
+               case TextureFormat::SNORM_INT_1010102_REV:
+               case TextureFormat::UNORM_INT_1010102_REV:
+                       return true;
+
+               default:
+                       return false;
+       }
+}
+
+void getPackInfo (const TextureFormat texFormat,
+                                 IVec4& bitSizes,
+                                 IVec4& bitOffsets,
+                                 int& baseTypeBytes)
+{
+       DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
+
+       switch (texFormat.type)
+       {
+               case TextureFormat::UNORM_BYTE_44:
+                       bitSizes = IVec4(4, 4, 0, 0);
+                       bitOffsets = IVec4(0, 4, 0, 0);
+                       baseTypeBytes = 1;
+                       break;
+
+               case TextureFormat::UNORM_SHORT_565:
+                       bitSizes = IVec4(5, 6, 5, 0);
+                       bitOffsets = IVec4(0, 5, 11, 0);
+                       baseTypeBytes = 2;
+                       break;
+
+               case TextureFormat::UNORM_SHORT_555:
+                       bitSizes = IVec4(5, 5, 5, 0);
+                       bitOffsets = IVec4(0, 5, 10, 0);
+                       baseTypeBytes = 2;
+                       break;
+
+               case TextureFormat::UNORM_SHORT_4444:
+                       bitSizes = IVec4(4, 4, 4, 4);
+                       bitOffsets = IVec4(0, 4, 8, 12);
+                       baseTypeBytes = 2;
+                       break;
+
+               case TextureFormat::UNORM_SHORT_5551:
+                       bitSizes = IVec4(5, 5, 5, 1);
+                       bitOffsets = IVec4(0, 5, 10, 15);
+                       baseTypeBytes = 2;
+                       break;
+
+               case TextureFormat::UNORM_SHORT_1555:
+                       bitSizes = IVec4(1, 5, 5, 5);
+                       bitOffsets = IVec4(0, 1, 6, 11);
+                       baseTypeBytes = 2;
+                       break;
+
+               case TextureFormat::UNORM_INT_101010:
+                       bitSizes = IVec4(10, 10, 10, 0);
+                       bitOffsets = IVec4(0, 10, 20, 0);
+                       baseTypeBytes = 4;
+                       break;
+
+               case TextureFormat::SNORM_INT_1010102_REV:
+                       bitSizes = IVec4(2, 10, 10, 10);
+                       bitOffsets = IVec4(0, 2, 12, 22);
+                       baseTypeBytes = 4;
+                       break;
+
+               case TextureFormat::UNORM_INT_1010102_REV:
+                       bitSizes = IVec4(2, 10, 10, 10);
+                       bitOffsets = IVec4(0, 2, 12, 22);
+                       baseTypeBytes = 4;
+                       break;
+
+               default:
+                       DE_FATAL("Invalid texture channel type");
+                       return;
+       }
+}
+
+template <typename BaseType>
+deUint64 unpackBits (const BaseType pack,
+                                        const int              bitOffset,
+                                        const int              numBits)
+{
+       DE_ASSERT(bitOffset + numBits <= 8 * (int) sizeof(BaseType));
+
+       const BaseType mask = (BaseType) (((BaseType) 1 << (BaseType) numBits) - (BaseType) 1);
+
+    return mask & (pack >> (BaseType) (8 * (int) sizeof(BaseType) - bitOffset - numBits));
+}
+
+deUint64 readChannel (const void* ptr,
+                                         const int byteOffset,
+                                         const int numBytes)
+{
+       const deUint8*  cPtr   = (const deUint8*) ptr + byteOffset;
+       deUint64                result = 0;
+
+       for (int byteNdx = 0; byteNdx < numBytes; ++byteNdx)
+       {
+               result = (result << 8U) | (deUint64) (cPtr[numBytes - byteNdx - 1]);
+       }
+
+       return result;
+}
+
+void convertNormalizedFormat (const void*      pixelPtr,
+                                                         TextureFormat texFormat,
+                                                         FloatFormat   internalFormat,
+                                                         Vec4&                 resultMin,
+                                                         Vec4&                 resultMax)
+{
+    TextureSwizzle                             readSwizzle     = getChannelReadSwizzle(texFormat.order);
+       const TextureChannelClass       chanClass       = getTextureChannelClass(texFormat.type);
+
+       DE_ASSERT(getTextureChannelClass(texFormat.type) < 2);
+
+       // Information for non-packed types
+       int chanSize = -1;
+
+       // Information for packed types
+       IVec4 bitOffsets;
+       IVec4 bitSizes;
+       int baseTypeBytes = -1;
+
+       const bool isPacked = isPackedType(texFormat.type);
+
+       if (isPacked)
+       {
+               getPackInfo(texFormat, bitSizes, bitOffsets, baseTypeBytes);
+
+               // Kludge to work around deficiency in framework
+
+               if (texFormat.type == TextureFormat::UNORM_INT_1010102_REV ||
+                       texFormat.type == TextureFormat::SNORM_INT_1010102_REV)
+               {
+                       for (int ndx = 0; ndx < 2; ++ndx)
+                       {
+                               std::swap(readSwizzle.components[ndx], readSwizzle.components[3 - ndx]);
+                       }
+               }
+
+               DE_ASSERT(baseTypeBytes == 1 || baseTypeBytes == 2 || baseTypeBytes == 4);
+       }
+       else
+       {
+               chanSize = getChannelSize(texFormat.type);
+       }
+
+       const bool      isSigned = (chanClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
+       const bool      isSrgb   = isSRGB(texFormat);
+
+       // \todo [2016-08-01 collinbaker] Handle sRGB with correct rounding
+       DE_ASSERT(!isSrgb);
+       DE_UNREF(isSrgb);
+
+       for (int compNdx = 0; compNdx < 4; ++compNdx)
+       {
+               const TextureSwizzle::Channel chan = readSwizzle.components[compNdx];
+
+               if (chan == TextureSwizzle::CHANNEL_ZERO)
+               {
+                       resultMin[compNdx] = 0.0f;
+                       resultMax[compNdx] = 0.0f;
+               }
+               else if (chan == TextureSwizzle::CHANNEL_ONE)
+               {
+                       resultMin[compNdx] = 1.0f;
+                       resultMax[compNdx] = 1.0f;
+               }
+               else
+               {
+                       deUint64 chanUVal = 0;
+                       int chanBits = 0;
+
+                       if (isPacked)
+                       {
+                               deUint64 pack = readChannel(pixelPtr, 0, baseTypeBytes);
+                               chanBits = bitSizes[chan];
+
+                               switch (baseTypeBytes)
+                               {
+                                       case 1:
+                                               chanUVal = unpackBits<deUint8>((deUint8)pack, bitOffsets[chan], bitSizes[chan]);
+                                               break;
+
+                                       case 2:
+                                               chanUVal = unpackBits<deUint16>((deUint16)pack, bitOffsets[chan], bitSizes[chan]);
+                                               break;
+
+                                       case 4:
+                                               chanUVal = unpackBits<deUint32>((deUint32)pack, bitOffsets[chan], bitSizes[chan]);
+                                               break;
+
+                                       default:
+                                               break;
+                               }
+                       }
+                       else
+                       {
+                           chanUVal = readChannel(pixelPtr, chan * chanSize, chanSize);
+                               chanBits = 8 * chanSize;
+                       }
+
+                       deInt64 chanVal = 0;
+
+                       if (isSigned)
+                       {
+                               chanVal = signExtend(chanUVal, chanBits);
+                       }
+                       else
+                       {
+                               chanVal = (deInt64) chanUVal;
+                       }
+
+                       convertNormalizedInt(chanVal, chanBits, isSigned, internalFormat, resultMin[compNdx], resultMax[compNdx]);
+               }
+       }
+}
+
+void convertFloatFormat (const void*   pixelPtr,
+                                                TextureFormat  texFormat,
+                                                FloatFormat    internalFormat,
+                                                Vec4&                  resultMin,
+                                                Vec4&                  resultMax)
+{
+       DE_ASSERT(getTextureChannelClass(texFormat.type) == TEXTURECHANNELCLASS_FLOATING_POINT);
+
+       const TextureSwizzle readSwizzle = getChannelReadSwizzle(texFormat.order);
+
+       for (int compNdx = 0; compNdx < 4; ++compNdx)
+       {
+               const TextureSwizzle::Channel chan = readSwizzle.components[compNdx];
+
+               if (chan == TextureSwizzle::CHANNEL_ZERO)
+               {
+                       resultMin[compNdx] = 0.0f;
+                       resultMax[compNdx] = 0.0f;
+               }
+               else if (chan == TextureSwizzle::CHANNEL_ONE)
+               {
+                       resultMin[compNdx] = 1.0f;
+                       resultMax[compNdx] = 1.0f;
+               }
+               else if (texFormat.type == TextureFormat::FLOAT)
+               {
+                       resultMin[compNdx] = resultMax[compNdx] = *((const float*)pixelPtr + chan);
+               }
+               else if (texFormat.type == TextureFormat::HALF_FLOAT)
+               {
+                       convertFP16((const deUint16*) pixelPtr + chan, internalFormat, resultMin[compNdx], resultMax[compNdx]);
+               }
+               else
+               {
+                       DE_FATAL("Unsupported floating point format");
+               }
+       }
+}
+
+} // anonymous
+
+void convertFormat (const void*                pixelPtr,
+                                       TextureFormat   texFormat,
+                                       FloatFormat             internalFormat,
+                                       Vec4&                   resultMin,
+                                       Vec4&                   resultMax)
+{
+       const TextureChannelClass       chanClass        = getTextureChannelClass(texFormat.type);
+
+       // \todo [2016-08-01 collinbaker] Handle float and shared exponent formats
+       if (chanClass == TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || chanClass == TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
+       {
+               convertNormalizedFormat(pixelPtr, texFormat, internalFormat, resultMin, resultMax);
+       }
+       else if (chanClass == TEXTURECHANNELCLASS_FLOATING_POINT)
+       {
+               convertFloatFormat(pixelPtr, texFormat, internalFormat, resultMin, resultMax);
+       }
+       else
+       {
+               DE_FATAL("Unimplemented");
+       }
+}
+
+} // util
+} // texture_filtering
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifierUtil.hpp b/external/vulkancts/modules/vulkan/texture_filtering/vktSampleVerifierUtil.hpp
new file mode 100644 (file)
index 0000000..e1566c6
--- /dev/null
@@ -0,0 +1,179 @@
+#ifndef _VKTSAMPLEVERIFIERUTIL_HPP
+#define _VKTSAMPLEVERIFIERUTIL_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief GPU image sample verification
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSampleVerifier.hpp"
+
+#include "deMath.h"
+#include "tcuFloatFormat.hpp"
+#include "tcuTexture.hpp"
+#include "vkDefs.hpp"
+
+namespace vkt
+{
+namespace texture_filtering
+{
+namespace util
+{
+
+float          addUlp                                          (float                                                  num,
+                                                                                deInt32                                                ulp);
+
+deInt32                mod                                                     (const deInt32                                  a,
+                                                                                const deInt32                                  n);
+deInt32            mirror                                              (const deInt32                                  n);
+
+tcu::Vec2      calcLodBounds                           (const tcu::Vec3&                               dPdx,
+                                                                                const tcu::Vec3&                               dPdy,
+                                                                                const tcu::IVec3                               size,
+                                                                                const float                                    lodBias,
+                                                                                const float                                    lodMin,
+                                                                                const float                                    lodMax);
+tcu::UVec2     calcLevelBounds                         (const tcu::Vec2&                               lodBounds,
+                                                                                const int                                              levelCount,
+                                                                                vk::VkSamplerMipmapMode                mipmapFilter);
+tcu::Vec2      calcLevelLodBounds                      (const tcu::Vec2&                               lodBounds,
+                                                                                int                                                    level);
+
+void           wrapTexelGridCoordLinear        (tcu::IVec3&                                    baseTexel,
+                                                                                tcu::IVec3&                                    texelGridOffset,
+                                                                                const int                                              coordBits,
+                                                                                const ImgDim                                   dim);
+void           calcTexelBaseOffset                     (const tcu::IVec3&                              gridCoord,
+                                                                                const int                                              coordBits,
+                                                                                tcu::IVec3&                                    baseTexel,
+                                                                                tcu::IVec3&                                    texelGridOffset);
+void           calcTexelGridCoordRange         (const tcu::Vec3&                               unnormalizedCoordMin,
+                                                                                const tcu::Vec3&                               unnormalizedCoordMax,
+                                                                                const int                                              coordBits,
+                                                                                tcu::IVec3&                                    gridCoordMin,
+                                                                                tcu::IVec3&                                    gridCoordMax);
+void           calcUnnormalizedCoordRange      (const tcu::Vec4&                               coord,
+                                                                                const tcu::IVec3&                              levelSize,
+                                                                                const tcu::FloatFormat&                internalFormat,
+                                                                                tcu::Vec3&                                             unnormalizedCoordMin,
+                                                                                tcu::Vec3&                                             unnormalizedCoordMax);
+void           calcCubemapFaceCoords           (const tcu::Vec3&                               r,
+                                                                                const tcu::Vec3&                               drdx,
+                                                                                const tcu::Vec3&                               drdy,
+                                                                                const int                                              faceNdx,
+                                                                                tcu::Vec2&                                             coordFace,
+                                                                                tcu::Vec2&                                             dPdxFace,
+                                                                                tcu::Vec2&                                             dPdyFace);
+int            calcCandidateCubemapFaces       (const tcu::Vec3&                               r);
+deInt32        wrapTexelCoord                          (const deInt32                                  coord,
+                                                                                const int                                              size,
+                                                                                const vk::VkSamplerAddressMode wrap);
+void           wrapCubemapEdge                         (const tcu::IVec2&                              coord,
+                                                                                const tcu::IVec2&                              size,
+                                                                                const int                                              faceNdx,
+                                                                                tcu::IVec2&                                    newCoord,
+                                                                                int&                                                   newFaceNdx);
+void           wrapCubemapCorner                       (const tcu::IVec2&                              coord,
+                                                                                const tcu::IVec2&                              size,
+                                                                                const int                                              faceNdx,
+                                                                                int&                                                   adjacentFace1,
+                                                                                int&                                                   adjacentFace2,
+                                                                                tcu::IVec2&                                    cornerCoord0,
+                                                                                tcu::IVec2&                                    cornerCoord1,
+                                                                                tcu::IVec2&                                    cornerCoord2);
+
+void           convertFormat                           (const void*                                    pixelPtr,
+                                                                                tcu::TextureFormat                             texFormat,
+                                                                                tcu::FloatFormat                               internalFormat,
+                                                                                tcu::Vec4&                                             resultMin,
+                                                                                tcu::Vec4&                                             resultMax);
+
+template <int Size>
+bool isEqualRelEpsilon (const tcu::Vector<float, Size>& a, const tcu::Vector<float, Size>& b, const float epsilon)
+{
+       for (int compNdx = 0; compNdx < Size; ++compNdx)
+       {
+               if (!isEqualRelEpsilon(a[compNdx], b[compNdx], epsilon))
+               {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+template <int Size>
+bool isInRange (const tcu::Vector<float, Size>& v, const tcu::Vector<float, Size>& min, const tcu::Vector<float, Size>& max)
+{
+       for (int compNdx = 0; compNdx < Size; ++compNdx)
+       {
+               if (v[compNdx] < min[compNdx] || v[compNdx] > max[compNdx])
+               {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+template <int Size>
+tcu::Vector<float, Size> floor (const tcu::Vector<float, Size>& v)
+{
+       tcu::Vector<float, Size> result;
+
+       for (int compNdx = 0; compNdx < Size; ++compNdx)
+       {
+               result[compNdx] = (float)deFloor(v[compNdx]);
+       }
+
+       return result;
+}
+
+template <int Size>
+tcu::Vector<float, Size> ceil (const tcu::Vector<float, Size>& v)
+{
+       tcu::Vector<float, Size> result;
+
+       for (int compNdx = 0; compNdx < Size; ++compNdx)
+       {
+               result[compNdx] = (float)deCeil(v[compNdx]);
+       }
+
+       return result;
+}
+
+template <int Size>
+tcu::Vector<float, Size> abs (const tcu::Vector<float, Size>& v)
+{
+       tcu::Vector<float, Size> result;
+
+       for (int compNdx = 0; compNdx < Size; ++compNdx)
+       {
+               result[compNdx] = de::abs(v[compNdx]);
+       }
+
+       return result;
+}
+
+} // util
+} // texture_filtering
+} // vkt
+
+#endif // _VKTSAMPLEVERIFIERUTIL_HPP
index ec93f90..3711c99 100644 (file)
@@ -44,6 +44,7 @@
 
 #include "deClock.h"
 #include "deMath.h"
+#include "deStringUtil.hpp"
 #include "deUniquePtr.hpp"
 
 #include <sstream>
@@ -74,15 +75,19 @@ string genSamplerDeclaration(const ImageViewParameters& imParams,
                case IMG_DIM_1D:
                        result += "1D";
                        break;
+
                case IMG_DIM_2D:
                        result += "2D";
                        break;
+
                case IMG_DIM_3D:
                        result += "3D";
                        break;
+
                case IMG_DIM_CUBE:
                        result += "Cube";
                        break;
+
                default:
                        break;
        }
@@ -104,22 +109,26 @@ string genLookupCode(const ImageViewParameters&           imParams,
                                         const SamplerParameters&               samplerParams,
                                         const SampleLookupSettings&    lookupSettings)
 {
-       int dim;
+       int dim = -1;
 
        switch (imParams.dim)
        {
                case IMG_DIM_1D:
                        dim = 1;
                        break;
+
                case IMG_DIM_2D:
                        dim = 2;
                        break;
+
                case IMG_DIM_3D:
                        dim = 3;
                        break;
+
                case IMG_DIM_CUBE:
                        dim = 3;
                        break;
+
                default:
                        dim = 0;
                        break;
@@ -212,7 +221,12 @@ string genLookupCode(const ImageViewParameters&            imParams,
 
        if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
        {
-               code += ", dPdx, dPdy";
+               code += ", vec";
+               code += (char) (numCoordComp + '0');
+               code += "(dPdx), ";
+               code += "vec";
+               code += (char) (numCoordComp + '0');
+               code += "(dPdy)";
        }
        else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
        {
@@ -300,9 +314,9 @@ void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba
                const VkImageSubresourceLayers curSubresource =
                {
                        VK_IMAGE_ASPECT_COLOR_BIT,
-                       (deUint32) level,
+                       (deUint32)level,
                        0,
-                       (deUint32) imParams.arrayLayers
+                       (deUint32)imParams.arrayLayers
                };
 
                const VkBufferImageCopy curRegion =
@@ -312,7 +326,7 @@ void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba
                        0,
                        curSubresource,
                        {0U, 0U, 0U},
-                       {(deUint32) curLevelSize[0], (deUint32) curLevelSize[1], (deUint32) curLevelSize[2]}
+                       {(deUint32)curLevelSize[0], (deUint32)curLevelSize[1], (deUint32)curLevelSize[2]}
                };
 
                copyRegions.push_back(curRegion);
@@ -334,9 +348,9 @@ void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba
        {
                VK_IMAGE_ASPECT_COLOR_BIT,
                0,
-               imParams.levels,
+               (deUint32)imParams.levels,
                0,
-               imParams.arrayLayers
+               (deUint32)imParams.arrayLayers
        };
 
        VkImageMemoryBarrier imMemBar =
@@ -381,7 +395,7 @@ void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba
                                                         buf.get(),
                                                         im,
                                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                                        (deUint32) copyRegions.size(),
+                                                        (deUint32)copyRegions.size(),
                                                         &copyRegions[0]);
 
        imMemBar.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
@@ -425,8 +439,6 @@ struct TestCaseData
        ImageViewParameters                                     imParams;
        SamplerParameters                                       samplerParams;
        SampleLookupSettings                            sampleLookupSettings;
-       const SampleArguments*                          sampleArguments;
-       deUint32                                                        numSamples;
        glu::ShaderType                                         shaderType;
 };
 
@@ -473,13 +485,16 @@ VkImageType mapImageType (ImgDim dim)
                case IMG_DIM_1D:
                        imType = VK_IMAGE_TYPE_1D;
                        break;
+
                case IMG_DIM_2D:
                case IMG_DIM_CUBE:
                        imType = VK_IMAGE_TYPE_2D;
                        break;
+
                case IMG_DIM_3D:
                        imType = VK_IMAGE_TYPE_3D;
                        break;
+
                default:
                        imType = VK_IMAGE_TYPE_LAST;
                        break;
@@ -499,12 +514,15 @@ VkImageViewType mapImageViewType (const ImageViewParameters& imParams)
                        case IMG_DIM_1D:
                                imViewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
                                break;
+
                        case IMG_DIM_2D:
                                imViewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
                                break;
+
                        case IMG_DIM_CUBE:
                                imViewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
                                break;
+
                        default:
                                imViewType = VK_IMAGE_VIEW_TYPE_LAST;
                                break;
@@ -517,15 +535,19 @@ VkImageViewType mapImageViewType (const ImageViewParameters& imParams)
                        case IMG_DIM_1D:
                                imViewType = VK_IMAGE_VIEW_TYPE_1D;
                                break;
+
                        case IMG_DIM_2D:
                                imViewType = VK_IMAGE_VIEW_TYPE_2D;
                                break;
+
                        case IMG_DIM_3D:
                                imViewType = VK_IMAGE_VIEW_TYPE_3D;
                                break;
+
                        case IMG_DIM_CUBE:
                                imViewType = VK_IMAGE_VIEW_TYPE_CUBE;
                                break;
+
                        default:
                                imViewType = VK_IMAGE_VIEW_TYPE_LAST;
                                break;
@@ -640,7 +662,7 @@ TestStatus TextureFilteringTestInstance::runTest (void)
        m_pba =   m_gen->getPba();
 
        m_sampleArguments = m_gen->getSampleArgs();
-       m_numSamples = (deUint32) m_sampleArguments.size();
+       m_numSamples = (deUint32)m_sampleArguments.size();
 
        createResources();
        initializeImage(m_ctx, m_im.get(), &m_pba[0], m_imParams);
@@ -694,37 +716,39 @@ bool TextureFilteringTestInstance::verify (void)
                                                        m_mipmapBits,
                                                        m_pba);
 
+       const int maxPrintedFailures = 5;
+       int failCount = 0;
+
        for (deUint32 sampleNdx = 0; sampleNdx < m_numSamples; ++sampleNdx)
        {
                if (!verifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx]))
                {
-                       // Re-run with report logging
-                       std::string report;
-                       verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report);
-
-                       m_ctx.getTestContext().getLog()
-                               << TestLog::Message
-                               << "Failed verification at sample " << sampleNdx << ".\n"
-                               << "\tCoordinate: " << m_sampleArguments[sampleNdx].coord << "\n"
-                               << "\tLOD: " << m_sampleArguments[sampleNdx].lod << "\n"
-                               << "\tGPU Result: " << m_resultSamples[sampleNdx] << "\n"
-                               << TestLog::EndMessage;
-
-                       for (int levelNdx = 0; levelNdx < m_imParams.levels; ++levelNdx)
+                       if (failCount++ < maxPrintedFailures)
                        {
-                               LogImage("", "", m_pba[levelNdx]).write(m_ctx.getTestContext().getLog());
+                               // Re-run with report logging
+                               std::string report;
+                               verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report);
+
+                               m_ctx.getTestContext().getLog()
+                                       << TestLog::Section("Failed sample", "Failed sample")
+                                       << TestLog::Message
+                                       << "Sample " << sampleNdx << ".\n"
+                                       << "\tCoordinate: " << m_sampleArguments[sampleNdx].coord << "\n"
+                                       << "\tLOD: " << m_sampleArguments[sampleNdx].lod << "\n"
+                                       << "\tGPU Result: " << m_resultSamples[sampleNdx] << "\n\n"
+                                       << "Failure report:\n" << report << "\n"
+                                       << TestLog::EndMessage
+                                       << TestLog::EndSection;
                        }
-
-                   m_ctx.getTestContext().getLog()
-                               << TestLog::Message
-                               << "Failure report:\n" << report << "\n"
-                               << TestLog::EndMessage;
-
-                       return false;
                }
        }
 
-       return true;
+       m_ctx.getTestContext().getLog()
+               << TestLog::Message
+               << "Passed " << m_numSamples - failCount << " out of " << m_numSamples << "."
+               << TestLog::EndMessage;
+
+       return failCount == 0;
 }
 
 void TextureFilteringTestInstance::execute (void)
@@ -803,8 +827,8 @@ void TextureFilteringTestInstance::createResources (void)
            mapImageType(m_imParams.dim),                                                                       // imageType
            m_imParams.format,                                                                                          // format
                m_imExtent,                                                                                                             // extent
-           m_imParams.levels,                                                                                          // mipLevels
-           m_imParams.arrayLayers,                                                                                     // arrayLayers
+           (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
@@ -829,11 +853,11 @@ void TextureFilteringTestInstance::createResources (void)
        // \todo [2016-06-23 collinbaker] Pick aspectMask based on image type (i.e. support depth and/or stencil images)
        VkImageSubresourceRange imViewSubresourceRange =
        {
-               VK_IMAGE_ASPECT_COLOR_BIT,      // aspectMask
-               0,                                                      // baseMipLevel
-               m_imParams.levels,                      // levelCount
-               0,                                                      // baseArrayLayer
-               m_imParams.arrayLayers          // layerCount
+               VK_IMAGE_ASPECT_COLOR_BIT,                      // aspectMask
+               0,                                                                      // baseMipLevel
+               (deUint32)m_imParams.levels,            // levelCount
+               0,                                                                      // baseArrayLayer
+               (deUint32)m_imParams.arrayLayers        // layerCount
        };
 
        if (m_imParams.dim == IMG_DIM_CUBE)
@@ -972,7 +996,8 @@ public:
                                                           VkFilter magFilter,
                                                           VkFilter minFilter,
                                                           VkSamplerMipmapMode mipmapFilter,
-                                                          VkSamplerAddressMode wrappingMode)
+                                                          VkSamplerAddressMode wrappingMode,
+                                                          bool useDerivatives)
 
                : TextureFilteringTestCase      (testCtx, name, desc)
                , m_format                                      (format)
@@ -981,6 +1006,7 @@ public:
                , m_minFilter                           (minFilter)
                , m_mipmapFilter                        (mipmapFilter)
                , m_wrappingMode                        (wrappingMode)
+               , m_useDerivatives                      (useDerivatives)
        {
                m_testCaseData = genTestCaseData();
                init();
@@ -997,7 +1023,7 @@ protected:
 
                SampleLookupSettings sampleLookupSettings =
                {
-                       LOOKUP_LOD_MODE_LOD, // lookupLodMode
+                   m_useDerivatives ? LOOKUP_LOD_MODE_DERIVATIVES : LOOKUP_LOD_MODE_LOD, // lookupLodMode
                        false, // hasLodBias
                        false, // isProjective
                };
@@ -1037,8 +1063,6 @@ protected:
                        imParameters,
                        samplerParameters,
                        sampleLookupSettings,
-                       &m_args[0],
-                       (deUint32) m_args.size(),
                        glu::SHADERTYPE_FRAGMENT
                };
 
@@ -1052,8 +1076,7 @@ private:
        VkFilter                                                m_minFilter;
        VkSamplerMipmapMode                             m_mipmapFilter;
        VkSamplerAddressMode                    m_wrappingMode;
-
-       std::vector<SampleArguments>    m_args;
+       bool                                                    m_useDerivatives;
 };
 
 class Texture2DGradientTestCase::Generator : public DataGenerator
@@ -1110,21 +1133,58 @@ public:
        {
                std::vector<SampleArguments> args;
 
-               const float lodList[] = {-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0};
-
-               for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
+               if (m_testCase->m_useDerivatives)
+               {
+                       struct
+                       {
+                               Vec4 dPdx;
+                               Vec4 dPdy;
+                       }
+                       derivativePairs[] =
+                       {
+                               {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
+                               {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
+                               {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
+                               {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
+                               {Vec4(2.0f, 2.0f, 2.0f, 0.0f), Vec4(2.0f, 2.0f, 2.0f, 0.0f)}
+                       };
+
+                       for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
+                       {
+                               for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
+                               {
+                                   for (deUint32 derivNdx = 0; derivNdx < DE_LENGTH_OF_ARRAY(derivativePairs); ++derivNdx)
+                                       {
+                                               SampleArguments cur;
+                                               cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
+                                                                                (float)j / (float)(2 * m_testCase->m_dimensions[1]),
+                                                                                0.0f, 0.0f);
+                                               cur.dPdx = derivativePairs[derivNdx].dPdx;
+                                               cur.dPdy = derivativePairs[derivNdx].dPdy;
+
+                                               args.push_back(cur);
+                                       }
+                               }
+                       }
+               }
+               else
                {
-                       for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
+                       const float lodList[] = {-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0};
+
+                       for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
                        {
-                               for (deUint32 lodNdx = 0; lodNdx < DE_LENGTH_OF_ARRAY(lodList); ++lodNdx)
+                               for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
                                {
-                                       SampleArguments cur;
-                                       cur.coord = Vec4((float) i / (float) (2 * m_testCase->m_dimensions[0]),
-                                                                        (float) j / (float) (2 * m_testCase->m_dimensions[1]),
-                                                                        0.0f, 0.0f);
-                                       cur.lod = lodList[lodNdx];
+                                       for (deUint32 lodNdx = 0; lodNdx < DE_LENGTH_OF_ARRAY(lodList); ++lodNdx)
+                                       {
+                                               SampleArguments cur;
+                                               cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
+                                                                                (float)j / (float)(2 * m_testCase->m_dimensions[1]),
+                                                                                0.0f, 0.0f);
+                                               cur.lod = lodList[lodNdx];
 
-                                       args.push_back(cur);
+                                               args.push_back(cur);
+                                       }
                                }
                        }
                }
@@ -1158,25 +1218,28 @@ TestCaseGroup* create2DFormatTests (TestContext& testCtx)
                VK_FORMAT_R8G8_SNORM,
                VK_FORMAT_R8G8B8A8_UNORM,
                VK_FORMAT_R8G8B8A8_SNORM,
-               VK_FORMAT_R8G8B8A8_SRGB,
+//             VK_FORMAT_R8G8B8A8_SRGB,
                VK_FORMAT_B8G8R8A8_UNORM,
-               VK_FORMAT_B8G8R8A8_SRGB,
+//             VK_FORMAT_B8G8R8A8_SRGB,
                VK_FORMAT_A8B8G8R8_UNORM_PACK32,
                VK_FORMAT_A8B8G8R8_SNORM_PACK32,
-               VK_FORMAT_A8B8G8R8_SRGB_PACK32,
+//             VK_FORMAT_A8B8G8R8_SRGB_PACK32,
                VK_FORMAT_A2B10G10R10_UNORM_PACK32,
                VK_FORMAT_R16_SFLOAT,
                VK_FORMAT_R16G16_SFLOAT,
                VK_FORMAT_R16G16B16A16_SFLOAT,
-               VK_FORMAT_B10G11R11_UFLOAT_PACK32,
-               VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
+               VK_FORMAT_R32_SFLOAT,
+               VK_FORMAT_R32G32_SFLOAT,
+               VK_FORMAT_R32G32B32A32_SFLOAT,
+//             VK_FORMAT_B10G11R11_UFLOAT_PACK32,
+//             VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
        };
 
        const IVec3 size(32, 32, 1);
 
        for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
        {
-               std::string prefix = getFormatName(formats[formatNdx]);
+               std::string prefix = de::toLower(std::string(getFormatName(formats[formatNdx])).substr(10));
 
                Texture2DGradientTestCase* testCaseNearest =
                        new Texture2DGradientTestCase(
@@ -1188,7 +1251,8 @@ TestCaseGroup* create2DFormatTests (TestContext& testCtx)
                                VK_FILTER_NEAREST,
                                VK_FILTER_NEAREST,
                                VK_SAMPLER_MIPMAP_MODE_NEAREST,
-                               VK_SAMPLER_ADDRESS_MODE_REPEAT);
+                               VK_SAMPLER_ADDRESS_MODE_REPEAT,
+                               false);
 
                tests->addChild(testCaseNearest);
 
@@ -1202,7 +1266,8 @@ TestCaseGroup* create2DFormatTests (TestContext& testCtx)
                                VK_FILTER_LINEAR,
                                VK_FILTER_LINEAR,
                                VK_SAMPLER_MIPMAP_MODE_LINEAR,
-                               VK_SAMPLER_ADDRESS_MODE_REPEAT);
+                               VK_SAMPLER_ADDRESS_MODE_REPEAT,
+                               false);
 
                tests->addChild(testCaseLinear);
        }
@@ -1210,6 +1275,100 @@ TestCaseGroup* create2DFormatTests (TestContext& testCtx)
        return tests.release();
 }
 
+TestCaseGroup* create2DDerivTests (TestContext& testCtx)
+{
+       de::MovePtr<TestCaseGroup> tests(
+               new TestCaseGroup(testCtx, "derivatives", "Explicit derivative tests"));
+
+       const VkFormat                          format           = VK_FORMAT_R8G8B8A8_UNORM;
+       const VkSamplerAddressMode      wrappingMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+       const IVec3                                     size             = IVec3(16, 16, 1);
+
+       const VkFilter filters[2] =
+       {
+               VK_FILTER_NEAREST,
+               VK_FILTER_LINEAR
+       };
+
+       const VkSamplerMipmapMode mipmapFilters[2] =
+       {
+               VK_SAMPLER_MIPMAP_MODE_NEAREST,
+               VK_SAMPLER_MIPMAP_MODE_LINEAR,
+       };
+
+       for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++magFilterNdx)
+       {
+               for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++minFilterNdx)
+               {
+                       for (int mipmapFilterNdx = 0; mipmapFilterNdx < DE_LENGTH_OF_ARRAY(mipmapFilters); ++mipmapFilterNdx)
+                       {
+                               std::ostringstream caseName;
+
+                               switch (filters[magFilterNdx])
+                               {
+                                       case VK_FILTER_NEAREST:
+                                               caseName << "nearest";
+                                               break;
+
+                                       case VK_FILTER_LINEAR:
+                                               caseName << "linear";
+                                               break;
+
+                                       default:
+                                               break;
+                               }
+
+                               switch (filters[minFilterNdx])
+                               {
+                                       case VK_FILTER_NEAREST:
+                                               caseName << "_nearest";
+                                               break;
+
+                                       case VK_FILTER_LINEAR:
+                                               caseName << "_linear";
+                                               break;
+
+                                       default:
+                                               break;
+                               }
+
+                               caseName << "_mipmap";
+
+                               switch (mipmapFilters[mipmapFilterNdx])
+                               {
+                                       case VK_SAMPLER_MIPMAP_MODE_NEAREST:
+                                               caseName << "_nearest";
+                                               break;
+
+                                       case VK_SAMPLER_MIPMAP_MODE_LINEAR:
+                                               caseName << "_linear";
+                                               break;
+
+                                       default:
+                                               break;
+                               }
+
+                               Texture2DGradientTestCase* testCase =
+                                       new Texture2DGradientTestCase(
+                                               testCtx,
+                                               caseName.str().c_str(),
+                                               "...",
+                                               mapVkFormat(format),
+                                               size,
+                                               filters[magFilterNdx],
+                                               filters[minFilterNdx],
+                                               mipmapFilters[mipmapFilterNdx],
+                                               wrappingMode,
+                                               true);
+
+                               tests->addChild(testCase);
+                       }
+               }
+       }
+
+       return tests.release();
+}
+
 TestCaseGroup* create2DSizeTests (TestContext& testCtx)
 {
        de::MovePtr<TestCaseGroup> tests(
@@ -1266,9 +1425,11 @@ TestCaseGroup* create2DSizeTests (TestContext& testCtx)
                                                        case VK_FILTER_NEAREST:
                                                                caseName << "_nearest";
                                                                break;
+
                                                        case VK_FILTER_LINEAR:
                                                                caseName << "_linear";
                                                                break;
+
                                                        default:
                                                                break;
                                                }
@@ -1278,9 +1439,11 @@ TestCaseGroup* create2DSizeTests (TestContext& testCtx)
                                                        case VK_FILTER_NEAREST:
                                                                caseName << "_nearest";
                                                                break;
+
                                                        case VK_FILTER_LINEAR:
                                                                caseName << "_linear";
                                                                break;
+
                                                        default:
                                                                break;
                                                }
@@ -1290,9 +1453,11 @@ TestCaseGroup* create2DSizeTests (TestContext& testCtx)
                                                        case VK_SAMPLER_MIPMAP_MODE_NEAREST:
                                                                caseName << "_mipmap_nearest";
                                                                break;
+
                                                        case VK_SAMPLER_MIPMAP_MODE_LINEAR:
                                                                caseName << "_mipmap_linear";
                                                                break;
+
                                                        default:
                                                                break;
                                                }
@@ -1302,9 +1467,11 @@ TestCaseGroup* create2DSizeTests (TestContext& testCtx)
                                                        case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
                                                                caseName << "_clamp";
                                                                break;
+
                                                        case VK_SAMPLER_ADDRESS_MODE_REPEAT:
                                                                caseName << "_repeat";
                                                                break;
+
                                                        default:
                                                                break;
                                                }
@@ -1319,7 +1486,8 @@ TestCaseGroup* create2DSizeTests (TestContext& testCtx)
                                                                filters[magFilterNdx],
                                                                filters[minFilterNdx],
                                                                mipmapFilters[mipmapFilterNdx],
-                                                               wrappingModes[wrappingModeNdx]);
+                                                               wrappingModes[wrappingModeNdx],
+                                                               false);
 
                                                tests->addChild(testCase);
                                        }
@@ -1338,6 +1506,7 @@ TestCaseGroup* create2DTests (TestContext& testCtx)
 
        tests->addChild(create2DSizeTests(testCtx));
        tests->addChild(create2DFormatTests(testCtx));
+       tests->addChild(create2DDerivTests(testCtx));
 
        return tests.release();
 }
index 75c7d65..cc271a1 100644 (file)
@@ -70,6 +70,9 @@ public:
                                        , m_lo          (m_hasNaN ? TCU_INFINITY : val)
                                        , m_hi          (m_hasNaN ? -TCU_INFINITY : val) {}
 
+                               Interval                (bool hasNaN_, double lo_, double hi_)
+                                       : m_hasNaN(hasNaN_), m_lo(lo_), m_hi(hi_) {}
+
                                Interval                (const Interval& a, const Interval& b)
                                        : m_hasNaN      (a.m_hasNaN || b.m_hasNaN)
                                        , m_lo          (de::min(a.lo(), b.lo()))
@@ -145,8 +148,6 @@ public:
        }
 
 private:
-                               Interval                (bool hasNaN_, double lo_, double hi_)
-                                       : m_hasNaN(hasNaN_), m_lo(lo_), m_hi(hi_) {}
        bool            m_hasNaN;
        double          m_lo;
        double          m_hi;
index ed0709e..1d76fb9 100644 (file)
@@ -257,36 +257,6 @@ inline deUint32 convertSatRteUint24 (float f)
        return de::min(rounded, maxUint24);
 }
 
-int getChannelSize (TextureFormat::ChannelType type)
-{
-       // make sure this table is updated if format table is updated
-       DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
-
-       switch (type)
-       {
-               case TextureFormat::SNORM_INT8:                 return 1;
-               case TextureFormat::SNORM_INT16:                return 2;
-               case TextureFormat::SNORM_INT32:                return 4;
-               case TextureFormat::UNORM_INT8:                 return 1;
-               case TextureFormat::UNORM_INT16:                return 2;
-               case TextureFormat::UNORM_INT24:                return 3;
-               case TextureFormat::UNORM_INT32:                return 4;
-               case TextureFormat::SIGNED_INT8:                return 1;
-               case TextureFormat::SIGNED_INT16:               return 2;
-               case TextureFormat::SIGNED_INT32:               return 4;
-               case TextureFormat::UNSIGNED_INT8:              return 1;
-               case TextureFormat::UNSIGNED_INT16:             return 2;
-               case TextureFormat::UNSIGNED_INT24:             return 3;
-               case TextureFormat::UNSIGNED_INT32:             return 4;
-               case TextureFormat::HALF_FLOAT:                 return 2;
-               case TextureFormat::FLOAT:                              return 4;
-               case TextureFormat::FLOAT64:                    return 8;
-               default:
-                       DE_ASSERT(DE_FALSE);
-                       return 0;
-       }
-}
-
 inline float channelToFloat (const deUint8* value, TextureFormat::ChannelType type)
 {
        // make sure this table is updated if format table is updated
@@ -656,6 +626,36 @@ int getNumUsedChannels (TextureFormat::ChannelOrder order)
        }
 }
 
+int getChannelSize (TextureFormat::ChannelType type)
+{
+       // make sure this table is updated if format table is updated
+       DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
+
+       switch (type)
+       {
+               case TextureFormat::SNORM_INT8:                 return 1;
+               case TextureFormat::SNORM_INT16:                return 2;
+               case TextureFormat::SNORM_INT32:                return 4;
+               case TextureFormat::UNORM_INT8:                 return 1;
+               case TextureFormat::UNORM_INT16:                return 2;
+               case TextureFormat::UNORM_INT24:                return 3;
+               case TextureFormat::UNORM_INT32:                return 4;
+               case TextureFormat::SIGNED_INT8:                return 1;
+               case TextureFormat::SIGNED_INT16:               return 2;
+               case TextureFormat::SIGNED_INT32:               return 4;
+               case TextureFormat::UNSIGNED_INT8:              return 1;
+               case TextureFormat::UNSIGNED_INT16:             return 2;
+               case TextureFormat::UNSIGNED_INT24:             return 3;
+               case TextureFormat::UNSIGNED_INT32:             return 4;
+               case TextureFormat::HALF_FLOAT:                 return 2;
+               case TextureFormat::FLOAT:                              return 4;
+               case TextureFormat::FLOAT64:                    return 8;
+               default:
+                       DE_ASSERT(DE_FALSE);
+                       return 0;
+       }
+}
+
 /** Get pixel size in bytes. */
 int getPixelSize (TextureFormat format)
 {
index f401cf6..e73f274 100644 (file)
@@ -140,6 +140,7 @@ public:
 bool   isValid                         (TextureFormat format);
 int            getPixelSize            (TextureFormat format);
 int            getNumUsedChannels      (TextureFormat::ChannelOrder order);
+int            getChannelSize          (TextureFormat::ChannelType type);
 
 /*--------------------------------------------------------------------*//*!
  * \brief Texture swizzle