From 29999e6b9d737cdab9510246bc5f780791f7c9dc Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Wed, 21 Oct 2020 03:35:26 +0200 Subject: [PATCH] radv: Fix 1D compressed mipmaps on GFX9. Partial rollback as GFX9 really requires height = 1 to work. The two substantial parts of the fix remaining: 1) Deal with views with multiple levels. 2) Limit the expansion to the base mip pitch/height. On GFX9 this is exactly equal to the surf_pitch that was used before. I've done some investigation to make sure that on GFX10 this always results in the right physical layout. Remaining stupid question is how the actual extents for bounds checking never end up too low when the size gets clamped, but this change and the previous change don't change that ... Fixes: 1fb3e1fb708 "radv: Fix mipmap extent adjustment on GFX9+." Reviewed-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/radv_image.c | 51 ++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c index ebd74d0f157..c9470e15a11 100644 --- a/src/amd/vulkan/radv_image.c +++ b/src/amd/vulkan/radv_image.c @@ -1600,6 +1600,11 @@ radv_image_view_init(struct radv_image_view *iview, iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask; iview->multiple_planes = vk_format_get_plane_count(image->vk_format) > 1 && iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT; + iview->base_layer = range->baseArrayLayer; + iview->layer_count = radv_get_layerCount(image, range); + iview->base_mip = range->baseMipLevel; + iview->level_count = radv_get_levelCount(image, range); + iview->vk_format = pCreateInfo->format; /* If the image has an Android external format, pCreateInfo->format will be @@ -1655,21 +1660,43 @@ radv_image_view_init(struct radv_image_view *iview, * * This means that mip2 will be missing texels. * - * Fix it by taking the actual extent addrlib assigned to the base mip level. + * 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 the physical extent + * of the base mipmap. + * + * On GFX10 we have to take care to not go over the physical extent + * of the base mipmap as otherwise the GPU computes a different layout. + * Note that the GPU does use the same base-mip dimensions for both a + * block compatible format and the compressed format, so even if we take + * the plain converted dimensions the physical layout is correct. */ if (device->physical_device->rad_info.chip_class >= GFX9 && - vk_format_is_compressed(image->vk_format) && - !vk_format_is_compressed(iview->vk_format) && - iview->image->info.levels > 1) { - iview->extent.width = iview->image->planes[0].surface.u.gfx9.base_mip_width; - iview->extent.height = iview->image->planes[0].surface.u.gfx9.base_mip_height; - } - } + vk_format_is_compressed(image->vk_format) && + !vk_format_is_compressed(iview->vk_format)) { + /* If we have multiple levels in the view we should ideally take the last level, + * but the mip calculation has a max(..., 1) so walking back to the base mip in an + * useful way is hard. */ + if (iview->level_count > 1) { + iview->extent.width = iview->image->planes[0].surface.u.gfx9.base_mip_width; + iview->extent.height = iview->image->planes[0].surface.u.gfx9.base_mip_height; + } else { + unsigned lvl_width = radv_minify(image->info.width , range->baseMipLevel); + unsigned lvl_height = radv_minify(image->info.height, range->baseMipLevel); - iview->base_layer = range->baseArrayLayer; - iview->layer_count = radv_get_layerCount(image, range); - iview->base_mip = range->baseMipLevel; - iview->level_count = radv_get_levelCount(image, range); + 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, + iview->image->planes[0].surface.u.gfx9.base_mip_width); + iview->extent.height = CLAMP(lvl_height, iview->extent.height, + iview->image->planes[0].surface.u.gfx9.base_mip_height); + } + } + } bool disable_compression = extra_create_info ? extra_create_info->disable_compression: false; for (unsigned i = 0; i < (iview->multiple_planes ? vk_format_get_plane_count(image->vk_format) : 1); ++i) {