dEQP-VK.sparse_resources.shader_intrinsics*gather: fix possible of-by-one errors
authorSlawomir Cygan <slawomir.cygan@intel.com>
Thu, 6 Oct 2016 15:31:47 +0000 (17:31 +0200)
committerPyry Haulos <phaulos@google.com>
Fri, 14 Oct 2016 19:51:02 +0000 (12:51 -0700)
The test seems to perform GATHER sampling from center of pixels

On un-even image sizes this may cause failures, as texcoord (being float32)
may not exactly represent pixel center, what can cause different 2x2 rectangle to
be gathered.

The fix is to bias texcoord by half a texel, so sampling is always performed
from centre of 2x2 rectangle.

Fixes following tests (for me):
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.r32i.503_137_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.r32i.11_37_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.r16i.503_137_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.r16i.11_37_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.r8i.503_137_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.r8i.11_37_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.rgba32ui.503_137_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.rgba32ui.11_37_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.rgba16ui.503_137_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.rgba16ui.11_37_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.rgba8ui.503_137_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_sparse_gather.rgba8ui.11_37_1
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.r32i.503_137_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.r32i.11_37_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.r16i.503_137_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.r16i.11_37_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.r8i.503_137_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.r8i.11_37_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba32ui.503_137_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba32ui.11_37_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba16ui.503_137_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba16ui.11_37_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.503_137_3
dEQP-VK.sparse_resources.shader_intrinsics.2d_array_sparse_gather.rgba8ui.11_37_3

Affects: dEQP-VK.sparse_resources.shader_intrinsics.*gather*

Change-Id: I218d68033e3c83d5270c54731eac3a72c6899173

external/vulkancts/modules/vulkan/sparse_resources/vktSparseResourcesShaderIntrinsicsSampled.cpp

index 538afc26efc3fc9302b40ab79eb3c09999864bc2..d93bbb36db0223ffdb039eb552fef191264e47dd 100644 (file)
@@ -116,9 +116,10 @@ void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections&
                << "OpName %output_texel \"out_texel\"\n"
                << "OpName %output_residency \"out_residency\"\n"
 
-               << "OpName %type_uniformblock_lod \"LodBlock\"\n"
-               << "OpMemberName %type_uniformblock_lod 0 \"lod\"\n"
-               << "OpName %uniformblock_lod_instance \"lodInstance\"\n"
+               << "OpName %type_uniformblock \"LodBlock\"\n"
+               << "OpMemberName %type_uniformblock 0 \"lod\"\n"
+               << "OpMemberName %type_uniformblock 1 \"size\"\n"
+               << "OpName %uniformblock_instance \"lodInstance\"\n"
 
                << "OpName %uniformconst_image_sparse \"u_imageSparse\"\n"
 
@@ -127,8 +128,9 @@ void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections&
                << "OpDecorate %output_texel     Location 0\n"
                << "OpDecorate %output_residency Location 1\n"
 
-               << "OpDecorate           %type_uniformblock_lod Block\n"
-               << "OpMemberDecorate %type_uniformblock_lod 0 Offset 0\n"
+               << "OpDecorate           %type_uniformblock Block\n"
+               << "OpMemberDecorate %type_uniformblock 0 Offset 0\n"
+               << "OpMemberDecorate %type_uniformblock 1 Offset 8\n"
 
                << "OpDecorate %uniformconst_image_sparse DescriptorSet 0\n"
                << "OpDecorate %uniformconst_image_sparse Binding " << BINDING_IMAGE_SPARSE << "\n"
@@ -143,7 +145,7 @@ void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections&
                << "%type_vec2                                                  = OpTypeVector %type_float 2\n"
                << "%type_vec3                                                  = OpTypeVector %type_float 3\n"
                << "%type_vec4                                                  = OpTypeVector %type_float 4\n"
