etnaviv: use linear PE rendering only on properly aligned surfaces

When linear rendering is used together with TS, the color tiles must be fully
contained in a single row of pixels. When wrapping around to the next row
TS gets confused and records wrong tile status information, leading to visual
corruption when the surface is resolved/decompressed.

The corruption can be fixed by increasing the stride alignment for linear
render targets, but that would break some existing use-cases, as some display
engines used together with Vivante GPUs currently don't support strides that
don't match the horizontal display resolution.

For now only enable linear PE rendering when the surface is properly aligned
already. This allows to use the optimization in a lot of common use-cases, but
falls back to the proven tiled rendering with subsequent resolve into linear
for the problematic cases.

CC: mesa-stable #22.2
Fixes: 53445284a4 ("etnaviv: add linear PE support")
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Tested-by: Guido Günther <agx@sigxcpu.org>
Reviewed-by: Guido Günther <agx@sigxcpu.org>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18232>
This commit is contained in:
Lucas Stach
2022-08-24 16:26:52 +02:00
committed by Marge Bot
parent 09953d7b75
commit ea8fc9592c
2 changed files with 13 additions and 6 deletions

View File

@@ -103,7 +103,9 @@ etna_screen_resource_alloc_ts(struct pipe_screen *pscreen,
* the size of the resource might also determine if we want to use it or not
*/
if (VIV_FEATURE(screen, chipMinorFeatures6, CACHE128B256BPERLINE) &&
ts_compress_fmt >= 0)
ts_compress_fmt >= 0 &&
(rsc->layout != ETNA_LAYOUT_LINEAR ||
rsc->levels[0].stride % 256 == 0) )
ts_mode = TS_MODE_256B;
layers = prsc->target == PIPE_TEXTURE_3D ? prsc->depth0 : prsc->array_size;

View File

@@ -41,19 +41,24 @@
#include "drm-uapi/drm_fourcc.h"
static struct etna_resource *
etna_render_handle_incompatible(struct pipe_context *pctx, struct pipe_resource *prsc)
etna_render_handle_incompatible(struct pipe_context *pctx,
struct pipe_resource *prsc,
unsigned int level)
{
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);
/* 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, chipMinorFeatures2, LINEAR_PE)) &&
(VIV_FEATURE(screen, chipMinorFeatures2, LINEAR_PE) &&
(!VIV_FEATURE(screen, chipFeatures, FAST_CLEAR) ||
res->levels[level].stride % min_tilesize == 0))) &&
(!need_multitiled || (res->layout & ETNA_LAYOUT_BIT_MULTI)))
return res;
@@ -81,15 +86,15 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc,
{
struct etna_context *ctx = etna_context(pctx);
struct etna_screen *screen = ctx->screen;
struct etna_resource *rsc = etna_render_handle_incompatible(pctx, prsc);
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_surface *surf = CALLOC_STRUCT(etna_surface);
if (!surf)
return NULL;
assert(templat->u.tex.first_layer == templat->u.tex.last_layer);
unsigned layer = templat->u.tex.first_layer;
unsigned level = templat->u.tex.level;
assert(layer <= util_max_layer(prsc, level));
surf->base.context = pctx;