From: Dave Airlie <airl...@redhat.com>

This ports a fix from amdvlk, to fix the sizing for mip levels
when block compressed images are viewed using uncompressed views.

My original fix didn't power the clamping, but it looks like
the clamping is required to stop the sizing going too large.

Fixes:
dEQP-VK.image.texel_view_compatible.graphic.extended*bc*
Doesn't crash DOW3 anymore.

Signed-off-by: Dave Airlie <airl...@redhat.com>
---
 src/amd/vulkan/radv_image.c | 53 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 49 insertions(+), 4 deletions(-)

diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c
index 54b2b5247d2..0838e95ee19 100644
--- a/src/amd/vulkan/radv_image.c
+++ b/src/amd/vulkan/radv_image.c
@@ -1068,10 +1068,55 @@ radv_image_view_init(struct radv_image_view *iview,
        }
 
        if (iview->vk_format != image->vk_format) {
-               iview->extent.width = round_up_u32(iview->extent.width * 
vk_format_get_blockwidth(iview->vk_format),
-                                                  
vk_format_get_blockwidth(image->vk_format));
-               iview->extent.height = round_up_u32(iview->extent.height * 
vk_format_get_blockheight(iview->vk_format),
-                                                   
vk_format_get_blockheight(image->vk_format));
+               unsigned view_bw = vk_format_get_blockwidth(iview->vk_format);
+               unsigned view_bh = vk_format_get_blockheight(iview->vk_format);
+               unsigned img_bw = vk_format_get_blockwidth(image->vk_format);
+               unsigned img_bh = vk_format_get_blockheight(image->vk_format);
+
+               iview->extent.width = round_up_u32(iview->extent.width * 
view_bw, img_bw);
+               iview->extent.height = round_up_u32(iview->extent.height * 
view_bh, img_bh);
+
+               /* Comment ported from amdvlk -
+                * If we have the following image:
+                *              Uncompressed pixels   Compressed block sizes 
(4x4)
+                *      mip0:       22 x 22                   6 x 6
+                *      mip1:       11 x 11                   3 x 3
+                *      mip2:        5 x  5                   2 x 2
+                *      mip3:        2 x  2                   1 x 1
+                *      mip4:        1 x  1                   1 x 1
+                *
+                * On GFX9 the descriptor is always programmed with the WIDTH 
and HEIGHT of the base level and the HW is
+                * calculating the degradation of the block sizes down the 
mip-chain as follows (straight-up
+                * divide-by-two integer math):
+                *      mip0:  6x6
+                *      mip1:  3x3
+                *      mip2:  1x1
+                *      mip3:  1x1
+                *
+                * This means that mip2 will be missing texels.
+                *
+                * Fix this by calculating the base mip's width and height, 
then convert that, and round it
+                * back up to get the level 0 size.
+                * Clamp the converted size between the original values, and 
next power of two, which
+                * means we don't oversize the image.
+                */
+                if (device->physical_device->rad_info.chip_class >= GFX9 &&
+                    vk_format_is_compressed(image->vk_format) &&
+                    !vk_format_is_compressed(iview->vk_format)) {
+                        unsigned rounded_img_w = 
util_next_power_of_two(iview->extent.width);
+                        unsigned rounded_img_h = 
util_next_power_of_two(iview->extent.height);
+                        unsigned lvl_width  = radv_minify(image->info.width , 
range->baseMipLevel);
+                        unsigned lvl_height = radv_minify(image->info.height, 
range->baseMipLevel);
+
+                        lvl_width = round_up_u32(lvl_width * view_bw, img_bw);
+                        lvl_height = round_up_u32(lvl_height * view_bh, 
img_bh);
+
+                        lvl_width <<= range->baseMipLevel;
+                        lvl_height <<= range->baseMipLevel;
+
+                        iview->extent.width = CLAMP(lvl_width, 
iview->extent.width, rounded_img_w);
+                        iview->extent.height = CLAMP(lvl_height, 
iview->extent.height, rounded_img_h);
+                }
        }
 
        iview->base_layer = range->baseArrayLayer;
-- 
2.14.3

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to