-               << "%type_uniformblock_lod                              = OpTypeStruct %type_uint\n"
+               << "%type_uniformblock                                  = OpTypeStruct %type_uint %type_vec2\n"
                << "%type_img_comp                                              = " << getOpTypeImageComponent(m_format) << "\n"
                << "%type_img_comp_vec4                                 = OpTypeVector %type_img_comp 4\n"
                << "%type_struct_int_img_comp_vec4              = OpTypeStruct %type_int %type_img_comp_vec4\n"
@@ -159,8 +161,9 @@ void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections&
                << "%type_function_img_comp_vec4                = OpTypePointer Function %type_img_comp_vec4\n"
                << "%type_function_int_img_comp_vec4    = OpTypePointer Function %type_struct_int_img_comp_vec4\n"
 
-               << "%type_pushconstant_uniformblock_lod                 = OpTypePointer PushConstant %type_uniformblock_lod\n"
+               << "%type_pushconstant_uniformblock                             = OpTypePointer PushConstant %type_uniformblock\n"
                << "%type_pushconstant_uniformblock_member_lod  = OpTypePointer PushConstant %type_uint\n"
+               << "%type_pushconstant_uniformblock_member_size = OpTypePointer PushConstant %type_vec2\n"
 
                << "%type_image_sparse                          = " << getOpTypeImageSparse(m_imageType, m_format, "%type_img_comp", true) << "\n"
                << "%type_sampled_image_sparse          = OpTypeSampledImage %type_image_sparse\n"
@@ -173,7 +176,7 @@ void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections&
 
                << "%uniformconst_image_sparse  = OpVariable %type_uniformconst_image_sparse UniformConstant\n"
 
-               << "%uniformblock_lod_instance  = OpVariable %type_pushconstant_uniformblock_lod PushConstant\n"
+               << "%uniformblock_instance  = OpVariable %type_pushconstant_uniformblock PushConstant\n"
 
                // Declare constants
                << "%constant_uint_0                            = OpConstant %type_uint 0\n"
@@ -184,6 +187,8 @@ void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections&
                << "%constant_int_1                                     = OpConstant %type_int  1\n"
                << "%constant_int_2                                     = OpConstant %type_int  2\n"
                << "%constant_int_3                                     = OpConstant %type_int  3\n"
+               << "%constant_float_0                           = OpConstant %type_float 0.0\n"
+               << "%constant_float_half                        = OpConstant %type_float 0.5\n"
                << "%constant_texel_resident            = OpConstant %type_uint " << MEMORY_BLOCK_BOUND_VALUE << "\n"
                << "%constant_texel_not_resident        = OpConstant %type_uint " << MEMORY_BLOCK_NOT_BOUND_VALUE << "\n"
 
@@ -200,9 +205,11 @@ void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections&
                << "%local_texCoord_xy  = OpCompositeConstruct %type_vec2 %local_texCoord_x %local_texCoord_y\n"
                << "%local_texCoord_xyz = OpCompositeConstruct %type_vec3 %local_texCoord_x %local_texCoord_y %local_texCoord_z\n"
 
-               << "%access_uniformblock_member_uint_lod = OpAccessChain %type_pushconstant_uniformblock_member_lod %uniformblock_lod_instance %constant_int_0\n"
+               << "%access_uniformblock_member_uint_lod = OpAccessChain %type_pushconstant_uniformblock_member_lod %uniformblock_instance %constant_int_0\n"
                << "%local_uniformblock_member_uint_lod  = OpLoad %type_uint %access_uniformblock_member_uint_lod\n"
                << "%local_uniformblock_member_float_lod = OpConvertUToF %type_float %local_uniformblock_member_uint_lod\n"
+               << "%access_uniformblock_member_size     = OpAccessChain %type_pushconstant_uniformblock_member_size %uniformblock_instance %constant_int_1\n"
+               << "%local_uniformblock_member_size              = OpLoad %type_vec2 %access_uniformblock_member_size\n"
 
                << sparseImageOpString("%local_sparse_op_result", "%type_struct_int_img_comp_vec4", "%local_image_sparse", coordString, "%local_uniformblock_member_float_lod") << "\n"
 
