This is a framework for testing image sampling with explicit LOD in vulkan.
Change-Id: I36ea968d9e4624a76b9a918f5ab7e3d5a9039a55
external/vulkancts/modules/vulkan/shaderexecutor/vktShaderExecutor.cpp \
external/vulkancts/modules/vulkan/shaderexecutor/vktShaderIntegerFunctionTests.cpp \
external/vulkancts/modules/vulkan/shaderexecutor/vktShaderPackingFunctionTests.cpp \
- external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderBuiltinVarTests.cpp \
external/vulkancts/modules/vulkan/shaderrender/vktShaderRender.cpp \
+ external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderBuiltinVarTests.cpp \
external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderDerivateTests.cpp \
external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderDiscardTests.cpp \
external/vulkancts/modules/vulkan/shaderrender/vktShaderRenderIndexingTests.cpp \
external/vulkancts/modules/vulkan/tessellation/vktTessellationUserDefinedIO.cpp \
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/vktTextureFilteringTests.cpp \
+ external/vulkancts/modules/vulkan/texture_filtering/vktTextureFilteringExplicitLodTests.cpp \
external/vulkancts/modules/vulkan/ubo/vktRandomUniformBlockCase.cpp \
external/vulkancts/modules/vulkan/ubo/vktUniformBlockCase.cpp \
external/vulkancts/modules/vulkan/ubo/vktUniformBlockTests.cpp \
$(deqp_dir)/external/vulkancts/modules/vulkan/ssbo \
$(deqp_dir)/external/vulkancts/modules/vulkan/synchronization \
$(deqp_dir)/external/vulkancts/modules/vulkan/tessellation \
+ $(deqp_dir)/external/vulkancts/modules/vulkan/texture_filtering \
$(deqp_dir)/external/vulkancts/modules/vulkan/ubo \
$(deqp_dir)/external/vulkancts/modules/vulkan/wsi
</TestSuite>
</TestSuite>
</TestSuite>
+ <TestSuite name="texture_filtering">
+ <TestSuite name="explicit_lod">
+ <TestSuite name="2d">
+ <TestCase name="sizes">
+ <Test name="2x2_nearest_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_nearest_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_nearest_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_nearest_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_nearest_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_nearest_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_nearest_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_nearest_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_linear_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_linear_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_linear_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_linear_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_linear_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_linear_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_linear_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x2_linear_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_nearest_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_nearest_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_nearest_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_nearest_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_nearest_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_nearest_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_nearest_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_nearest_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_linear_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_linear_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_linear_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_linear_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_linear_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_linear_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_linear_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="2x3_linear_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_nearest_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_nearest_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_nearest_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_nearest_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_nearest_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_nearest_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_nearest_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_nearest_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_linear_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_linear_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_linear_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_linear_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_linear_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_linear_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_linear_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="3x7_linear_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_nearest_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_nearest_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_nearest_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_nearest_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_nearest_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_nearest_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_nearest_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_nearest_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_linear_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_linear_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_linear_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_linear_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_linear_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_linear_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_linear_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="4x8_linear_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_nearest_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_nearest_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_nearest_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_nearest_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_nearest_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_nearest_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_nearest_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_nearest_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_linear_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_linear_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_linear_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_linear_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_linear_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_linear_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_linear_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="31x55_linear_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_nearest_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_nearest_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_nearest_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_nearest_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_nearest_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_nearest_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_nearest_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_nearest_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_linear_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_linear_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_linear_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_linear_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_linear_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_linear_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_linear_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x32_linear_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_nearest_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_nearest_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_nearest_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_nearest_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_nearest_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_nearest_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_nearest_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_nearest_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_linear_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_linear_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_linear_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_linear_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_linear_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_linear_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_linear_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="32x64_linear_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_nearest_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_nearest_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_nearest_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_nearest_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_nearest_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_nearest_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_nearest_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_nearest_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_linear_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_linear_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_linear_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_linear_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_linear_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_linear_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_linear_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="57x35_linear_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_nearest_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_nearest_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_nearest_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_nearest_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_nearest_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_nearest_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_nearest_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_nearest_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_linear_nearest_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_linear_nearest_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_linear_nearest_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_linear_nearest_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_linear_linear_mipmap_nearest_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_linear_linear_mipmap_nearest_clamp">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_linear_linear_mipmap_linear_repeat">
+ <TestInstance/>
+ </Test>
+ <Test name="128x128_linear_linear_mipmap_linear_clamp">
+ <TestInstance/>
+ </Test>
+ </TestCase>
+ <TestCase name="formats">
+ <Test name="VK_FORMAT_B4G4R4A4_UNORM_PACK16_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_B4G4R4A4_UNORM_PACK16_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R5G6B5_UNORM_PACK16_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R5G6B5_UNORM_PACK16_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A1R5G5B5_UNORM_PACK16_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A1R5G5B5_UNORM_PACK16_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8_UNORM_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8_UNORM_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8_SNORM_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8_SNORM_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8_UNORM_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8_UNORM_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8_SNORM_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8_SNORM_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8B8A8_UNORM_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8B8A8_UNORM_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8B8A8_SNORM_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8B8A8_SNORM_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8B8A8_SRGB_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R8G8B8A8_SRGB_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_B8G8R8A8_UNORM_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_B8G8R8A8_UNORM_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_B8G8R8A8_SRGB_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_B8G8R8A8_SRGB_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A8B8G8R8_UNORM_PACK32_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A8B8G8R8_UNORM_PACK32_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A8B8G8R8_SNORM_PACK32_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A8B8G8R8_SNORM_PACK32_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A8B8G8R8_SRGB_PACK32_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A8B8G8R8_SRGB_PACK32_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A2B10G10R10_UNORM_PACK32_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_A2B10G10R10_UNORM_PACK32_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R16_SFLOAT_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R16_SFLOAT_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R16G16_SFLOAT_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R16G16_SFLOAT_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R16G16B16A16_SFLOAT_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_R16G16B16A16_SFLOAT_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_B10G11R11_UFLOAT_PACK32_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_B10G11R11_UFLOAT_PACK32_linear">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_E5B9G9R9_UFLOAT_PACK32_nearest">
+ <TestInstance/>
+ </Test>
+ <Test name="VK_FORMAT_E5B9G9R9_UFLOAT_PACK32_linear">
+ <TestInstance/>
+ </Test>
+ </TestCase>
+ </TestSuite>
+ </TestSuite>
+ </TestSuite>
</TestSuite>
</TestPackage>
dEQP-VK.clipping.user_defined.clip_cull_distance_dynamic_index.vert_tess_geom.6_2
dEQP-VK.clipping.user_defined.clip_cull_distance_dynamic_index.vert_tess_geom.7_1
dEQP-VK.clipping.user_defined.clip_cull_distance_dynamic_index.vert_tess_geom.8
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_nearest_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_nearest_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_nearest_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_nearest_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_nearest_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_nearest_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_nearest_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_nearest_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_linear_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_linear_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_linear_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_linear_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_linear_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_linear_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_linear_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x2_linear_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_nearest_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_nearest_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_nearest_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_nearest_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_nearest_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_nearest_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_nearest_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_nearest_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_linear_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_linear_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_linear_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_linear_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_linear_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_linear_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_linear_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.2x3_linear_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_nearest_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_nearest_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_nearest_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_nearest_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_nearest_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_nearest_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_nearest_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_nearest_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_linear_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_linear_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_linear_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_linear_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_linear_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_linear_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_linear_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.3x7_linear_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_nearest_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_nearest_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_nearest_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_nearest_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_nearest_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_nearest_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_nearest_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_nearest_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_linear_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_linear_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_linear_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_linear_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_linear_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_linear_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_linear_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.4x8_linear_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_nearest_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_nearest_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_nearest_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_nearest_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_nearest_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_nearest_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_nearest_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_nearest_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_linear_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_linear_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_linear_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_linear_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_linear_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_linear_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_linear_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.31x55_linear_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_nearest_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_nearest_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_nearest_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_nearest_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_nearest_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_nearest_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_nearest_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_nearest_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_linear_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_linear_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_linear_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_linear_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_linear_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_linear_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_linear_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x32_linear_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_nearest_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_nearest_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_nearest_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_nearest_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_nearest_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_nearest_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_nearest_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_nearest_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_linear_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_linear_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_linear_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_linear_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_linear_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_linear_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_linear_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.32x64_linear_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_nearest_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_nearest_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_nearest_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_nearest_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_nearest_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_nearest_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_nearest_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_nearest_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_linear_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_linear_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_linear_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_linear_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_linear_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_linear_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_linear_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.57x35_linear_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_nearest_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_nearest_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_nearest_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_nearest_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_nearest_linear_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_nearest_linear_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_nearest_linear_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_nearest_linear_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_linear_nearest_mipmap_nearest_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_linear_nearest_mipmap_nearest_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_linear_nearest_mipmap_linear_repeat
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_linear_nearest_mipmap_linear_clamp
+dEQP-VK.texture_filtering.explicit_lod.2d.sizes.128x128_linear_linear_mipmap_nearest_repeat
+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
return tcuFormat.order == tcu::TextureFormat::D || tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS;
}
+bool isSrgbFormat (VkFormat format)
+{
+ switch (mapVkFormat(format).order)
+ {
+ case tcu::TextureFormat::sR:
+ case tcu::TextureFormat::sRG:
+ case tcu::TextureFormat::sRGB:
+ case tcu::TextureFormat::sRGBA:
+ case tcu::TextureFormat::sBGR:
+ case tcu::TextureFormat::sBGRA:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
bool isCompressedFormat (VkFormat format)
{
// update this mapping if VkFormat changes
bool isUintFormat (VkFormat format);
bool isDepthStencilFormat (VkFormat format);
bool isCompressedFormat (VkFormat format);
+bool isSrgbFormat (VkFormat format);
tcu::TextureFormat mapVkFormat (VkFormat format);
tcu::CompressedTexFormat mapVkCompressedFormat (VkFormat format);
add_subdirectory(spirv_assembly)
add_subdirectory(shaderrender)
add_subdirectory(shaderexecutor)
+add_subdirectory(texture_filtering)
add_subdirectory(memory)
add_subdirectory(ubo)
add_subdirectory(dynamic_state)
spirv_assembly
shaderrender
shaderexecutor
+ texture_filtering
memory
ubo
dynamic_state
deqp-vk-spirv-assembly
deqp-vk-shaderrender
deqp-vk-shaderexecutor
+ deqp-vk-texture-filtering
deqp-vk-memory
deqp-vk-ubo
deqp-vk-dynamic-state
descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
if (!m_uniformInfos.empty())
descriptorPool = m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
- else
+ else
{
const VkDescriptorPoolSize poolSizeCount = { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 };
const VkDescriptorPoolCreateInfo createInfo =
m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(samplers)));
}
+void ShaderExecutor::addSamplerUniform (deUint32 bindingLocation,
+ VkImageView imageView,
+ VkSampler sampler)
+{
+ de::MovePtr<UnmanagedSamplerUniform> samplerUniform(new UnmanagedSamplerUniform());
+
+ const VkDescriptorImageInfo descriptor =
+ {
+ sampler,
+ imageView,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+ };
+
+ samplerUniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ samplerUniform->location = bindingLocation;
+ samplerUniform->descriptor = descriptor;
+
+ m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(samplerUniform)));
+
+ m_descriptorSetLayoutBuilder.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_ALL, DE_NULL);
+ m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1);
+}
+
const void* ShaderExecutor::getBufferPtr (const deUint32 bindingLocation) const
{
std::vector<UniformInfoSp>::const_iterator it = m_uniformInfos.begin();
const SamplerUniform* samplerUniform = static_cast<const SamplerUniform*>(uniformInfo);
descriptorSetUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(samplerUniform->location), samplerUniform->type, &samplerUniform->descriptor);
}
+ else if (uniformType == UniformInfo::UNIFORM_TYPE_UNMANAGED_SAMPLER)
+ {
+ const UnmanagedSamplerUniform* samplerUniform = static_cast<const UnmanagedSamplerUniform*>(uniformInfo);
+ descriptorSetUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(samplerUniform->location), samplerUniform->type, &samplerUniform->descriptor);
+ }
}
}
VkImageViewType imageViewType,
const void* data);
+ void addSamplerUniform (deUint32 bindingLocation,
+ VkImageView imageView,
+ VkSampler sampler);
+
const void* getBufferPtr (const deUint32 bindingLocation) const;
protected:
{
UNIFORM_TYPE_BUFFER = 0,
UNIFORM_TYPE_SAMPLER,
+ UNIFORM_TYPE_UNMANAGED_SAMPLER,
UNIFORM_TYPE_BUFFER_ARRAY,
UNIFORM_TYPE_SAMPLER_ARRAY,
VkDescriptorImageInfo descriptor;
};
+ class UnmanagedSamplerUniform : public UniformInfo
+ {
+ public:
+ UnmanagedSamplerUniform (void) {}
+ virtual ~UnmanagedSamplerUniform (void) {}
+ virtual UniformType getType (void) const { return UNIFORM_TYPE_UNMANAGED_SAMPLER; }
+
+ VkImageView imageView;
+ VkSampler sampler;
+ VkDescriptorImageInfo descriptor;
+ };
+
class BufferArrayUniform : public UniformInfo
{
public:
--- /dev/null
+include_directories(.. ../shaderexecutor)
+
+set(DEQP_VK_TEXTURE_FILTERING_SRCS
+ vktTextureFilteringTests.cpp
+ vktTextureFilteringTests.hpp
+ vktSampleVerifier.cpp
+ vktSampleVerifier.hpp
+ vktTextureFilteringExplicitLodTests.cpp
+ vktTextureFilteringExplicitLodTests.hpp
+)
+
+set(DEQP_VK_TEXTURE_FILTERING_LIBS
+ deqp-vk-common
+ deqp-vk-shaderexecutor
+ tcutil
+ vkutil
+)
+
+add_library(deqp-vk-texture-filtering STATIC ${DEQP_VK_TEXTURE_FILTERING_SRCS})
+target_link_libraries(deqp-vk-texture-filtering ${DEQP_VK_TEXTURE_FITLERING_LIBS})
--- /dev/null
+/*-------------------------------------------------------------------------
+ * 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 "tcuFloat.hpp"
+#include "tcuTextureUtil.hpp"
+#include "vkImageUtil.hpp"
+
+#include <fstream>
+#include <sstream>
+
+namespace vkt
+{
+namespace texture_filtering
+{
+
+using namespace vk;
+using namespace tcu;
+
+namespace
+{
+
+bool isEqualRelEpsilon (const float a, const float b, const float epsilon)
+{
+ 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 (!isEqualRelEpsilon(a[compNdx], b[compNdx], epsilon))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+float calcRelEpsilon (VkFormat format, VkFilter filter, VkSamplerMipmapMode mipmapFilter)
+{
+ // 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)
+ {
+ return n;
+ }
+ else
+ {
+ return -(1 + n);
+ }
+}
+
+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] = 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] = 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,
+ const SamplerParameters& samplerParams,
+ const SampleLookupSettings& sampleLookupSettings,
+ int coordBits,
+ int mipmapBits,
+ const std::vector<tcu::ConstPixelBufferAccess>& pba)
+
+ : m_imParams (imParams)
+ , m_samplerParams (samplerParams)
+ , m_sampleLookupSettings (sampleLookupSettings)
+ , m_coordBits (coordBits)
+ , m_mipmapBits (mipmapBits)
+ , m_pba (pba)
+{
+ if (m_imParams.dim == IMG_DIM_1D)
+ {
+ m_unnormalizedDim = 1;
+ }
+ else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
+ {
+ m_unnormalizedDim = 2;
+ }
+ else
+ {
+ m_unnormalizedDim = 3;
+ }
+}
+
+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];
+}
+
+Vec4 SampleVerifier::fetchTexel (const IVec3& coordIn, deUint32 layer, deUint8 level, VkFilter filter) const
+{
+ IVec3 coord = coordIn;
+
+ VkSamplerAddressMode wrappingModes[] =
+ {
+ m_samplerParams.wrappingModeU,
+ m_samplerParams.wrappingModeV,
+ m_samplerParams.wrappingModeW
+ };
+
+ const bool isSrgb = isSrgbFormat(m_imParams.format);
+
+ // 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};
+
+ static const deUint8 edgeFactors[4][2] =
+ {
+ {0, 0},
+ {1, 0},
+ {0, 1},
+ {0, 0}
+ };
+
+ 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;
+ }
+
+ 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;
+
+ 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;
+ }
+ 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;
+ }
+
+ // Calculate faces and corners thereof adjacent to sampled corner
+
+ const deUint8 cornerEdges[2] = {cornerNdx, (deUint8) ((cornerNdx + 3) % 4)};
+
+ const deUint8 faces[3] = {arrayFace,
+ adjacentFaces[arrayFace][cornerEdges[0]],
+ adjacentFaces[arrayFace][cornerEdges[1]]};
+
+ deUint8 faceCorners[3] = {cornerNdx, 0, 0};
+
+ for (deUint8 edgeNdx = 0; edgeNdx < 2; ++edgeNdx)
+ {
+ const deUint8 faceEdge = adjacentEdges[arrayFace][cornerEdges[edgeNdx]];
+
+ bool isFlipped = (adjacentEdgeDirs[arrayFace][cornerEdges[edgeNdx]]);
+
+ if ((cornerEdges[edgeNdx] > 1) != (faceEdge > 1))
+ {
+ isFlipped = !isFlipped;
+ }
+
+ if (isFlipped)
+ {
+ faceCorners[edgeNdx + 1] = (deUint8) ((faceEdge + 1) % 4);
+ }
+ else
+ {
+ faceCorners[edgeNdx + 1] = faceEdge;
+ }
+ }
+
+ // Compute average of corners and return
+
+ Vec4 result(0.0f);
+
+ for (deUint8 faceNdx = 0; faceNdx < 3; ++faceNdx)
+ {
+ 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);
+ }
+
+ const IVec2 cornerCoord = cornerFactor * (m_pba[level].getSize().swizzle(0, 1) - IVec2(1));
+ const deUint32 cornerLayer = arrayLayer * 6 + faces[faceNdx];
+
+ if (isSrgb)
+ {
+ result += sRGBToLinear(m_pba[level].getPixel(cornerCoord[0], cornerCoord[1], cornerLayer));
+ }
+ else
+ {
+ result += m_pba[level].getPixel(cornerCoord[0], cornerCoord[1], cornerLayer);
+ }
+ }
+
+ result = result / 3.0f;
+
+ return result;
+ }
+ }
+ else
+ {
+ 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)
+ {
+ const deUint32 size = m_pba[level].getSize()[compNdx];
+
+ coord[compNdx] = wrapTexelCoord(coord[compNdx], size, wrappingModes[compNdx]);
+ }
+ }
+
+ if (coordOutOfRange(coord, 0, level) ||
+ coordOutOfRange(coord, 1, level) ||
+ coordOutOfRange(coord, 2, level))
+ {
+ switch (m_samplerParams.borderColor)
+ {
+ case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
+ return Vec4(0.0f, 0.0f, 0.0f, 0.0f);
+ case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
+ return Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+ case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
+ return Vec4(1.0f, 1.0f, 1.0f, 1.0f);
+ 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
+
+ if (isSrgb)
+ {
+ return sRGBToLinear(result);
+ }
+ else
+ {
+ return result;
+ }
+ }
+
+ return Vec4(0.0f);
+}
+
+Vec4 SampleVerifier::getFilteredSample1D (const IVec3& texelBase,
+ float weight,
+ deUint32 layer,
+ deUint8 level) const
+{
+ Vec4 texels[2];
+
+ for (deUint8 i = 0; i < 2; ++i)
+ {
+ texels[i] = fetchTexel(texelBase + IVec3(i, 0, 0), layer, level, VK_FILTER_LINEAR);
+ }
+
+ return (1.0f - weight) * texels[0] + weight * texels[1];
+}
+
+
+Vec4 SampleVerifier::getFilteredSample2D (const IVec3& texelBase,
+ const Vec2& weights,
+ deUint32 layer,
+ deUint8 level) const
+{
+ Vec4 texels[4];
+
+ for (deUint8 i = 0; i < 2; ++i)
+ {
+ for (deUint8 j = 0; j < 2; ++j)
+ {
+ texels[2 * j + i] = fetchTexel(texelBase + IVec3(i, j, 0), layer, level, VK_FILTER_LINEAR);
+ }
+ }
+
+ 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];
+}
+
+Vec4 SampleVerifier::getFilteredSample3D (const IVec3& texelBase,
+ const Vec3& weights,
+ deUint32 layer,
+ deUint8 level) const
+{
+ Vec4 texels[8];
+
+ for (deUint8 i = 0; i < 2; ++i)
+ {
+ for (deUint8 j = 0; j < 2; ++j)
+ {
+ for (deUint8 k = 0; k < 2; ++k)
+ {
+ texels[4 * k + 2 * j + i] = fetchTexel(texelBase + IVec3(i, j, k), layer, level, VK_FILTER_LINEAR);
+ }
+ }
+ }
+
+ 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];
+}
+
+Vec4 SampleVerifier::getFilteredSample (const IVec3& texelBase,
+ const Vec3& weights,
+ deUint32 layer,
+ deUint8 level) 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);
+ }
+ else if (m_imParams.dim == IMG_DIM_2D || m_imParams.dim == IMG_DIM_CUBE)
+ {
+ return getFilteredSample2D(texelBase, weights.swizzle(0, 1), layer, level);
+ }
+ 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);
+ }
+}
+
+void SampleVerifier::getMipmapStepBounds (const Vec2& lodFracBounds,
+ deInt32& stepMin,
+ deInt32& stepMax) const
+{
+ DE_ASSERT(m_mipmapBits < 32);
+ const deUint32 mipmapSteps = ((deUint32) 1) << m_mipmapBits;
+
+ stepMin = deFloorFloatToInt32(lodFracBounds[0] * (float) mipmapSteps);
+ stepMax = deCeilFloatToInt32 (lodFracBounds[1] * (float) 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 Vec2& lodFracBounds,
+ VkFilter filter,
+ VkSamplerMipmapMode mipmapFilter,
+ std::ostream& report) const
+{
+ DE_ASSERT(layer < m_imParams.arrayLayers);
+ DE_ASSERT(levelHi < m_imParams.levels);
+
+ const float epsilon = calcRelEpsilon(m_imParams.format, filter, mipmapFilter);
+
+ const deUint32 coordSteps = ((deUint32) 1) << m_coordBits;
+ const deUint32 lodSteps = ((deUint32) 1) << m_mipmapBits;
+
+ IVec3 texelBase[2];
+ IVec3 weightStepsMin[2];
+ IVec3 weightStepsMax[2];
+ deInt32 lodStepsMin;
+ deInt32 lodStepsMax;
+
+ deUint8 levels;
+ deUint8 levelLo;
+
+ 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 = (deUint8) 1 + levelHi;
+ }
+
+ getWeightStepBounds(unnormalizedCoordHi, weightStepsMin[0], weightStepsMax[0], texelBase[0]);
+
+ if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+ {
+ getWeightStepBounds(unnormalizedCoordLo, weightStepsMin[1], weightStepsMax[1], texelBase[1]);
+ getMipmapStepBounds(lodFracBounds, lodStepsMin, lodStepsMax);
+ }
+ else
+ {
+ texelBase[1] = IVec3(0);
+ weightStepsMin[1] = IVec3(0);
+ weightStepsMax[1] = IVec3(0);
+ }
+
+ IVec3 weightSteps[2] = {weightStepsMin[0], weightStepsMin[1]};
+
+ bool done = false;
+
+ while (!done)
+ {
+ report << "Testing at base texel " << texelBase[0] << ", " << texelBase[1] << " with weight steps " << weightSteps[0] << ", " << weightSteps[1] << "\n";
+
+ Vec4 idealSampleHi, idealSampleLo;
+
+ // Get ideal samples at steps at each mipmap level
+
+ if (filter == VK_FILTER_LINEAR)
+ {
+ Vec3 roundedWeightsHi, roundedWeightsLo;
+
+ 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 hi sample: " << idealSampleHi << "\n";
+
+ if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+ {
+ idealSampleLo = getFilteredSample(texelBase[1], roundedWeightsLo, layer, levelLo);
+
+ report << "Ideal lo sample: " << idealSampleLo << "\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";
+
+ if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+ {
+ idealSampleLo = fetchTexel(floor(unnormalizedCoordLo).cast<deInt32>(), layer, levelLo, VK_FILTER_NEAREST);
+
+ report << "Ideal lo sample: " << idealSampleLo << "\n";
+ }
+ }
+
+ // Test ideal samples based on mipmap filtering mode
+
+ if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+ {
+ for (deInt32 lodStep = lodStepsMin; lodStep <= lodStepsMax; ++lodStep)
+ {
+ float weight = (float) lodStep / (float) lodSteps;
+
+ report << "Testing at mipmap weight " << weight << "\n";
+
+ Vec4 idealSample = weight * idealSampleLo + (1.0f - weight) * idealSampleHi;
+
+ report << "Ideal sample: " << idealSample << "\n";
+
+ if (isEqualRelEpsilon(idealSample, result, epsilon))
+ {
+ return true;
+ }
+ else
+ {
+ report << "Failed comparison\n";
+ }
+ }
+ }
+ else if (filter == VK_FILTER_LINEAR)
+ {
+ if (isEqualRelEpsilon(idealSampleHi, result, epsilon))
+ {
+ return true;
+ }
+ else
+ {
+ 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)
+ {
+ 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;
+ }
+ }
+
+ if (carry)
+ {
+ done = true;
+ }
+ }
+
+ 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
+{
+ const deUint8 layer = m_imParams.isArrayed ? (deUint8) deRoundEven(args.layer) : 0U;
+
+ const bool canBeMinified = lodBounds[1] > 0.0f;
+ const bool canBeMagnified = lodBounds[0] <= 0.0f;
+
+ if (canBeMagnified)
+ {
+ report << "Trying magnification...\n";
+
+ if (m_samplerParams.magFilter == VK_FILTER_NEAREST)
+ {
+ report << "Testing against nearest texel at " << floor(unnormalizedCoord).cast<deInt32>() << "\n";
+
+ const Vec4 ideal = fetchTexel(floor(unnormalizedCoord).cast<deInt32>(), layer, level, VK_FILTER_NEAREST);
+
+ if (result == ideal)
+ {
+ return true;
+ }
+ else
+ {
+ report << "Failed against " << ideal << "\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))
+ return true;
+ }
+ }
+
+ if (canBeMinified)
+ {
+ report << "Trying minification...\n";
+
+ if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+ {
+ const Vec2 lodFracBounds = lodBounds - Vec2(level);
+
+ if (verifySampleFiltered(result, unnormalizedCoord, unnormalizedCoordLo, 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))
+ return true;
+ }
+ else
+ {
+ report << "Testing against nearest texel at " << floor(unnormalizedCoord).cast<deInt32>() << "\n";
+
+ Vec4 ideal = fetchTexel(floor(unnormalizedCoord).cast<deInt32>(), layer, level, VK_FILTER_NEAREST);
+
+ if (result == ideal)
+ {
+ return true;
+ }
+ else
+ {
+ report << "Failed against " << ideal << "\n";
+ }
+ }
+ }
+
+ return false;
+}
+
+bool SampleVerifier::verifySampleMipmapLevel (const SampleArguments& args,
+ const Vec4& result,
+ const Vec4& coord,
+ const Vec2& lodBounds,
+ deUint8 level,
+ std::ostream& report) const
+{
+ DE_ASSERT(level < m_imParams.levels);
+
+ VkSamplerMipmapMode mipmapFilter = m_samplerParams.mipmapFilter;
+
+ if (level == m_imParams.levels - 1)
+ {
+ mipmapFilter = VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ }
+
+ Vector<double, 3> unnormalizedCoordHiDbl, unnormalizedCoordLoDbl;
+
+ unnormalizedCoordHiDbl = coord.cast<double>().swizzle(0, 1, 2) * m_pba[level].getSize().cast<double>();
+
+ if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+ {
+ unnormalizedCoordLoDbl = coord.cast<double>().swizzle(0, 1, 2) * m_pba[level + 1].getSize().cast<double>();
+ }
+
+ // Check if result(s) will be rounded
+
+ bool hiIsRounded[3] = {false};
+ bool loIsRounded[3] = {false};
+
+ for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
+ {
+ hiIsRounded[compNdx] = ((double) (float) unnormalizedCoordHiDbl[compNdx]) != unnormalizedCoordHiDbl[compNdx];
+
+ if (mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+ {
+ loIsRounded[compNdx] = ((double) (float) unnormalizedCoordLoDbl[compNdx]) != unnormalizedCoordLoDbl[compNdx];
+ }
+ }
+
+ 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};
+
+ 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
+ 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))
+ return true;
+
+ // Increment rounding types
+
+ bool carry = true;
+
+ for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
+ {
+ if (hiIsRounded[compNdx])
+ {
+ if (carry)
+ {
+ if (roundTypesHi[compNdx] == 2)
+ {
+ roundTypesHi[compNdx] = 0;
+ }
+ else
+ {
+ roundTypesHi[compNdx]++;
+ carry = false;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
+ {
+ if (loIsRounded[compNdx])
+ {
+ if (carry)
+ {
+ if (roundTypesLo[compNdx] == 2)
+ {
+ roundTypesLo[compNdx] = 0;
+ }
+ else
+ {
+ roundTypesLo[compNdx]++;
+ carry = false;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ if (carry)
+ {
+ done = true;
+ }
+ }
+
+ return false;
+}
+
+bool SampleVerifier::verifySampleCubemapFace (const SampleArguments& args,
+ const Vec4& result,
+ const Vec4& coord,
+ const Vec4& dPdx,
+ const Vec4& dPdy,
+ deUint8 face,
+ std::ostream& report) const
+{
+ Vec2 lodBounds;
+
+ 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);
+ }
+ }
+ else
+ {
+ lodBounds[0] = lodBounds[1] = args.lod;
+ }
+
+ DE_ASSERT(lodBounds[0] <= lodBounds[1]);
+
+ const float q = (float) (m_imParams.levels - 1);
+
+ if (m_samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_NEAREST)
+ {
+ 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);
+ }
+
+ 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;
+
+ for (deUint8 compNdx = 0; compNdx < 2; ++compNdx)
+ {
+ if (lodBounds[compNdx] >= q)
+ {
+ levelBounds[compNdx] = deRoundFloatToInt32(q);
+ }
+ else
+ {
+ levelBounds[compNdx] = lodBounds[compNdx] < 0.0f ? 0 : deFloorFloatToInt32(lodBounds[compNdx]);
+ }
+ }
+
+ 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;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool SampleVerifier::verifySampleImpl (const SampleArguments& args,
+ const Vec4& result,
+ std::ostream& report) const
+{
+ // \todo [2016-07-11 collinbaker] Handle depth and stencil formats
+ // \todo [2016-07-06 collinbaker] Handle dRef
+ DE_ASSERT(m_samplerParams.isCompare == false);
+
+ Vec4 coord = args.coord;
+ deUint8 coordSize = 0;
+
+ if (m_imParams.dim == IMG_DIM_1D)
+ {
+ coordSize = 1;
+ }
+ else if (m_imParams.dim == IMG_DIM_2D)
+ {
+ coordSize = 2;
+ }
+ else if (m_imParams.dim == IMG_DIM_3D || m_imParams.dim == IMG_DIM_CUBE)
+ {
+ coordSize = 3;
+ }
+
+ // 15.6.1 Project operation
+
+ if (m_sampleLookupSettings.isProjective)
+ {
+ DE_ASSERT(args.coord[coordSize] != 0.0f);
+ const float proj = coord[coordSize];
+
+ coord = coord / proj;
+ }
+
+ const Vec4 dPdx = (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) ? args.dPdx : Vec4(0);
+ const Vec4 dPdy = (m_sampleLookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) ? args.dPdy : Vec4(0);
+
+ // 15.6.3 Cube Map Face Selection and Transformations
+
+ 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]));
+ }
+
+ for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
+ {
+ if (de::abs(r[compNdx]) == rMax)
+ {
+ isMajor[compNdx] = true;
+ }
+ }
+
+ DE_ASSERT(isMajor[0] || isMajor[1] || isMajor[2]);
+
+ // We must test every possible disambiguation order
+
+ for (deUint8 i = 0; i < 3; ++i)
+ {
+ if (!isMajor[i])
+ {
+ continue;
+ }
+
+ 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] =
+ {
+ {-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;
+ }
+
+ coordC[2] = de::abs(coordC[2]);
+
+ Vec4 coordFace;
+ Vec4 dPdxFace;
+ Vec4 dPdyFace;
+
+ for (deUint8 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]);
+ }
+
+ 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;
+ }
+ else
+ {
+ return verifySampleCubemapFace(args, result, coord, dPdx, dPdy, 0, report);
+ }
+}
+
+bool SampleVerifier::verifySampleReport (const SampleArguments& args,
+ const Vec4& result,
+ std::string& report) const
+{
+ std::ostringstream reportStream;
+
+ const bool isValid = verifySampleImpl(args, result, reportStream);
+
+ report = reportStream.str();
+
+ return isValid;
+}
+
+bool SampleVerifier::verifySample (const SampleArguments& args,
+ const Vec4& result) const
+{
+ // Create unopened ofstream to simulate "null" ostream
+ std::ofstream nullStream;
+
+ return verifySampleImpl(args, result, nullStream);
+}
+
+} // texture_filtering
+} // vkt
--- /dev/null
+#ifndef _VKTSAMPLEVERIFIER_HPP
+#define _VKTSAMPLEVERIFIER_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 "vkDefs.hpp"
+
+#include "deUniquePtr.hpp"
+
+#include "tcuTexture.hpp"
+#include "tcuVector.hpp"
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace vkt
+{
+namespace texture_filtering
+{
+
+struct SampleArguments
+{
+ tcu::Vec4 coord;
+ tcu::Vec4 dPdx;
+ tcu::Vec4 dPdy;
+ float layer;
+ float lod;
+ float lodBias;
+ float dRef;
+};
+
+enum LookupLodMode
+{
+ LOOKUP_LOD_MODE_DERIVATIVES = 0,
+ LOOKUP_LOD_MODE_LOD,
+
+ LOOKUP_LOD_MODE_LAST
+};
+
+struct SampleLookupSettings
+{
+ LookupLodMode lookupLodMode;
+ bool hasLodBias;
+ bool isProjective;
+};
+
+enum WrappingMode
+{
+ WRAPPING_MODE_REPEAT = 0,
+ WRAPPING_MODE_MIRRORED_REPEAT,
+ WRAPPING_MODE_CLAMP_TO_EDGE,
+ WRAPPING_MODE_CLAMP_TO_BORDER,
+ WRAPPING_MODE_MIRROR_CLAMP_TO_EDGE,
+
+ WRAPPING_MODE_LAST
+};
+
+struct SamplerParameters
+{
+ vk::VkFilter magFilter;
+ vk::VkFilter minFilter;
+ vk::VkSamplerMipmapMode mipmapFilter;
+
+ vk::VkSamplerAddressMode wrappingModeU;
+ vk::VkSamplerAddressMode wrappingModeV;
+ vk::VkSamplerAddressMode wrappingModeW;
+
+ vk::VkBorderColor borderColor;
+
+ float lodBias;
+ float minLod;
+ float maxLod;
+
+ bool isUnnormalized;
+ bool isCompare;
+};
+
+enum ImgDim
+{
+ IMG_DIM_INVALID = 0,
+ IMG_DIM_1D,
+ IMG_DIM_2D,
+ IMG_DIM_3D,
+ IMG_DIM_CUBE,
+
+ IMG_DIM_LAST
+};
+
+struct ImageViewParameters
+{
+ ImgDim dim;
+ vk::VkFormat format;
+ tcu::IVec3 size;
+ deUint8 levels;
+
+ bool isArrayed;
+ deUint32 arrayLayers;
+};
+
+class SampleVerifier
+{
+public:
+ SampleVerifier (const ImageViewParameters& imParams,
+ const SamplerParameters& samplerParams,
+ const SampleLookupSettings& sampleLookupSettings,
+ int coordBits,
+ int mipmapBits,
+ const std::vector<tcu::ConstPixelBufferAccess>& pba);
+
+ bool verifySample (const SampleArguments& args,
+ const tcu::Vec4& result) const;
+
+ bool verifySampleReport (const SampleArguments& args,
+ const tcu::Vec4& result,
+ 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::Vec2& lodFracBounds,
+ vk::VkFilter filter,
+ vk::VkSamplerMipmapMode mipmapFilter,
+ std::ostream& report) const;
+
+ bool verifySampleUnnormalizedCoords (const SampleArguments& args,
+ const tcu::Vec4& result,
+ const tcu::Vec3& unnormalizedCoord,
+ const tcu::Vec3& unnormalizedCoordLo,
+ const tcu::Vec2& lodBounds,
+ deUint8 level,
+ vk::VkSamplerMipmapMode mipmapFilter,
+ std::ostream& report) const;
+
+ bool verifySampleMipmapLevel (const SampleArguments& args,
+ const tcu::Vec4& result,
+ const tcu::Vec4& coord,
+ const tcu::Vec2& lodFracBounds,
+ deUint8 level,
+ std::ostream& report) const;
+
+ bool verifySampleCubemapFace (const SampleArguments& args,
+ const tcu::Vec4& result,
+ const tcu::Vec4& coord,
+ const tcu::Vec4& dPdx,
+ const tcu::Vec4& dPdy,
+ deUint8 face,
+ std::ostream& report) const;
+
+ bool verifySampleImpl (const SampleArguments& args,
+ const tcu::Vec4& result,
+ std::ostream& report) const;
+
+ bool coordOutOfRange (const tcu::IVec3& coord,
+ int compNdx,
+ int level) const;
+
+ tcu::Vec4 fetchTexel (const tcu::IVec3& coordIn,
+ deUint32 layer,
+ deUint8 level,
+ vk::VkFilter filter) const;
+
+ tcu::Vec4 getFilteredSample1D (const tcu::IVec3& texelBase,
+ float weight,
+ deUint32 layer,
+ deUint8 level) const;
+
+ tcu::Vec4 getFilteredSample2D (const tcu::IVec3& texelBase,
+ const tcu::Vec2& weights,
+ deUint32 layer,
+ deUint8 level) const;
+
+ tcu::Vec4 getFilteredSample3D (const tcu::IVec3& texelBase,
+ const tcu::Vec3& weights,
+ deUint32 layer,
+ deUint8 level) const;
+
+ tcu::Vec4 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;
+
+ void getMipmapStepBounds (const tcu::Vec2& lodFracBounds,
+ deInt32& stepMin,
+ deInt32& stepMax) const;
+
+ const ImageViewParameters& m_imParams;
+ const SamplerParameters& m_samplerParams;
+ const SampleLookupSettings& m_sampleLookupSettings;
+
+ int m_coordBits;
+ int m_mipmapBits;
+
+ int m_unnormalizedDim;
+
+ const std::vector<tcu::ConstPixelBufferAccess>& m_pba;
+};
+
+} // texture_filtering
+} // vkt
+
+#endif // _VKTSAMPLEVERIFIER_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * 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 Texture filtering tests with explicit LOD instructions
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTextureFilteringExplicitLodTests.hpp"
+
+#include "vkDefs.hpp"
+
+#include "vktSampleVerifier.hpp"
+#include "vktShaderExecutor.hpp"
+#include "vktTestCaseUtil.hpp"
+
+#include "vkDeviceUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkStrUtil.hpp"
+
+#include "tcuTexLookupVerifier.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuTexture.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuVector.hpp"
+
+#include "deClock.h"
+#include "deMath.h"
+#include "deUniquePtr.hpp"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace vkt
+{
+namespace texture_filtering
+{
+
+using namespace tcu;
+using namespace vk;
+using std::string;
+
+namespace
+{
+
+using namespace shaderexecutor;
+
+string genSamplerDeclaration(const ImageViewParameters& imParams,
+ const SamplerParameters& samplerParams)
+{
+ string result = "sampler";
+
+ switch (imParams.dim)
+ {
+ 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;
+ }
+
+ if (imParams.isArrayed)
+ {
+ result += "Array";
+ }
+
+ if (samplerParams.isCompare)
+ {
+ result += "Shadow";
+ }
+
+ return result;
+}
+
+string genLookupCode(const ImageViewParameters& imParams,
+ const SamplerParameters& samplerParams,
+ const SampleLookupSettings& lookupSettings)
+{
+ int dim;
+
+ 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;
+ }
+
+ DE_ASSERT(dim >= 1 && dim <= 3);
+
+ int numCoordComp = dim;
+
+ if (lookupSettings.isProjective)
+ {
+ ++numCoordComp;
+ }
+
+ int numArgComp = numCoordComp;
+ bool hasSeparateCompare = false;
+
+ if (imParams.isArrayed)
+ {
+ DE_ASSERT(!lookupSettings.isProjective && "Can't do a projective lookup on an arrayed image!");
+
+ ++numArgComp;
+ }
+
+ if (samplerParams.isCompare && numCoordComp == 4)
+ {
+ hasSeparateCompare = true;
+ }
+ else if (samplerParams.isCompare)
+ {
+ ++numArgComp;
+ }
+
+ // Build coordinate input to texture*() function
+
+ string arg = "vec";
+ arg += (char) (numArgComp + '0');
+ arg += "(vec";
+ arg += (char) (numCoordComp + '0');
+ arg += "(coord)";
+
+ int numZero = numArgComp - numCoordComp;
+
+ if (imParams.isArrayed)
+ {
+ arg += ", layer";
+ --numZero;
+ }
+
+ if (samplerParams.isCompare && !hasSeparateCompare)
+ {
+ arg += ", dRef";
+ --numZero;
+ }
+
+ for (int ndx = 0; ndx < numZero; ++ndx)
+ {
+ arg += ", 0.0";
+ }
+
+ arg += ")";
+
+ // Build call to texture*() function
+
+ string code;
+
+ code += "result = texture";
+
+ if (lookupSettings.isProjective)
+ {
+ code += "Proj";
+ }
+
+ if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
+ {
+ code += "Grad";
+ }
+ else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
+ {
+ code += "Lod";
+ }
+
+ code += "(testSampler, ";
+ code += arg;
+
+ if (samplerParams.isCompare && hasSeparateCompare)
+ {
+ code += ", dRef";
+ }
+
+ if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
+ {
+ code += ", dPdx, dPdy";
+ }
+ else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
+ {
+ code += ", lod";
+ }
+
+ code += ");";
+
+ return code;
+}
+
+void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba, ImageViewParameters imParams)
+{
+ const DeviceInterface& vkd = ctx.getDeviceInterface();
+ const VkDevice dev = ctx.getDevice();
+ const deUint32 uqfi = ctx.getUniversalQueueFamilyIndex();
+
+ const VkDeviceSize bufSize =
+ getPixelSize(mapVkFormat(imParams.format))
+ * imParams.arrayLayers
+ * imParams.size[0]
+ * imParams.size[1]
+ * imParams.size[2]
+ * 2;
+
+ const VkBufferCreateInfo bufCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0, // flags
+ bufSize, // size
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
+ VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 1, // queueFamilyIndexCount
+ &uqfi // pQueueFamilyIndices
+ };
+
+ Unique<VkBuffer> buf(createBuffer(vkd, dev, &bufCreateInfo));
+
+ VkMemoryRequirements bufMemReq;
+ vkd.getBufferMemoryRequirements(dev, buf.get(), &bufMemReq);
+
+ de::UniquePtr<Allocation> bufMem(ctx.getDefaultAllocator().allocate(bufMemReq, MemoryRequirement::HostVisible));
+ VK_CHECK(vkd.bindBufferMemory(dev, buf.get(), bufMem->getMemory(), bufMem->getOffset()));
+
+ const VkCommandPoolCreateInfo copyPoolCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ DE_NULL,
+ VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
+ uqfi
+ };
+
+ Unique<VkCommandPool> copyPool(createCommandPool(vkd, dev, ©PoolCreateInfo));
+
+ const VkCommandBufferAllocateInfo copyBufferCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ DE_NULL,
+ copyPool.get(),
+ VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ 1
+ };
+
+ Unique<VkCommandBuffer> copyBuffer(allocateCommandBuffer(vkd, dev, ©BufferCreateInfo));
+
+ std::vector<VkBufferImageCopy> copyRegions;
+
+ deUint8* const bufMapPtr = reinterpret_cast<deUint8*>(bufMem->getHostPtr());
+ deUint8* bufCurPtr = bufMapPtr;
+
+ for (int level = 0; level < imParams.levels; ++level)
+ {
+ const IVec3 curLevelSize = pba[level].getSize();
+
+ const std::size_t copySize =
+ getPixelSize(mapVkFormat(imParams.format))
+ * curLevelSize[0] * curLevelSize[1] * curLevelSize[2]
+ * imParams.arrayLayers;
+
+ deMemcpy(bufCurPtr, pba[level].getDataPtr(), copySize);
+
+ flushMappedMemoryRange(vkd, dev, bufMem->getMemory(), bufMem->getOffset() + (bufCurPtr - bufMapPtr), copySize);
+
+ const VkImageSubresourceLayers curSubresource =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ (deUint32) level,
+ 0,
+ (deUint32) imParams.arrayLayers
+ };
+
+ const VkBufferImageCopy curRegion =
+ {
+ (VkDeviceSize) (bufCurPtr - bufMapPtr),
+ 0,
+ 0,
+ curSubresource,
+ {0U, 0U, 0U},
+ {(deUint32) curLevelSize[0], (deUint32) curLevelSize[1], (deUint32) curLevelSize[2]}
+ };
+
+ copyRegions.push_back(curRegion);
+
+ bufCurPtr += copySize;
+ }
+
+ const VkCommandBufferBeginInfo beginInfo =
+ {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+ DE_NULL
+ };
+
+ VK_CHECK(vkd.beginCommandBuffer(copyBuffer.get(), &beginInfo));
+
+ const VkImageSubresourceRange imMemBarSubRange =
+ {
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ 0,
+ imParams.levels,
+ 0,
+ imParams.arrayLayers
+ };
+
+ VkImageMemoryBarrier imMemBar =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ DE_NULL,
+ 0,
+ VK_ACCESS_TRANSFER_WRITE_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_QUEUE_FAMILY_IGNORED,
+ VK_QUEUE_FAMILY_IGNORED,
+ im,
+ imMemBarSubRange
+ };
+
+ VkBufferMemoryBarrier bufMemBar =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ VK_ACCESS_HOST_WRITE_BIT,
+ VK_ACCESS_TRANSFER_READ_BIT,
+ VK_QUEUE_FAMILY_IGNORED,
+ VK_QUEUE_FAMILY_IGNORED,
+ buf.get(),
+ 0,
+ bufSize
+ };
+
+ vkd.cmdPipelineBarrier(copyBuffer.get(),
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ 0,
+ 0,
+ DE_NULL,
+ 1,
+ &bufMemBar,
+ 1,
+ &imMemBar);
+
+ vkd.cmdCopyBufferToImage(copyBuffer.get(),
+ buf.get(),
+ im,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ (deUint32) copyRegions.size(),
+ ©Regions[0]);
+
+ imMemBar.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ imMemBar.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ imMemBar.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ imMemBar.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ vkd.cmdPipelineBarrier(copyBuffer.get(),
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ 0,
+ 0,
+ DE_NULL,
+ 0,
+ DE_NULL,
+ 1,
+ &imMemBar);
+
+ VK_CHECK(vkd.endCommandBuffer(copyBuffer.get()));
+
+ const VkSubmitInfo copySubmitInfo =
+ {
+ VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ DE_NULL,
+ 0,
+ DE_NULL,
+ DE_NULL,
+ 1,
+ &(copyBuffer.get()),
+ 0,
+ DE_NULL
+ };
+
+ VK_CHECK(vkd.queueSubmit(ctx.getUniversalQueue(), 1, ©SubmitInfo, 0));
+ VK_CHECK(vkd.queueWaitIdle(ctx.getUniversalQueue()));
+}
+
+struct TestCaseData
+{
+ std::vector<ConstPixelBufferAccess> pba;
+ ImageViewParameters imParams;
+ SamplerParameters samplerParams;
+ SampleLookupSettings sampleLookupSettings;
+ const SampleArguments* sampleArguments;
+ deUint32 numSamples;
+ glu::ShaderType shaderType;
+};
+
+VkSamplerCreateInfo mapSamplerCreateInfo (const SamplerParameters& samplerParams)
+{
+ VkSamplerCreateInfo samplerCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0U, // flags
+ samplerParams.magFilter, // magFilter
+ samplerParams.minFilter, // minFilter
+ samplerParams.mipmapFilter, // mipmapMode
+ samplerParams.wrappingModeU, // addressModeU
+ samplerParams.wrappingModeV, // addressModeV
+ samplerParams.wrappingModeW, // addressMoveW
+ samplerParams.lodBias, // mipLodBias
+ VK_FALSE, // anisotropyEnable
+ 1.0f, // maxAnisotropy
+ VK_FALSE, // compareEnable
+ VK_COMPARE_OP_NEVER, // compareOp
+ samplerParams.minLod, // minLod
+ samplerParams.maxLod, // maxLod
+ samplerParams.borderColor, // borderColor
+ samplerParams.isUnnormalized ? VK_TRUE : VK_FALSE, // unnormalizedCoordinates
+ };
+
+ if (samplerParams.isCompare)
+ {
+ samplerCreateInfo.compareEnable = VK_TRUE;
+
+ DE_FATAL("Not implemented");
+ }
+
+ return samplerCreateInfo;
+}
+
+VkImageType mapImageType (ImgDim dim)
+{
+ VkImageType imType;
+
+ switch (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;
+ }
+
+ return imType;
+}
+
+VkImageViewType mapImageViewType (const ImageViewParameters& imParams)
+{
+ VkImageViewType imViewType;
+
+ if (imParams.isArrayed)
+ {
+ switch (imParams.dim)
+ {
+ 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;
+ }
+ }
+ else
+ {
+ switch (imParams.dim)
+ {
+ 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;
+ }
+ }
+
+ return imViewType;
+}
+
+class DataGenerator
+{
+public:
+ virtual ~DataGenerator (void) {}
+
+ virtual bool generate (void) = 0;
+
+ virtual std::vector<ConstPixelBufferAccess> getPba (void) const = 0;
+ virtual std::vector<SampleArguments> getSampleArgs (void) const = 0;
+
+protected:
+ DataGenerator (void) {}
+};
+
+class TextureFilteringTestInstance : public TestInstance
+{
+public:
+ TextureFilteringTestInstance (Context& ctx,
+ const TestCaseData& testCaseData,
+ ShaderExecutor& shaderExecutor,
+ de::MovePtr<DataGenerator> gen)
+
+ : TestInstance (ctx)
+ , m_imParams (testCaseData.imParams)
+ , m_samplerParams (testCaseData.samplerParams)
+ , m_sampleLookupSettings (testCaseData.sampleLookupSettings)
+ , m_shaderExecutor (shaderExecutor)
+ , m_ctx (ctx)
+ , m_vki (m_ctx.getInstanceInterface())
+ , m_vkd (m_ctx.getDeviceInterface())
+ , m_instance (m_ctx.getInstance())
+ , m_physicalDevice (m_ctx.getPhysicalDevice())
+ , m_device (m_ctx.getDevice())
+ , m_uqfi (m_ctx.getUniversalQueueFamilyIndex())
+ , m_pba (testCaseData.pba)
+ , m_gen (gen.release())
+ {
+ for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
+ {
+ DE_ASSERT(m_imParams.size[compNdx] > 0);
+ }
+
+ m_imExtent.width = m_imParams.size[0];
+ m_imExtent.height = m_imParams.size[1];
+ m_imExtent.depth = m_imParams.size[2];
+ }
+
+ virtual TestStatus iterate (void)
+ {
+ return runTest();
+ }
+
+protected:
+ TestStatus runTest (void);
+ bool isSupported (void);
+ void createResources (void);
+ void execute (void);
+ bool verify (void);
+
+ tcu::Sampler mapTcuSampler (void);
+
+ const ImageViewParameters& m_imParams;
+ const SamplerParameters& m_samplerParams;
+ const SampleLookupSettings& m_sampleLookupSettings;
+
+ std::vector<SampleArguments> m_sampleArguments;
+ deUint32 m_numSamples;
+
+ ShaderExecutor& m_shaderExecutor;
+ Context& m_ctx;
+ const InstanceInterface& m_vki;
+ const DeviceInterface& m_vkd;
+ VkInstance m_instance;
+ VkPhysicalDevice m_physicalDevice;
+ VkDevice m_device;
+ deUint32 m_uqfi;
+
+ VkExtent3D m_imExtent;
+
+ int m_coordBits;
+ int m_mipmapBits;
+
+ de::MovePtr<Allocation> m_imAllocation;
+ Move<VkImage> m_im;
+ Move<VkImageView> m_imView;
+ Move<VkSampler> m_sampler;
+
+ std::vector<ConstPixelBufferAccess> m_pba;
+ de::MovePtr<DataGenerator> m_gen;
+
+ std::vector<Vec4> m_resultSamples;
+ std::vector<Vec4> m_resultCoords;
+};
+
+TestStatus TextureFilteringTestInstance::runTest (void)
+{
+ if (!isSupported())
+ {
+ TCU_THROW(NotSupportedError, "Unsupported combination of filtering and image format");
+ }
+
+ TCU_CHECK(m_gen->generate());
+ m_pba = m_gen->getPba();
+
+ m_sampleArguments = m_gen->getSampleArgs();
+ m_numSamples = (deUint32) m_sampleArguments.size();
+
+ createResources();
+ initializeImage(m_ctx, m_im.get(), &m_pba[0], m_imParams);
+
+ m_shaderExecutor.addSamplerUniform(0, m_imView.get(), m_sampler.get());
+
+ deUint64 startTime, endTime;
+
+ startTime = deGetMicroseconds();
+ execute();
+ endTime = deGetMicroseconds();
+
+ m_ctx.getTestContext().getLog() << TestLog::Message
+ << "Execution time: "
+ << endTime - startTime
+ << "us"
+ << TestLog::EndMessage;
+
+ startTime = deGetMicroseconds();
+ bool result = verify();
+ endTime = deGetMicroseconds();
+
+ m_ctx.getTestContext().getLog() << TestLog::Message
+ << "Verification time: "
+ << endTime - startTime
+ << "us"
+ << TestLog::EndMessage;
+
+ if (result)
+ {
+ return TestStatus::pass("Success");
+ }
+ else
+ {
+ // \todo [2016-06-24 collinbaker] Print report if verification fails
+ return TestStatus::fail("Verification failed");
+ }
+}
+
+bool TextureFilteringTestInstance::verify (void)
+{
+ // \todo [2016-06-24 collinbaker] Handle cubemaps
+
+ m_coordBits = (deUint8) m_ctx.getDeviceProperties().limits.subTexelPrecisionBits;
+ m_mipmapBits = (deUint8) m_ctx.getDeviceProperties().limits.mipmapPrecisionBits;
+
+ SampleVerifier verifier(m_imParams,
+ m_samplerParams,
+ m_sampleLookupSettings,
+ m_coordBits,
+ m_mipmapBits,
+ m_pba);
+
+ 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)
+ {
+ LogImage("", "", m_pba[levelNdx]).write(m_ctx.getTestContext().getLog());
+ }
+
+ m_ctx.getTestContext().getLog()
+ << TestLog::Message
+ << "Failure report:\n" << report << "\n"
+ << TestLog::EndMessage;
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void TextureFilteringTestInstance::execute (void)
+{
+ std::vector<float> coords, layers, dRefs, dPdxs, dPdys, lods;
+
+ for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
+ {
+ const SampleArguments& sampleArgs = m_sampleArguments[ndx];
+
+ for (deUint8 compNdx = 0; compNdx < 4; ++compNdx)
+ {
+ coords.push_back(sampleArgs.coord[compNdx]);
+ dPdxs .push_back(sampleArgs.dPdx[compNdx]);
+ dPdys .push_back(sampleArgs.dPdy[compNdx]);
+ }
+
+ layers.push_back(sampleArgs.layer);
+ dRefs .push_back(sampleArgs.dRef);
+ lods .push_back(sampleArgs.lod);
+ }
+
+ const void* inputs[6] =
+ {
+ reinterpret_cast<const void*>(&coords[0]),
+ reinterpret_cast<const void*>(&layers[0]),
+ reinterpret_cast<const void*>(&dRefs[0]),
+ reinterpret_cast<const void*>(&dPdxs[0]),
+ reinterpret_cast<const void*>(&dPdys[0]),
+ reinterpret_cast<const void*>(&lods[0])
+ };
+
+ // Staging buffers; data will be copied into vectors of Vec4
+ // \todo [2016-06-24 collinbaker] Figure out if I actually need to
+ // use staging buffers
+ std::vector<float> resultSamplesTemp(m_numSamples * 4);
+ std::vector<float> resultCoordsTemp (m_numSamples * 4);
+
+ void* outputs[2] =
+ {
+ reinterpret_cast<void*>(&resultSamplesTemp[0]),
+ reinterpret_cast<void*>(&resultCoordsTemp[0])
+ };
+
+ m_shaderExecutor.execute(m_ctx, m_numSamples, inputs, outputs);
+
+ m_resultSamples.resize(m_numSamples);
+ m_resultCoords .resize(m_numSamples);
+
+ for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
+ {
+ m_resultSamples[ndx] = Vec4(resultSamplesTemp[4 * ndx + 0],
+ resultSamplesTemp[4 * ndx + 1],
+ resultSamplesTemp[4 * ndx + 2],
+ resultSamplesTemp[4 * ndx + 3]);
+
+ m_resultCoords [ndx] = Vec4(resultCoordsTemp [4 * ndx + 0],
+ resultCoordsTemp [4 * ndx + 1],
+ resultCoordsTemp [4 * ndx + 2],
+ resultCoordsTemp [4 * ndx + 3]);
+ }
+}
+
+void TextureFilteringTestInstance::createResources (void)
+{
+ // Create VkImage
+
+ const VkImageCreateFlags imCreateFlags =
+ (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
+
+ const VkImageCreateInfo imCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ imCreateFlags, // flags
+ mapImageType(m_imParams.dim), // imageType
+ m_imParams.format, // format
+ m_imExtent, // extent
+ m_imParams.levels, // mipLevels
+ m_imParams.arrayLayers, // arrayLayers
+ VK_SAMPLE_COUNT_1_BIT, // samples
+ VK_IMAGE_TILING_OPTIMAL, // tiling
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // usage
+ VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 1, // queueFamilyIndexCount
+ &m_uqfi, // pQueueFamilyIndices
+ VK_IMAGE_LAYOUT_UNDEFINED // initialLayout
+ };
+
+ m_im = createImage(m_vkd, m_device, &imCreateInfo);
+
+ // Allocate memory for image
+
+ VkMemoryRequirements imMemReq;
+ m_vkd.getImageMemoryRequirements(m_device, m_im.get(), &imMemReq);
+
+ m_imAllocation = m_ctx.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any);
+ VK_CHECK(m_vkd.bindImageMemory(m_device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset()));
+
+ // Create VkImageView
+
+ // \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
+ };
+
+ if (m_imParams.dim == IMG_DIM_CUBE)
+ {
+ imViewSubresourceRange.layerCount *= 6;
+ }
+
+ const VkComponentMapping imViewCompMap =
+ {
+ VK_COMPONENT_SWIZZLE_R,
+ VK_COMPONENT_SWIZZLE_G,
+ VK_COMPONENT_SWIZZLE_B,
+ VK_COMPONENT_SWIZZLE_A
+ };
+
+ const VkImageViewCreateInfo imViewCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
+ DE_NULL, // pNext
+ 0, // flags
+ m_im.get(), // image
+ mapImageViewType(m_imParams), // viewType
+ m_imParams.format, // format
+ imViewCompMap, // components
+ imViewSubresourceRange // subresourceRange
+ };
+
+ m_imView = createImageView(m_vkd, m_device, &imViewCreateInfo);
+
+ // Create VkSampler
+
+ const VkSamplerCreateInfo samplerCreateInfo = mapSamplerCreateInfo(m_samplerParams);
+ m_sampler = createSampler(m_vkd, m_device, &samplerCreateInfo);
+}
+
+bool TextureFilteringTestInstance::isSupported (void)
+{
+ const VkImageCreateFlags imCreateFlags =
+ (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
+
+ VkImageFormatProperties imFormatProperties;
+ VkFormatProperties formatProperties;
+
+ m_vki.getPhysicalDeviceImageFormatProperties(m_physicalDevice,
+ m_imParams.format,
+ mapImageType(m_imParams.dim),
+ VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ imCreateFlags,
+ &imFormatProperties);
+
+ m_vki.getPhysicalDeviceFormatProperties( m_physicalDevice,
+ m_imParams.format,
+ &formatProperties);
+
+ // \todo [2016-06-23 collinbaker] Check image parameters against imFormatProperties
+
+ VkFormatFeatureFlags reqImFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
+
+ if (m_samplerParams.minFilter == VK_FILTER_LINEAR ||
+ m_samplerParams.magFilter == VK_FILTER_LINEAR ||
+ m_samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
+ {
+ reqImFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
+ }
+
+ return (formatProperties.optimalTilingFeatures & reqImFeatures) == reqImFeatures;
+}
+
+class TextureFilteringTestCase : public TestCase
+{
+public:
+ TextureFilteringTestCase (tcu::TestContext& testCtx,
+ const char* name,
+ const char* description)
+ : TestCase(testCtx, name, description)
+ {
+ }
+
+ void init (void);
+
+ virtual void initPrograms (vk::SourceCollections& programCollection) const
+ {
+ DE_ASSERT(m_executor);
+ m_executor->setShaderSources(programCollection);
+ }
+
+ virtual de::MovePtr<DataGenerator> createGenerator (void) const = 0;
+
+ virtual TestInstance* createInstance (Context& ctx) const
+ {
+ return new TextureFilteringTestInstance(ctx, m_testCaseData, *m_executor, createGenerator());
+ }
+
+protected:
+ de::MovePtr<ShaderExecutor> m_executor;
+ TestCaseData m_testCaseData;
+};
+
+void TextureFilteringTestCase::init (void)
+{
+ ShaderSpec shaderSpec;
+ shaderSpec.source = genLookupCode(m_testCaseData.imParams,
+ m_testCaseData.samplerParams,
+ m_testCaseData.sampleLookupSettings);
+ shaderSpec.source += "\nsampledCoord = coord;";
+
+ shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
+ shaderSpec.outputs.push_back(Symbol("sampledCoord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
+ shaderSpec.inputs .push_back(Symbol("coord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
+ shaderSpec.inputs .push_back(Symbol("layer", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
+ shaderSpec.inputs .push_back(Symbol("dRef", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
+ shaderSpec.inputs .push_back(Symbol("dPdx", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
+ shaderSpec.inputs .push_back(Symbol("dPdy", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
+ shaderSpec.inputs .push_back(Symbol("lod", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
+
+ shaderSpec.globalDeclarations = "layout(set=0, binding=0) uniform highp ";
+ shaderSpec.globalDeclarations += genSamplerDeclaration(m_testCaseData.imParams,
+ m_testCaseData.samplerParams);
+ shaderSpec.globalDeclarations += " testSampler;";
+
+ m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_testCaseData.shaderType, shaderSpec));
+ DE_ASSERT(m_executor);
+
+ m_testCtx.getLog() << *m_executor;
+}
+
+class Texture2DGradientTestCase : public TextureFilteringTestCase
+{
+public:
+ Texture2DGradientTestCase (TestContext& testCtx,
+ const char* name,
+ const char* desc,
+ TextureFormat format,
+ IVec3 dimensions,
+ VkFilter magFilter,
+ VkFilter minFilter,
+ VkSamplerMipmapMode mipmapFilter,
+ VkSamplerAddressMode wrappingMode)
+
+ : TextureFilteringTestCase (testCtx, name, desc)
+ , m_testCtx (testCtx)
+ , m_format (format)
+ , m_dimensions (dimensions)
+ , m_magFilter (magFilter)
+ , m_minFilter (minFilter)
+ , m_mipmapFilter (mipmapFilter)
+ , m_wrappingMode (wrappingMode)
+ {
+ m_testCaseData = genTestCaseData();
+ init();
+ }
+
+protected:
+ class Generator;
+
+ virtual de::MovePtr<DataGenerator> createGenerator (void) const;
+
+ TestCaseData genTestCaseData()
+ {
+ // Generate grid
+
+ SampleLookupSettings sampleLookupSettings =
+ {
+ LOOKUP_LOD_MODE_LOD, // lookupLodMode
+ false, // hasLodBias
+ false, // isProjective
+ };
+
+ SamplerParameters samplerParameters =
+ {
+ m_magFilter, // magFilter
+ m_minFilter, // minFilter
+ m_mipmapFilter, // mipmapFilter
+ m_wrappingMode, // wrappingModeU
+ m_wrappingMode, // wrappingModeV
+ m_wrappingMode, // wrappingModeW
+ VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, // borderColor
+ 0.0f, // lodBias
+ -1.0f, // minLod
+ 50.0f, // maxLod
+ false, // isUnnormalized
+ false // isCompare
+ };
+
+ deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_dimensions[0],
+ m_dimensions[1])));
+
+ ImageViewParameters imParameters =
+ {
+ IMG_DIM_2D, // dim
+ mapTextureFormat(m_format), // format
+ m_dimensions, // size
+ numLevels, // levels
+ false, // isArrayed
+ 1, // arrayLayers
+ };
+
+ TestCaseData data =
+ {
+ std::vector<ConstPixelBufferAccess>(),
+ imParameters,
+ samplerParameters,
+ sampleLookupSettings,
+ &m_args[0],
+ (deUint32) m_args.size(),
+ glu::SHADERTYPE_FRAGMENT
+ };
+
+ return data;
+ }
+
+private:
+ TestContext& m_testCtx;
+ TextureFormat m_format;
+ IVec3 m_dimensions;
+ VkFilter m_magFilter;
+ VkFilter m_minFilter;
+ VkSamplerMipmapMode m_mipmapFilter;
+ VkSamplerAddressMode m_wrappingMode;
+
+ std::vector<SampleArguments> m_args;
+};
+
+class Texture2DGradientTestCase::Generator : public DataGenerator
+{
+public:
+ Generator (const Texture2DGradientTestCase* testCase) : m_testCase(testCase) {}
+
+ virtual ~Generator (void)
+ {
+ delete m_tex.release();
+ }
+
+ virtual bool generate (void)
+ {
+ m_tex = de::MovePtr<Texture2D>(new Texture2D(m_testCase->m_format,
+ m_testCase->m_dimensions[0],
+ m_testCase->m_dimensions[1]));
+
+ deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_testCase->m_dimensions[0],
+ m_testCase->m_dimensions[1])));
+
+ TextureFormatInfo fmtInfo = getTextureFormatInfo(m_testCase->m_format);
+
+ Vec4 cBias = fmtInfo.valueMin;
+ Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
+
+ for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
+ {
+ Vec4 gMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
+ Vec4 gMax = Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
+
+ m_tex->allocLevel(levelNdx);
+ fillWithComponentGradients(m_tex->getLevel(levelNdx), gMin, gMax);
+ }
+
+ return true;
+ }
+
+ virtual std::vector<ConstPixelBufferAccess> getPba (void) const
+ {
+ std::vector<ConstPixelBufferAccess> pba;
+
+ const deUint8 numLevels = (deUint8) m_tex->getNumLevels();
+
+ for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
+ {
+ pba.push_back(m_tex->getLevel(levelNdx));
+ }
+
+ return pba;
+ }
+
+ virtual std::vector<SampleArguments> getSampleArgs (void) const
+ {
+ 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)
+ {
+ for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
+ {
+ 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);
+ }
+ }
+ }
+
+ return args;
+ }
+
+private:
+ const Texture2DGradientTestCase* m_testCase;
+ de::MovePtr<Texture2D> m_tex;
+};
+
+de::MovePtr<DataGenerator> Texture2DGradientTestCase::createGenerator (void) const
+{
+ return de::MovePtr<DataGenerator>(new Generator(this));
+}
+
+TestCaseGroup* create2DFormatTests (TestContext& testCtx)
+{
+ de::MovePtr<TestCaseGroup> tests(
+ new TestCaseGroup(testCtx, "formats", "Various image formats"));
+
+ VkFormat formats[] =
+ {
+ VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+ VK_FORMAT_R5G6B5_UNORM_PACK16,
+ VK_FORMAT_A1R5G5B5_UNORM_PACK16,
+ VK_FORMAT_R8_UNORM,
+ VK_FORMAT_R8_SNORM,
+ VK_FORMAT_R8G8_UNORM,
+ VK_FORMAT_R8G8_SNORM,
+ VK_FORMAT_R8G8B8A8_UNORM,
+ VK_FORMAT_R8G8B8A8_SNORM,
+ VK_FORMAT_R8G8B8A8_SRGB,
+ VK_FORMAT_B8G8R8A8_UNORM,
+ VK_FORMAT_B8G8R8A8_SRGB,
+ VK_FORMAT_A8B8G8R8_UNORM_PACK32,
+ VK_FORMAT_A8B8G8R8_SNORM_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
+ };
+
+ const IVec3 size(32, 32, 1);
+
+ for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
+ {
+ std::string prefix = getFormatName(formats[formatNdx]);
+
+ Texture2DGradientTestCase* testCaseNearest =
+ new Texture2DGradientTestCase(
+ testCtx,
+ (prefix + "_nearest").c_str(),
+ "...",
+ mapVkFormat(formats[formatNdx]),
+ size,
+ VK_FILTER_NEAREST,
+ VK_FILTER_NEAREST,
+ VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_ADDRESS_MODE_REPEAT);
+
+ tests->addChild(testCaseNearest);
+
+ Texture2DGradientTestCase* testCaseLinear =
+ new Texture2DGradientTestCase(
+ testCtx,
+ (prefix + "_linear").c_str(),
+ "...",
+ mapVkFormat(formats[formatNdx]),
+ size,
+ VK_FILTER_LINEAR,
+ VK_FILTER_LINEAR,
+ VK_SAMPLER_MIPMAP_MODE_LINEAR,
+ VK_SAMPLER_ADDRESS_MODE_REPEAT);
+
+ tests->addChild(testCaseLinear);
+ }
+
+ return tests.release();
+}
+
+TestCaseGroup* create2DSizeTests (TestContext& testCtx)
+{
+ de::MovePtr<TestCaseGroup> tests(
+ new TestCaseGroup(testCtx, "sizes", "Various size and filtering combinations"));
+
+ const VkFilter filters[2] =
+ {
+ VK_FILTER_NEAREST,
+ VK_FILTER_LINEAR
+ };
+
+ const VkSamplerMipmapMode mipmapFilters[2] =
+ {
+ VK_SAMPLER_MIPMAP_MODE_NEAREST,
+ VK_SAMPLER_MIPMAP_MODE_LINEAR
+ };
+
+ const VkSamplerAddressMode wrappingModes[2] =
+ {
+ VK_SAMPLER_ADDRESS_MODE_REPEAT,
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
+ };
+
+ IVec3 sizes[] =
+ {
+ IVec3(2, 2, 1),
+ IVec3(2, 3, 1),
+ IVec3(3, 7, 1),
+ IVec3(4, 8, 1),
+ IVec3(31, 55, 1),
+ IVec3(32, 32, 1),
+ IVec3(32, 64, 1),
+ IVec3(57, 35, 1),
+ IVec3(128, 128, 1)
+ };
+
+
+ for (deUint32 sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
+ {
+ for (deUint32 magFilterNdx = 0; magFilterNdx < 2; ++magFilterNdx)
+ {
+ for (deUint32 minFilterNdx = 0; minFilterNdx < 2; ++minFilterNdx)
+ {
+ for (deUint32 mipmapFilterNdx = 0; mipmapFilterNdx < 2; ++mipmapFilterNdx)
+ {
+ for (deUint32 wrappingModeNdx = 0; wrappingModeNdx < 2; ++wrappingModeNdx)
+ {
+ std::ostringstream caseName;
+
+ caseName << sizes[sizeNdx][0] << "x" << sizes[sizeNdx][1];
+
+ 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;
+ }
+
+ switch (mipmapFilters[mipmapFilterNdx])
+ {
+ case VK_SAMPLER_MIPMAP_MODE_NEAREST:
+ caseName << "_mipmap_nearest";
+ break;
+ case VK_SAMPLER_MIPMAP_MODE_LINEAR:
+ caseName << "_mipmap_linear";
+ break;
+ default:
+ break;
+ }
+
+ switch (wrappingModes[wrappingModeNdx])
+ {
+ case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
+ caseName << "_clamp";
+ break;
+ case VK_SAMPLER_ADDRESS_MODE_REPEAT:
+ caseName << "_repeat";
+ break;
+ default:
+ break;
+ }
+
+ Texture2DGradientTestCase* testCase =
+ new Texture2DGradientTestCase(
+ testCtx,
+ caseName.str().c_str(),
+ "...",
+ mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM),
+ sizes[sizeNdx],
+ filters[magFilterNdx],
+ filters[minFilterNdx],
+ mipmapFilters[mipmapFilterNdx],
+ wrappingModes[wrappingModeNdx]);
+
+ tests->addChild(testCase);
+ }
+ }
+ }
+ }
+ }
+
+ return tests.release();
+}
+
+TestCaseGroup* create2DTests (TestContext& testCtx)
+{
+ de::MovePtr<TestCaseGroup> tests(
+ new TestCaseGroup(testCtx, "2d", "2D Image filtering tests"));
+
+ tests->addChild(create2DSizeTests(testCtx));
+ tests->addChild(create2DFormatTests(testCtx));
+
+ return tests.release();
+}
+
+} // anonymous
+
+TestCaseGroup* createExplicitLodTests (TestContext& testCtx)
+{
+ de::MovePtr<TestCaseGroup> tests(
+ new TestCaseGroup(testCtx, "explicit_lod", "Texture filtering with explicit LOD"));
+
+ tests->addChild(create2DTests(testCtx));
+
+ return tests.release();
+}
+
+} // texture_filtering
+} // vkt
--- /dev/null
+#ifndef _VKTTEXTUREFILTERINGEXPLICITLODTESTS_HPP
+#define _VKTTEXTUREFILTERINGEXPLICITLODTESTS_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 Texture filtering tests with explicit LOD instructions
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace texture_filtering
+{
+
+tcu::TestCaseGroup* createExplicitLodTests (tcu::TestContext& testCtx);
+
+} // texture_filtering
+} // vkt
+
+#endif // _VKTTEXTUREFILTERINGEXPLICITLODTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * 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 Texture filtering tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTextureFilteringTests.hpp"
+
+#include "vktTextureFilteringExplicitLodTests.hpp"
+#include "deUniquePtr.hpp"
+
+namespace vkt
+{
+namespace texture_filtering
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "texture_filtering", "Texture filtering verification tests"));
+
+ group->addChild(createExplicitLodTests(testCtx));
+
+ return group.release();
+}
+
+} // texture_filtering
+} // vkt
--- /dev/null
+#ifndef _VKTTEXTUREFILTERINGTESTS_HPP
+#define _VKTTEXTUREFILTERINGTESTS_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 Texture filtering tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace texture_filtering
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx);
+
+} // texture_filtering
+} // vkt
+
+#endif // _VKTTEXTUREFILTERINGTESTS_HPP
#include "vktShaderRenderTextureGatherTests.hpp"
#include "vktShaderBuiltinTests.hpp"
#include "vktOpaqueTypeIndexingTests.hpp"
+#include "vktTextureFilteringTests.hpp"
#include "vktUniformBlockTests.hpp"
#include "vktDynamicStateTests.hpp"
#include "vktSSBOLayoutTests.hpp"
addChild(tessellation::createTests (m_testCtx));
addChild(rasterization::createTests (m_testCtx));
addChild(clipping::createTests (m_testCtx));
+ addChild(texture_filtering::createTests (m_testCtx));
}
} // vkt