Module: Mesa Branch: main Commit: 2a3aa6da5038e50a34f22d986fb36870024fd57e URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=2a3aa6da5038e50a34f22d986fb36870024fd57e
Author: Karmjit Mahil <[email protected]> Date: Tue Sep 19 17:08:41 2023 +0100 pvr: Fix cubemap layer stride The hw calculates the layer stride with the assumption of a full mip chain being there even though certain levels might never be used. Fix the `layer_size` by accounting for any missing mip levels. Fixes: 8991e6464 ("pvr: Add a Vulkan driver for Imagination Technologies PowerVR Rogue GPUs") Reported-by: James Glanville <[email protected]> Signed-off-by: Karmjit Mahil <[email protected]> Reviewed-by: Frank Binns <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25344> --- src/imagination/vulkan/pvr_image.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/imagination/vulkan/pvr_image.c b/src/imagination/vulkan/pvr_image.c index 88c4bed45fb..c21544182da 100644 --- a/src/imagination/vulkan/pvr_image.c +++ b/src/imagination/vulkan/pvr_image.c @@ -98,20 +98,36 @@ static void pvr_image_setup_mip_levels(struct pvr_image *image) image->layer_size = 0; for (uint32_t i = 0; i < image->vk.mip_levels; i++) { - const uint32_t height = u_minify(extent.height, i); - const uint32_t width = u_minify(extent.width, i); - const uint32_t depth = u_minify(extent.depth, i); struct pvr_mip_level *mip_level = &image->mip_levels[i]; - mip_level->pitch = cpp * ALIGN(width, extent_alignment); - mip_level->height_pitch = ALIGN(height, extent_alignment); + mip_level->pitch = cpp * ALIGN(extent.width, extent_alignment); + mip_level->height_pitch = ALIGN(extent.height, extent_alignment); mip_level->size = image->vk.samples * mip_level->pitch * mip_level->height_pitch * - ALIGN(depth, extent_alignment); + ALIGN(extent.depth, extent_alignment); mip_level->size = ALIGN(mip_level->size, level_alignment); mip_level->offset = image->layer_size; image->layer_size += mip_level->size; + + extent.height = u_minify(extent.height, 1); + extent.width = u_minify(extent.width, 1); + extent.depth = u_minify(extent.depth, 1); + } + + /* The hw calculates layer strides as if a full mip chain up until 1x1x1 + * were present so we need to account for that in the `layer_size`. + */ + while (extent.height != 1 || extent.width != 1 || extent.depth != 1) { + const uint32_t height_pitch = ALIGN(extent.height, extent_alignment); + const uint32_t pitch = cpp * ALIGN(extent.width, extent_alignment); + + image->layer_size += image->vk.samples * pitch * height_pitch * + ALIGN(extent.depth, extent_alignment); + + extent.height = u_minify(extent.height, 1); + extent.width = u_minify(extent.width, 1); + extent.depth = u_minify(extent.depth, 1); } /* TODO: It might be useful to store the alignment in the image so it can be
