From 4226be0c750eed6c247a9298ee3124db8ca0e4c7 Mon Sep 17 00:00:00 2001 From: "Juan A. Suarez Romero" Date: Tue, 17 Dec 2024 23:10:54 +0100 Subject: [PATCH] vc4: ensure sharing tiled resources are of proper format When creating a tiled resource, it could be created either with "T" or "LT" format. But when sharing the resource, only "T" format is appropiate. So we need to perform a conversion if required. This is based on https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32661. Reviewed-by: Jose Maria Casanova Crespo Signed-off-by: Juan A. Suarez Romero Part-of: --- src/gallium/drivers/vc4/vc4_resource.c | 69 +++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c index 8c289d28155..6021fc038ee 100644 --- a/src/gallium/drivers/vc4/vc4_resource.c +++ b/src/gallium/drivers/vc4/vc4_resource.c @@ -294,10 +294,12 @@ vc4_resource_destroy(struct pipe_screen *pscreen, static uint64_t vc4_resource_modifier(struct vc4_resource *rsc) { - if (rsc->tiled) + if (rsc->tiled) { + assert(rsc->slices[0].tiling == VC4_TILING_FORMAT_T); return DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED; - else + } else { return DRM_FORMAT_MOD_LINEAR; + } } static bool @@ -376,7 +378,8 @@ vc4_resource_get_param(struct pipe_screen *pscreen, } static void -vc4_setup_slices(struct vc4_resource *rsc, const char *caller) +vc4_setup_slices(struct vc4_resource *rsc, const char *caller, + bool force_format_t) { struct pipe_resource *prsc = &rsc->base; uint32_t width = prsc->width0; @@ -414,7 +417,8 @@ vc4_setup_slices(struct vc4_resource *rsc, const char *caller) level_width = align(level_width, utile_w); } } else { - if (vc4_size_is_lt(level_width, level_height, + if (!force_format_t && + vc4_size_is_lt(level_width, level_height, rsc->cpp)) { slice->tiling = VC4_TILING_FORMAT_LT; level_width = align(level_width, utile_w); @@ -581,7 +585,7 @@ vc4_resource_create_with_modifiers(struct pipe_screen *pscreen, if (tmpl->target != PIPE_BUFFER) rsc->vc4_format = get_resource_texture_format(prsc); - vc4_setup_slices(rsc, "create"); + vc4_setup_slices(rsc, "create", tmpl->bind & PIPE_BIND_SHARED); if (!vc4_resource_bo_alloc(rsc)) goto fail; @@ -696,7 +700,7 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, } rsc->vc4_format = get_resource_texture_format(prsc); - vc4_setup_slices(rsc, "import"); + vc4_setup_slices(rsc, "import", true); if (whandle->offset != 0) { if (rsc->tiled) { @@ -1027,11 +1031,60 @@ vc4_dump_surface(struct pipe_surface *psurf) } static void -vc4_flush_resource(struct pipe_context *pctx, struct pipe_resource *resource) +vc4_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc) { /* All calls to flush_resource are followed by a flush of the context, - * so there's nothing to do. + * so there's nothing to do. Still, if the resource is going to be + * shared and it is tiled, only T format is valid, so we need to + * convert it. */ + struct vc4_resource *rsc = vc4_resource(prsc); + struct vc4_screen *screen = vc4_screen(prsc->screen); + if (rsc->tiled && + (rsc->slices[0].tiling != VC4_TILING_FORMAT_T || + !screen->has_tiling_ioctl)) { + /* Shared resources must be not mipmapped */ + assert(prsc->last_level == 0); + /* Shared resources must not be multisampled */ + assert(prsc->nr_samples <= 1); + + struct pipe_resource ptmpl = *prsc; + ptmpl.bind |= PIPE_BIND_SHARED; + struct vc4_resource *new_rsc = + vc4_resource(pctx->screen->resource_create(pctx->screen, + &ptmpl)); + assert(new_rsc); + + struct pipe_blit_info blit = { 0 }; + u_box_3d(0, 0, 0, + prsc->width0, prsc->height0, prsc->depth0, + &blit.dst.box); + blit.src.box = blit.dst.box; + blit.dst.resource = &new_rsc->base; + blit.dst.format = new_rsc->base.format; + blit.dst.level = 0; + blit.src.resource = prsc; + blit.src.format = prsc->format; + blit.src.level = 0; + blit.mask = util_format_get_mask(blit.src.format); + blit.filter = PIPE_TEX_FILTER_NEAREST; + + vc4_blit(pctx, &blit); + + rsc->base.bind = new_rsc->base.bind; + /* Swap the BOs */ + struct vc4_bo *old_bo = rsc->bo; + rsc->bo = new_rsc->bo; + new_rsc->bo = old_bo; + + /* Copy the affected fields */ + rsc->slices[0] = new_rsc->slices[0]; + rsc->cube_map_stride = new_rsc->cube_map_stride; + rsc->tiled = new_rsc->tiled; + + struct pipe_resource *new_prsc = (struct pipe_resource *)&new_rsc; + pipe_resource_reference(&new_prsc, NULL); + } } void