lima: switch resource to linear layout if there's to many full updates

Overwriting entire resource multiple times indicates streaming and in this
case it's more efficient to use linear layout to avoid expensive linear->tiled
conversions.

Reviewed-by: Erico Nunes <nunes.erico@gmail.com>
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10572>
This commit is contained in:
Vasily Khoruzhick 2021-05-01 22:45:30 -07:00 committed by Marge Bot
parent d6356b81a4
commit 636a7cf84b
2 changed files with 69 additions and 9 deletions

View file

@ -322,6 +322,8 @@ lima_resource_from_handle(struct pipe_screen *pscreen,
return NULL;
}
res->modifier_constant = true;
switch (handle->modifier) {
case DRM_FORMAT_MOD_LINEAR:
res->tiled = false;
@ -412,6 +414,8 @@ lima_resource_get_handle(struct pipe_screen *pscreen,
else
handle->modifier = DRM_FORMAT_MOD_LINEAR;
res->modifier_constant = true;
if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro &&
renderonly_get_handle(res->scanout, handle))
return true;
@ -686,6 +690,38 @@ lima_transfer_flush_region(struct pipe_context *pctx,
}
static bool
lima_should_convert_linear(struct lima_resource *res,
struct pipe_transfer *ptrans)
{
if (res->modifier_constant)
return false;
/* Overwriting the entire resource indicates streaming, for which
* linear layout is most efficient due to the lack of expensive
* conversion.
*
* For now we just switch to linear after a number of complete
* overwrites to keep things simple, but we could do better.
*/
unsigned depth = res->base.target == PIPE_TEXTURE_3D ?
res->base.depth0 : res->base.array_size;
bool entire_overwrite =
res->base.last_level == 0 &&
ptrans->box.width == res->base.width0 &&
ptrans->box.height == res->base.height0 &&
ptrans->box.depth == depth &&
ptrans->box.x == 0 &&
ptrans->box.y == 0 &&
ptrans->box.z == 0;
if (entire_overwrite)
++res->full_updates;
return res->full_updates >= LAYOUT_CONVERT_THRESHOLD;
}
static void
lima_transfer_unmap_inner(struct lima_context *ctx,
struct pipe_transfer *ptrans)
@ -699,15 +735,36 @@ lima_transfer_unmap_inner(struct lima_context *ctx,
pres = &res->base;
if (trans->base.usage & PIPE_MAP_WRITE) {
unsigned i;
for (i = 0; i < trans->base.box.depth; i++)
panfrost_store_tiled_image(
bo->map + res->levels[trans->base.level].offset + (i + trans->base.box.z) * res->levels[trans->base.level].layer_stride,
trans->staging + i * ptrans->stride * ptrans->box.height,
ptrans->box.x, ptrans->box.y,
ptrans->box.width, ptrans->box.height,
res->levels[ptrans->level].stride,
ptrans->stride,
pres->format);
if (lima_should_convert_linear(res, ptrans)) {
/* It's safe to re-use the same BO since tiled BO always has
* aligned dimensions */
for (i = 0; i < trans->base.box.depth; i++) {
util_copy_rect(bo->map + res->levels[0].offset +
(i + trans->base.box.z) * res->levels[0].stride,
res->base.format,
res->levels[0].stride,
0, 0,
ptrans->box.width,
ptrans->box.height,
trans->staging + i * ptrans->stride * ptrans->box.height,
ptrans->stride,
0, 0);
}
res->tiled = false;
res->modifier_constant = true;
/* Update texture descriptor */
ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
} else {
for (i = 0; i < trans->base.box.depth; i++)
panfrost_store_tiled_image(
bo->map + res->levels[trans->base.level].offset + (i + trans->base.box.z) * res->levels[trans->base.level].layer_stride,
trans->staging + i * ptrans->stride * ptrans->box.height,
ptrans->box.x, ptrans->box.y,
ptrans->box.width, ptrans->box.height,
res->levels[ptrans->level].stride,
ptrans->stride,
pres->format);
}
}
}
}

View file

@ -29,6 +29,7 @@
/* max texture size is 4096x4096 */
#define LIMA_MAX_MIP_LEVELS 13
#define LAYOUT_CONVERT_THRESHOLD 8
struct lima_screen;
struct panfrost_minmax_cache;
@ -55,6 +56,8 @@ struct lima_resource {
struct lima_bo *bo;
struct panfrost_minmax_cache *index_cache;
bool tiled;
bool modifier_constant;
unsigned full_updates;
struct lima_resource_level levels[LIMA_MAX_MIP_LEVELS];
};