From 636a7cf84b78db7f92b396b4cbe1e15e3689cb66 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Sat, 1 May 2021 22:45:30 -0700 Subject: [PATCH] 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 Signed-off-by: Vasily Khoruzhick Part-of: --- src/gallium/drivers/lima/lima_resource.c | 75 +++++++++++++++++++++--- src/gallium/drivers/lima/lima_resource.h | 3 + 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/gallium/drivers/lima/lima_resource.c b/src/gallium/drivers/lima/lima_resource.c index d16a0b0b731..4e0c8d3460c 100644 --- a/src/gallium/drivers/lima/lima_resource.c +++ b/src/gallium/drivers/lima/lima_resource.c @@ -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); + } } } } diff --git a/src/gallium/drivers/lima/lima_resource.h b/src/gallium/drivers/lima/lima_resource.h index 36ea605c6b0..91443e540b5 100644 --- a/src/gallium/drivers/lima/lima_resource.h +++ b/src/gallium/drivers/lima/lima_resource.h @@ -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]; };