llvmpipe: allow calculating size of overly large texture

We need this for Lavapipe; we shouldn't fail to create an vkImage that
is too large, we should instead fail to allocate memory for it.

Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10689>
This commit is contained in:
Erik Faye-Lund 2021-05-07 13:04:00 +02:00 committed by Marge Bot
parent e10618f6f5
commit 1a099cb90b
2 changed files with 13 additions and 22 deletions

View File

@ -126,13 +126,7 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
else else
lpr->row_stride[level] = align(nblocksx * block_size, util_get_cpu_caps()->cacheline); lpr->row_stride[level] = align(nblocksx * block_size, util_get_cpu_caps()->cacheline);
/* if row_stride * height > LP_MAX_TEXTURE_SIZE */ lpr->img_stride[level] = (uint64_t)lpr->row_stride[level] * nblocksy;
if ((uint64_t)lpr->row_stride[level] * nblocksy > LP_MAX_TEXTURE_SIZE) {
/* image too large */
goto fail;
}
lpr->img_stride[level] = lpr->row_stride[level] * nblocksy;
/* Number of 3D image slices, cube faces or texture array layers */ /* Number of 3D image slices, cube faces or texture array layers */
if (lpr->base.target == PIPE_TEXTURE_CUBE) { if (lpr->base.target == PIPE_TEXTURE_CUBE) {
@ -149,19 +143,10 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
else else
num_slices = 1; num_slices = 1;
/* if img_stride * num_slices_faces > LP_MAX_TEXTURE_SIZE */ mipsize = lpr->img_stride[level] * num_slices;
mipsize = (uint64_t)lpr->img_stride[level] * num_slices;
if (mipsize > LP_MAX_TEXTURE_SIZE) {
/* volume too large */
goto fail;
}
lpr->mip_offsets[level] = total_size; lpr->mip_offsets[level] = total_size;
total_size += align((unsigned)mipsize, mip_align); total_size += align64(mipsize, mip_align);
if (total_size > LP_MAX_TEXTURE_SIZE) {
goto fail;
}
/* Compute size of next mipmap level */ /* Compute size of next mipmap level */
width = u_minify(width, 1); width = u_minify(width, 1);
@ -174,6 +159,9 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen,
lpr->size_required = total_size; lpr->size_required = total_size;
if (allocate) { if (allocate) {
if (total_size > LP_MAX_TEXTURE_SIZE)
goto fail;
lpr->tex_data = align_malloc(total_size, mip_align); lpr->tex_data = align_malloc(total_size, mip_align);
if (!lpr->tex_data) { if (!lpr->tex_data) {
return FALSE; return FALSE;
@ -201,7 +189,10 @@ llvmpipe_can_create_resource(struct pipe_screen *screen,
struct llvmpipe_resource lpr; struct llvmpipe_resource lpr;
memset(&lpr, 0, sizeof(lpr)); memset(&lpr, 0, sizeof(lpr));
lpr.base = *res; lpr.base = *res;
return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false); if (!llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false))
return false;
return lpr.size_required <= LP_MAX_TEXTURE_SIZE;
} }

View File

@ -63,11 +63,11 @@ struct llvmpipe_resource
/** Row stride in bytes */ /** Row stride in bytes */
unsigned row_stride[LP_MAX_TEXTURE_LEVELS]; unsigned row_stride[LP_MAX_TEXTURE_LEVELS];
/** Image stride (for cube maps, array or 3D textures) in bytes */ /** Image stride (for cube maps, array or 3D textures) in bytes */
unsigned img_stride[LP_MAX_TEXTURE_LEVELS]; uint64_t img_stride[LP_MAX_TEXTURE_LEVELS];
/** Offset to start of mipmap level, in bytes */ /** Offset to start of mipmap level, in bytes */
unsigned mip_offsets[LP_MAX_TEXTURE_LEVELS]; uint64_t mip_offsets[LP_MAX_TEXTURE_LEVELS];
/** allocated total size (for non-display target texture resources only) */ /** allocated total size (for non-display target texture resources only) */
unsigned total_alloc_size; uint64_t total_alloc_size;
/** /**
* Display target, for textures with the PIPE_BIND_DISPLAY_TARGET * Display target, for textures with the PIPE_BIND_DISPLAY_TARGET