freedreno/a6xx: Fix uncompressed resource vs stale CSO
authorRob Clark <robdclark@chromium.org>
Sun, 28 Feb 2021 19:06:13 +0000 (11:06 -0800)
committerMarge Bot <eric+marge@anholt.net>
Mon, 1 Mar 2021 20:01:07 +0000 (20:01 +0000)
A sequence like:

1) create sampler view CSO with UBWC resource
2) later create another sampler view or image view with the same
   resource, but a format that triggers demoting the resource to
   uncompressed
3) bind CSO created in step #1

would not work correctly, because the CSO created in step #1 is still
setup for UBWC, despite the fact that the resource had been demoted to
uncompressed.

Fortunately this is easy enough to detect, as the resource's seqno would
have been updated.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9321>

src/gallium/drivers/freedreno/a6xx/fd6_emit.c
src/gallium/drivers/freedreno/a6xx/fd6_texture.c
src/gallium/drivers/freedreno/a6xx/fd6_texture.h

index bef2841..87938e3 100644 (file)
@@ -390,9 +390,18 @@ fd6_emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring,
                struct fd_ringbuffer *state =
                        fd_ringbuffer_new_object(ctx->pipe, num_merged_textures * 16 * 4);
                for (unsigned i = 0; i < num_textures; i++) {
-                       static const struct fd6_pipe_sampler_view dummy_view = {};
-                       const struct fd6_pipe_sampler_view *view = tex->textures[i] ?
-                               fd6_pipe_sampler_view(tex->textures[i]) : &dummy_view;
+                       const struct fd6_pipe_sampler_view *view;
+
+                       if (tex->textures[i]) {
+                               view = fd6_pipe_sampler_view(tex->textures[i]);
+                               if (unlikely(view->rsc_seqno != view->ptr1->seqno)) {
+                                       fd6_sampler_view_update(ctx,
+                                                       fd6_pipe_sampler_view(tex->textures[i]));
+                               }
+                       } else {
+                               static const struct fd6_pipe_sampler_view dummy_view = {};
+                               view = &dummy_view;
+                       }
 
                        OUT_RING(state, view->texconst0);
                        OUT_RING(state, view->texconst1);
index c417ee3..f51d000 100644 (file)
@@ -161,27 +161,41 @@ fd6_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
 {
        struct fd6_pipe_sampler_view *so = CALLOC_STRUCT(fd6_pipe_sampler_view);
        struct fd_resource *rsc = fd_resource(prsc);
-       enum pipe_format format = cso->format;
-       bool ubwc_enabled = false;
-       unsigned lvl, layers = 0;
 
        if (!so)
                return NULL;
 
-       fd6_validate_format(fd_context(pctx), rsc, format);
-
-       if (format == PIPE_FORMAT_X32_S8X24_UINT) {
-               rsc = rsc->stencil;
-               format = rsc->base.format;
-       }
+       fd6_validate_format(fd_context(pctx), rsc, cso->format);
 
        so->base = *cso;
        pipe_reference(NULL, &prsc->reference);
        so->base.texture = prsc;
        so->base.reference.count = 1;
        so->base.context = pctx;
-       so->seqno = ++fd6_context(fd_context(pctx))->tex_seqno;
+
+       fd6_sampler_view_update(fd_context(pctx), so);
+
+       return &so->base;
+}
+
+void
+fd6_sampler_view_update(struct fd_context *ctx, struct fd6_pipe_sampler_view *so)
+{
+       const struct pipe_sampler_view *cso = &so->base;
+       struct pipe_resource *prsc = cso->texture;
+       struct fd_resource *rsc = fd_resource(prsc);
+       enum pipe_format format = cso->format;
+       bool ubwc_enabled = false;
+       unsigned lvl, layers = 0;
+
+       if (format == PIPE_FORMAT_X32_S8X24_UINT) {
+               rsc = rsc->stencil;
+               format = rsc->base.format;
+       }
+
+       so->seqno = ++fd6_context(ctx)->tex_seqno;
        so->ptr1 = rsc;
+       so->rsc_seqno = so->ptr1->seqno;
 
        if (cso->target == PIPE_BUFFER) {
                unsigned elements = cso->u.buf.size / util_format_get_blocksize(format);
@@ -297,8 +311,6 @@ fd6_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
                        A6XX_TEX_CONST_10_FLAG_BUFFER_LOGW(util_logbase2_ceil(DIV_ROUND_UP(u_minify(prsc->width0, lvl), block_width))) |
                        A6XX_TEX_CONST_10_FLAG_BUFFER_LOGH(util_logbase2_ceil(DIV_ROUND_UP(u_minify(prsc->height0, lvl), block_height)));
        }
-
-       return &so->base;
 }
 
 static void
@@ -363,6 +375,11 @@ fd6_texture_state(struct fd_context *ctx, enum pipe_shader_type type,
                struct fd6_pipe_sampler_view *view =
                        fd6_pipe_sampler_view(tex->textures[i]);
 
+               /* NOTE that if the backing rsc was uncompressed between the
+                * time that the CSO was originally created and now, the rsc
+                * seqno would have changed, so we don't have to worry about
+                * getting a bogus cache hit.
+                */
                key.view[i].rsc_seqno = fd_resource(view->base.texture)->seqno;
                key.view[i].seqno = view->seqno;
        }
index 3ce43d5..0271154 100644 (file)
@@ -56,6 +56,11 @@ struct fd6_pipe_sampler_view {
        uint32_t offset1, offset2;
        struct fd_resource *ptr1, *ptr2;
        uint16_t seqno;
+
+       /* For detecting when a resource has transitioned from UBWC compressed
+        * to uncompressed, which means the sampler state needs to be updated
+        */
+       uint16_t rsc_seqno;
 };
 
 static inline struct fd6_pipe_sampler_view *
@@ -64,6 +69,8 @@ fd6_pipe_sampler_view(struct pipe_sampler_view *pview)
        return (struct fd6_pipe_sampler_view *)pview;
 }
 
+void fd6_sampler_view_update(struct fd_context *ctx, struct fd6_pipe_sampler_view *so);
+
 void fd6_texture_init(struct pipe_context *pctx);
 void fd6_texture_fini(struct pipe_context *pctx);