freedreno/a6xx: Implement ARB_clear_texture
authorRob Clark <robdclark@chromium.org>
Sat, 29 Oct 2022 19:41:01 +0000 (12:41 -0700)
committerMarge Bot <emma+marge@anholt.net>
Wed, 2 Nov 2022 15:42:14 +0000 (15:42 +0000)
Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19400>

docs/features.txt
src/gallium/drivers/freedreno/a6xx/fd6_blitter.c
src/gallium/drivers/freedreno/freedreno_screen.c

index 45fbb6e..9539836 100644 (file)
@@ -196,7 +196,7 @@ GL 4.4, GLSL 4.40 -- all DONE: i965/gen8+, nvc0, r600, radeonsi, llvmpipe, zink
 
   GL_MAX_VERTEX_ATTRIB_STRIDE                           DONE (all drivers)
   GL_ARB_buffer_storage                                 DONE (freedreno, i965, nv50, v3d, vc4, lima, panfrost, asahi, d3d12, softpipe, etnaviv)
-  GL_ARB_clear_texture                                  DONE (i965, nv50, softpipe, virgl)
+  GL_ARB_clear_texture                                  DONE (freedreno/a6xx, i965, nv50, softpipe, virgl)
   GL_ARB_enhanced_layouts                               DONE (freedreno/a3xx+, i965, nv50, softpipe, virgl)
   - compile-time constant expressions                   DONE
   - explicit byte offsets for blocks                    DONE
index a113d90..9bbedce 100644 (file)
@@ -31,6 +31,7 @@
 #include "util/half_float.h"
 #include "util/u_dump.h"
 #include "util/u_log.h"
+#include "util/u_surface.h"
 
 #include "freedreno_blitter.h"
 #include "freedreno_fence.h"
@@ -233,6 +234,16 @@ can_do_blit(const struct pipe_blit_info *info)
    return true;
 }
 
+static bool
+can_do_clear(const struct pipe_resource *prsc, unsigned level,
+             const struct pipe_box *box)
+{
+   return ok_format(prsc->format) &&
+          ok_dims(prsc, box, level);
+
+   return true;
+}
+
 static void
 emit_setup(struct fd_batch *batch)
 {
@@ -829,6 +840,101 @@ fd6_clear_surface(struct fd_context *ctx, struct fd_ringbuffer *ring,
    }
 }
 
+static void
+fd6_clear_texture(struct pipe_context *pctx, struct pipe_resource *prsc,
+                  unsigned level, const struct pipe_box *box, const void *data)
+   assert_dt
+{
+   struct fd_context *ctx = fd_context(pctx);
+   struct fd_resource *rsc = fd_resource(prsc);
+
+   if (DEBUG_BLIT) {
+      fprintf(stderr, "surface texture:\ndst resource: ");
+      util_dump_resource(stderr, prsc);
+      fprintf(stderr, "\n");
+   }
+
+   if (!can_do_clear(prsc, level, box))
+      goto fallback;
+
+   union pipe_color_union color;
+
+   if (util_format_is_depth_or_stencil(prsc->format)) {
+      const struct util_format_description *desc =
+             util_format_description(prsc->format);
+      float depth = 0.0f;
+      uint8_t stencil = 0;
+
+      if (util_format_has_depth(desc))
+         util_format_unpack_z_float(prsc->format, &depth, data, 1);
+
+      if (util_format_has_stencil(desc))
+         util_format_unpack_s_8uint(prsc->format, &stencil, data, 1);
+
+      if (rsc->stencil)
+         fd6_clear_texture(pctx, &rsc->stencil->b.b, level, box, &stencil);
+
+      color.f[0] = depth;
+      color.ui[1] = stencil;
+   } else {
+      util_format_unpack_rgba(prsc->format, color.ui, data, 1);
+   }
+
+   struct fd_batch *batch = fd_bc_alloc_batch(ctx, true);
+
+   fd_screen_lock(ctx->screen);
+   fd_batch_resource_write(batch, rsc);
+   fd_screen_unlock(ctx->screen);
+
+   ASSERTED bool ret = fd_batch_lock_submit(batch);
+   assert(ret);
+
+   /* Marking the batch as needing flush must come after the batch
+    * dependency tracking (resource_read()/resource_write()), as that
+    * can trigger a flush
+    */
+   fd_batch_needs_flush(batch);
+
+   fd_batch_update_queries(batch);
+
+   emit_setup(batch);
+
+   struct pipe_surface surf = {
+         .format = prsc->format,
+         .texture = prsc,
+         .u = {
+               .tex = {
+                     .level = level,
+                     .first_layer = box->z,
+                     .last_layer = box->depth + box->z - 1,
+               },
+         },
+   };
+
+   fd6_clear_surface(ctx, batch->draw, &surf, box, &color, 0);
+
+   fd6_event_write(batch, batch->draw, PC_CCU_FLUSH_COLOR_TS, true);
+   fd6_event_write(batch, batch->draw, PC_CCU_FLUSH_DEPTH_TS, true);
+   fd6_event_write(batch, batch->draw, CACHE_FLUSH_TS, true);
+   fd_wfi(batch, batch->draw);
+   fd6_cache_inv(batch, batch->draw);
+
+   fd_batch_unlock_submit(batch);
+
+   fd_batch_flush(batch);
+   fd_batch_reference(&batch, NULL);
+
+   /* Acc query state will have been dirtied by our fd_batch_update_queries, so
+    * the ctx->batch may need to turn its queries back on.
+    */
+   ctx->update_active_queries = true;
+
+   return;
+
+fallback:
+   util_clear_texture(pctx, prsc, level, box, data);
+}
+
 void
 fd6_resolve_tile(struct fd_batch *batch, struct fd_ringbuffer *ring,
                  uint32_t base, struct pipe_surface *psurf, uint32_t unknown_8c01)
@@ -1190,6 +1296,7 @@ fd6_blitter_init(struct pipe_context *pctx) disable_thread_safety_analysis
    if (FD_DBG(NOBLIT))
       return;
 
+   pctx->clear_texture = fd6_clear_texture;
    ctx->blit = fd6_blit;
 }
 
index 0b2dbea..d3bdb47 100644 (file)
@@ -210,6 +210,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return 1;
 
    case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
+   case PIPE_CAP_CLEAR_TEXTURE:
       return is_a6xx(screen);
 
    case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: