freedreno/fdl: avoid overflow in layout size computations

When computing layout for large extents and array size, the computations
can overflow the 32-bit variables holding these values. This can end up
underreporting memory requirements for a given resource, making the
application think that such a resource is allocatable.

The size-holding variables in the fdl_layout struct have their type
upgraded to uint64_t, as does the total size variable in tu_image. This
avoids problems in corner-case tests in the Vulkan CTS, but this code
should be improved further to avoid overflows and narrowing conversions.

Fixes a quartet of tests under
dEQP-VK.pipeline.monolithic.render_to_image.core.2d_array.huge.width_height_layers.

Signed-off-by: Zan Dobersek <zdobersek@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28050>
This commit is contained in:
Zan Dobersek 2024-03-07 17:04:05 +01:00 committed by Marge Bot
parent be4a6b946a
commit 1e27138588
5 changed files with 9 additions and 8 deletions

View file

@ -104,7 +104,7 @@ fdl5_layout(struct fdl_layout *layout, enum pipe_format format,
}
if (layout->layer_first) {
layout->layer_size = align(layout->size, 4096);
layout->layer_size = align64(layout->size, 4096);
layout->size = layout->layer_size * array_size;
}
}

View file

@ -273,7 +273,7 @@ fdl6_layout(struct fdl_layout *layout, enum pipe_format format,
if (layout->ubwc) {
/* with UBWC every level is aligned to 4K */
layout->size = align(layout->size, 4096);
layout->size = align64(layout->size, 4096);
uint32_t meta_pitch = fdl_ubwc_pitch(layout, level);
uint32_t meta_height =
@ -287,7 +287,7 @@ fdl6_layout(struct fdl_layout *layout, enum pipe_format format,
}
if (layout->layer_first) {
layout->layer_size = align(layout->size, 4096);
layout->layer_size = align64(layout->size, 4096);
layout->size = layout->layer_size * array_size;
}

View file

@ -25,6 +25,7 @@
* Rob Clark <robclark@freedesktop.org>
*/
#include <inttypes.h>
#include <stdio.h>
#include "freedreno_layout.h"
@ -65,7 +66,7 @@ fdl_dump_layout(struct fdl_layout *layout)
fprintf(
stderr,
"%s: %ux%ux%u@%ux%u:\t%2u: stride=%4u, size=%6u,%6u, "
"aligned_height=%3u, offset=0x%x,0x%x, layersz %5u,%5u %s\n",
"aligned_height=%3u, offset=0x%x,0x%x, layersz %5" PRIu64 ",%5" PRIu64 " %s\n",
util_format_name(layout->format), u_minify(layout->width0, level),
u_minify(layout->height0, level), u_minify(layout->depth0, level),
layout->cpp, layout->nr_samples, level, fdl_pitch(layout, level),

View file

@ -113,8 +113,8 @@ struct fdl_layout {
struct fdl_slice ubwc_slices[FDL_MAX_MIP_LEVELS];
uint32_t pitch0;
uint32_t ubwc_width0;
uint32_t layer_size;
uint32_t ubwc_layer_size; /* in bytes */
uint64_t layer_size;
uint64_t ubwc_layer_size; /* in bytes */
bool ubwc : 1;
bool layer_first : 1; /* see above description */
bool tile_all : 1;
@ -143,7 +143,7 @@ struct fdl_layout {
uint32_t nr_samples;
enum pipe_format format;
uint32_t size; /* Size of the whole image, in bytes. */
uint64_t size; /* Size of the whole image, in bytes. */
uint32_t base_align; /* Alignment of the base address, in bytes. */
uint8_t pitchalign; /* log2(pitchalign) */
};

View file

@ -23,7 +23,7 @@ struct tu_image
struct vk_image vk;
struct fdl_layout layout[3];
uint32_t total_size;
uint64_t total_size;
#if DETECT_OS_ANDROID
/* For VK_ANDROID_native_buffer, the WSI image owns the memory, */