@@ -276,10 +283,19 @@ std::string       SparseCaseOpImageSparseGather::sparseImageOpString (const std::strin
 
        std::ostringstream      src;
 
-       src << "%local_sparse_gather_result_x = OpImageSparseGather " << resultType << " " << image << " " << coord << " %constant_int_0\n";
-       src << "%local_sparse_gather_result_y = OpImageSparseGather " << resultType << " " << image << " " << coord << " %constant_int_1\n";
-       src << "%local_sparse_gather_result_z = OpImageSparseGather " << resultType << " " << image << " " << coord << " %constant_int_2\n";
-       src << "%local_sparse_gather_result_w = OpImageSparseGather " << resultType << " " << image << " " << coord << " %constant_int_3\n";
+       // Bias the coord value by half a texel, so we sample from center of 2x2 gather rectangle
+
+       src << "%local_image_width      = OpCompositeExtract %type_float %local_uniformblock_member_size 0\n";
+       src << "%local_image_height     = OpCompositeExtract %type_float %local_uniformblock_member_size 1\n";
+       src << "%local_coord_x_bias     = OpFDiv %type_float %constant_float_half %local_image_width\n";
+       src << "%local_coord_y_bias     = OpFDiv %type_float %constant_float_half %local_image_height\n";
+       src << "%local_coord_bias       = OpCompositeConstruct %type_vec3 %local_coord_x_bias %local_coord_y_bias %constant_float_0\n";
+       src << "%local_coord_biased     = OpFAdd %type_vec3 " << coord << " %local_coord_bias\n";
+
+       src << "%local_sparse_gather_result_x = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_0\n";
+       src << "%local_sparse_gather_result_y = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_1\n";
+       src << "%local_sparse_gather_result_z = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_2\n";
+       src << "%local_sparse_gather_result_w = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_3\n";
 
        src << "%local_gather_residency_code = OpCompositeExtract %type_int %local_sparse_gather_result_x 0\n";
 
@@ -510,12 +526,20 @@ void SparseShaderIntrinsicsInstanceSampledBase::recordCommands (vk::Allocator&
        const VkSamplerCreateInfo       samplerCreateInfo = mapSampler(samplerObject, m_format);
        sampler = createSampler(deviceInterface, *m_logicalDevice, &samplerCreateInfo);
 
+       struct PushConstants
+       {
+               deUint32        lod;
+               deUint32        padding;                        // padding needed to satisfy std430 rules
+               float           lodWidth;
+               float           lodHeight;
+       };
+
        // Create pipeline layout
        const VkPushConstantRange lodConstantRange =
        {
                VK_SHADER_STAGE_FRAGMENT_BIT,   // VkShaderStageFlags   stageFlags;
                0u,                                                             // deUint32                     offset;
-               sizeof(deUint32),                               // deUint32                     size;
+               sizeof(PushConstants),                  // deUint32                     size;
        };
 
        const VkPipelineLayoutCreateInfo pipelineLayoutParams =
@@ -702,8 +726,16 @@ void SparseShaderIntrinsicsInstanceSampledBase::recordCommands (vk::Allocator&
                // Bind Scissor Rectangle
                deviceInterface.cmdSetScissor(commandBuffer, 0u, 1u, &renderArea);
 
+               const PushConstants pushConstants =
+               {
+                       mipLevelNdx,
+                       0u,                                                                                     // padding
+                       static_cast<float>(mipLevelSize.width),
+                       static_cast<float>(mipLevelSize.height)
+               };
+
                // Update push constants
-               deviceInterface.cmdPushConstants(commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(deUint32), &mipLevelNdx);
+               deviceInterface.cmdPushConstants(commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(PushConstants), &pushConstants);
 
                // Draw full screen quad
                deviceInterface.cmdDraw(commandBuffer, 4u, 1u, 0u, 0u);