Module: Mesa
Branch: staging/22.2
Commit: 1a79d5e86199e397175d2334fc0375c058be24f3
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=1a79d5e86199e397175d2334fc0375c058be24f3

Author: Lucas Stach <[email protected]>
Date:   Wed Aug 24 16:26:52 2022 +0200

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: 53445284a42 ("etnaviv: add linear PE support")
Signed-off-by: Lucas Stach <[email protected]>
Tested-by: Guido Günther <[email protected]>
Reviewed-by: Guido Günther <[email protected]>
Reviewed-by: Philipp Zabel <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18232>
(cherry picked from commit ea8fc9592c16ce137d58a27be8f30f530efcc524)

Conflicts:
        src/gallium/drivers/etnaviv/etnaviv_surface.c

---

 .pick_status.json                              |  2 +-
 src/gallium/drivers/etnaviv/etnaviv_resource.c |  4 +++-
 src/gallium/drivers/etnaviv/etnaviv_surface.c  | 17 +++++++++++------
 3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/.pick_status.json b/.pick_status.json
index b84d7091e77..49e8badc1b6 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -10345,7 +10345,7 @@
         "description": "etnaviv: use linear PE rendering only on properly 
aligned surfaces",
         "nominated": true,
         "nomination_type": 1,
-        "resolution": 0,
+        "resolution": 1,
         "main_sha": null,
         "because_sha": "53445284a427f79e94607dc4ca2f8bd8ac293356"
     },
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c 
b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index 6ad02dda152..7fc07a7e414 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -101,7 +101,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;
 
    ts_layer_stride = align(DIV_ROUND_UP(rsc->levels[0].layer_stride,
diff --git a/src/gallium/drivers/etnaviv/etnaviv_surface.c 
b/src/gallium/drivers/etnaviv/etnaviv_surface.c
index fa2d152ee5a..bdcf099e087 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_surface.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_surface.c
@@ -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,16 +86,16 @@ 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 < rsc->base.array_size);
+   assert(layer <= util_max_layer(prsc, level));
 
    surf->base.context = pctx;
 

Reply via email to