From 83ab7a8d58c46067de7ddf953dd2f4da4048cdf0 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 11 Apr 2025 22:42:36 +0200 Subject: [PATCH] etnaviv: add resource render compatible check Untangle the convoluted render compatible check from etna_render_handle_incompatible to make it easier to read and move it into a separate function so it can be reused from other callers. As this is intended to be called also at resource creation time, where we don't know the exact level of the resource that might be rendered to, the stride check for linear resources is made a bit more conservative by checking that the last level (the one with the smallest stride) still meets the render target stride alignment requirement. Signed-off-by: Lucas Stach Reviewed-by: Christian Gmeiner Part-of: --- .../drivers/etnaviv/etnaviv_resource.c | 26 +++++++++++++++++++ .../drivers/etnaviv/etnaviv_resource.h | 4 +++ src/gallium/drivers/etnaviv/etnaviv_surface.c | 16 +++--------- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c index a36e727abc8..7ebe1dab6f3 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c @@ -81,6 +81,32 @@ static uint64_t etna_resource_modifier(struct etna_resource *rsc) return layout_to_modifier(rsc->layout); } +bool +etna_resource_is_render_compatible(struct pipe_screen *pscreen, + struct etna_resource *rsc) +{ + struct etna_screen *screen = etna_screen(pscreen); + + if (rsc->layout == ETNA_LAYOUT_LINEAR) { + if (!VIV_FEATURE(screen, ETNA_FEATURE_LINEAR_PE)) + return false; + + if (VIV_FEATURE(screen, ETNA_FEATURE_FAST_CLEAR)) { + unsigned int min_tilesize = etna_screen_get_tile_size(screen, TS_MODE_128B, + rsc->base.nr_samples > 1); + + if (rsc->levels[rsc->base.last_level].stride % min_tilesize != 0) + return false; + } + } + + if (screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer && + !(rsc->layout & ETNA_LAYOUT_BIT_MULTI)) + return false; + + return true; +} + /* A tile is either 64 bytes or, when the GPU has the CACHE128B256BPERLINE * feature, 128/256 bytes of color/depth data, tracked by * 'screen->specs.bits_per_tile' bits of tile status. diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h index c29e019362d..b2721d0ed40 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.h +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h @@ -281,6 +281,10 @@ etna_resource_hw_tileable(bool use_blt, const struct pipe_resource *pres) util_format_get_blocksize(pres->format) == 4; } +bool +etna_resource_is_render_compatible(struct pipe_screen *pscreen, + struct etna_resource *rsc); + /* returns TRUE if resource TS buffer is exposed externally */ static inline bool etna_resource_ext_ts(const struct etna_resource *res) diff --git a/src/gallium/drivers/etnaviv/etnaviv_surface.c b/src/gallium/drivers/etnaviv/etnaviv_surface.c index 321407f767b..cb27c8cfd27 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_surface.c +++ b/src/gallium/drivers/etnaviv/etnaviv_surface.c @@ -40,25 +40,15 @@ static struct etna_resource * etna_render_handle_incompatible(struct pipe_context *pctx, - struct pipe_resource *prsc, - unsigned int level) + struct pipe_resource *prsc) { struct etna_context *ctx = etna_context(pctx); struct etna_screen *screen = ctx->screen; struct etna_resource *res = etna_resource(prsc); bool need_multitiled = screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer; bool want_supertiled = screen->specs.can_supertile; - unsigned int min_tilesize = etna_screen_get_tile_size(screen, TS_MODE_128B, - prsc->nr_samples > 1); - /* Resource is compatible if it is tiled or PE is able to render to linear - * and has multi tiling when required. - */ - if ((res->layout != ETNA_LAYOUT_LINEAR || - (VIV_FEATURE(screen, ETNA_FEATURE_LINEAR_PE) && - (!VIV_FEATURE(screen, ETNA_FEATURE_FAST_CLEAR) || - res->levels[level].stride % min_tilesize == 0))) && - (!need_multitiled || (res->layout & ETNA_LAYOUT_BIT_MULTI))) + if (etna_resource_is_render_compatible(pctx->screen, res)) return res; if (!res->render) { @@ -87,7 +77,7 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc, struct etna_screen *screen = ctx->screen; unsigned layer = templat->u.tex.first_layer; unsigned level = templat->u.tex.level; - struct etna_resource *rsc = etna_render_handle_incompatible(pctx, prsc, level); + struct etna_resource *rsc = etna_render_handle_incompatible(pctx, prsc); struct etna_resource_level *lev = &rsc->levels[level]; struct etna_surface *surf = CALLOC_STRUCT(etna_surface);