iris: Update aux state tracking for image views after draws/dispatches
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 5 Oct 2022 06:34:56 +0000 (23:34 -0700)
committerMarge Bot <emma+marge@anholt.net>
Wed, 14 Dec 2022 13:01:27 +0000 (13:01 +0000)
On Tigerlake and later, we enable compression for image views.  However,
we never actually added any code to update the aux state, which meant
that if it ever changed, things would break, badly.

We managed to avoid catastrophic effects in most cases because of
two other issues which papered over the problem: if compression wasn't
already enabled for an image, we'd leave it disabled.  And, we avoided
writing via the CPU to buffers with auxiliary.  So in most cases, CCS
remained disabled, or got enabled (say by glTexImage()) then stayed on
permanently.  There were still issues, but they managed to remain more
hidden than one would expect given the severity of the bug.

Reviewed-by: Nanley Chery <nanley.g.chery@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19060>

src/gallium/drivers/iris/iris_context.h
src/gallium/drivers/iris/iris_draw.c
src/gallium/drivers/iris/iris_resolve.c
src/gallium/drivers/iris/iris_state.c

index 1b875eb..39f259c 100644 (file)
@@ -579,6 +579,9 @@ struct iris_shader_state {
 
    /** Bitfield of which shader storage buffers are writable. */
    uint32_t writable_ssbos;
+
+   /** Array of aux usages used for our shader's images in the current draw */
+   enum isl_aux_usage image_aux_usage[PIPE_MAX_SHADER_IMAGES];
 };
 
 /**
@@ -1079,6 +1082,8 @@ void iris_predraw_flush_buffers(struct iris_context *ice,
                                 struct iris_batch *batch,
                                 gl_shader_stage stage);
 void iris_postdraw_update_resolve_tracking(struct iris_context *ice);
+void iris_postdraw_update_image_resolve_tracking(struct iris_context *ice,
+                                                 gl_shader_stage stage);
 void iris_cache_flush_for_render(struct iris_batch *batch,
                                  struct iris_bo *bo,
                                  enum isl_aux_usage aux_usage);
index 6908e73..88ee1f6 100644 (file)
@@ -382,6 +382,8 @@ void
 iris_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
 {
    struct iris_context *ice = (struct iris_context *) ctx;
+   struct iris_screen *screen = (struct iris_screen *) ctx->screen;
+   const struct intel_device_info *devinfo = &screen->devinfo;
    struct iris_batch *batch = &ice->batches[IRIS_BATCH_COMPUTE];
 
    if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
@@ -434,7 +436,6 @@ iris_launch_grid(struct pipe_context *ctx, const struct pipe_grid_info *grid)
    ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_COMPUTE;
    ice->state.stage_dirty &= ~IRIS_ALL_STAGE_DIRTY_FOR_COMPUTE;
 
-   /* Note: since compute shaders can't access the framebuffer, there's
-    * no need to call iris_postdraw_update_resolve_tracking.
-    */
+   if (devinfo->ver >= 12)
+      iris_postdraw_update_image_resolve_tracking(ice, MESA_SHADER_COMPUTE);
 }
index 454d493..f0ecb3a 100644 (file)
@@ -145,6 +145,10 @@ resolve_image_views(struct iris_context *ice,
                                       pview->u.tex.level, 1,
                                       pview->u.tex.first_layer, num_layers,
                                       aux_usage, false);
+
+         shs->image_aux_usage[i] = aux_usage;
+      } else {
+         shs->image_aux_usage[i] = ISL_AUX_USAGE_NONE;
       }
 
       iris_emit_buffer_barrier_for(batch, res->bo, IRIS_DOMAIN_DATA_WRITE);
@@ -257,6 +261,39 @@ iris_predraw_resolve_framebuffer(struct iris_context *ice,
    }
 }
 
+void
+iris_postdraw_update_image_resolve_tracking(struct iris_context *ice,
+                                            gl_shader_stage stage)
+{
+   struct iris_screen *screen = (void *) ice->ctx.screen;
+   ASSERTED struct intel_device_info *devinfo = &screen->devinfo;
+
+   assert(devinfo->ver >= 12);
+
+   const struct iris_shader_state *shs = &ice->state.shaders[stage];
+   const struct shader_info *info = iris_get_shader_info(ice, stage);
+
+   const uint64_t images_used = !info ? 0 :
+      (info->images_used[0] | ((uint64_t)info->images_used[1]) << 32);
+   uint64_t views = shs->bound_image_views & images_used;
+
+   while (views) {
+      const int i = u_bit_scan64(&views);
+      const struct pipe_image_view *pview = &shs->image[i].base;
+      struct iris_resource *res = (void *) pview->resource;
+
+      if (pview->shader_access & PIPE_IMAGE_ACCESS_WRITE &&
+          res->base.b.target != PIPE_BUFFER) {
+         unsigned num_layers =
+            pview->u.tex.last_layer - pview->u.tex.first_layer + 1;
+
+         iris_resource_finish_write(ice, res, pview->u.tex.level,
+                                    pview->u.tex.first_layer, num_layers,
+                                    shs->image_aux_usage[i]);
+      }
+   }
+}
+
 /**
  * \brief Call this after drawing to mark which buffers need resolving
  *
@@ -272,6 +309,8 @@ iris_predraw_resolve_framebuffer(struct iris_context *ice,
 void
 iris_postdraw_update_resolve_tracking(struct iris_context *ice)
 {
+   struct iris_screen *screen = (void *) ice->ctx.screen;
+   struct intel_device_info *devinfo = &screen->devinfo;
    struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
 
    // XXX: front buffer drawing?
@@ -324,6 +363,12 @@ iris_postdraw_update_resolve_tracking(struct iris_context *ice)
                                      aux_usage);
       }
    }
+
+   if (devinfo->ver >= 12) {
+      for (gl_shader_stage stage = 0; stage < MESA_SHADER_COMPUTE; stage++) {
+         iris_postdraw_update_image_resolve_tracking(ice, stage);
+      }
+   }
 }
 
 void
index 4ac9a25..9b623c8 100644 (file)
@@ -5137,8 +5137,7 @@ use_image(struct iris_batch *batch, struct iris_context *ice,
                          IRIS_DOMAIN_NONE);
    }
 
-   enum isl_aux_usage aux_usage =
-      iris_image_view_aux_usage(ice, &iv->base, info);
+   enum isl_aux_usage aux_usage = shs->image_aux_usage[i];
 
    return use_surface_state(batch, &iv->surface_state, aux_usage);
 }