Mesa (master): v3d: add fast-path tile-based blit for depth/stencil buffers

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jan 13 12:58:53 UTC 2021


Module: Mesa
Branch: master
Commit: f58a11460dddf771b5b35bbb1ee5de4b588b4d21
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f58a11460dddf771b5b35bbb1ee5de4b588b4d21

Author: Juan A. Suarez Romero <jasuarez at igalia.com>
Date:   Fri Dec 18 11:33:15 2020 +0100

v3d: add fast-path tile-based blit for depth/stencil buffers

This extends the TLB based blit to support both depth and stencil
buffers.

v2:
 - Ammend comment for further clarification (Iago)
 - Remove parenthesis (Iago)
 - Remove condition so separate stencil blit is done (Iago)

Signed-off-by: Juan A. Suarez Romero <jasuarez at igalia.com>
Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8304>

---

 src/gallium/drivers/v3d/v3d_blit.c | 44 +++++++++++++++++++++++++++++---------
 src/gallium/drivers/v3d/v3dx_rcl.c | 38 +++++++++++++++-----------------
 2 files changed, 51 insertions(+), 31 deletions(-)

diff --git a/src/gallium/drivers/v3d/v3d_blit.c b/src/gallium/drivers/v3d/v3d_blit.c
index 4e96c183513..dd5805d55a3 100644
--- a/src/gallium/drivers/v3d/v3d_blit.c
+++ b/src/gallium/drivers/v3d/v3d_blit.c
@@ -416,11 +416,18 @@ v3d_tlb_blit(struct pipe_context *pctx, struct pipe_blit_info *info)
         struct v3d_context *v3d = v3d_context(pctx);
         struct v3d_screen *screen = v3d->screen;
 
-        if (screen->devinfo.ver < 40)
+        if (screen->devinfo.ver < 40 || !info->mask)
                 return;
 
-        if ((info->mask & PIPE_MASK_RGBA) == 0)
-                return;
+        bool is_color_blit = info->mask & PIPE_MASK_RGBA;
+        bool is_depth_blit = info->mask & PIPE_MASK_Z;
+        bool is_stencil_blit = info->mask & PIPE_MASK_S;
+
+        /* We should receive either a depth/stencil blit, or color blit, but
+         * not both.
+         */
+        assert ((is_color_blit && !is_depth_blit && !is_stencil_blit) ||
+                (!is_color_blit && (is_depth_blit || is_stencil_blit)));
 
         if (info->scissor_enable)
                 return;
@@ -431,7 +438,8 @@ v3d_tlb_blit(struct pipe_context *pctx, struct pipe_blit_info *info)
             info->src.box.height != info->dst.box.height)
                 return;
 
-        if (util_format_is_depth_or_stencil(info->dst.resource->format))
+        if (is_color_blit &&
+            util_format_is_depth_or_stencil(info->dst.resource->format))
                 return;
 
         if (!v3d_rt_format_supported(&screen->devinfo, info->src.resource->format))
@@ -458,10 +466,11 @@ v3d_tlb_blit(struct pipe_context *pctx, struct pipe_blit_info *info)
            v3d_get_blit_surface(pctx, info->src.resource, info->src.level, info->src.box.z);
 
         struct pipe_surface *surfaces[V3D_MAX_DRAW_BUFFERS] = { 0 };
-        surfaces[0] = dst_surf;
+        if (is_color_blit)
+                surfaces[0] = dst_surf;
 
         uint32_t tile_width, tile_height, max_bpp;
-        v3d_get_tile_buffer_size(msaa, 1, surfaces, src_surf, &tile_width, &tile_height, &max_bpp);
+        v3d_get_tile_buffer_size(msaa, is_color_blit ? 1 : 0, surfaces, src_surf, &tile_width, &tile_height, &max_bpp);
 
         int dst_surface_width = u_minify(info->dst.resource->width0,
                                          info->dst.level);
@@ -478,7 +487,11 @@ v3d_tlb_blit(struct pipe_context *pctx, struct pipe_blit_info *info)
                 return;
         }
 
-        struct v3d_job *job = v3d_get_job(v3d, 1u, surfaces, NULL, src_surf);
+        struct v3d_job *job = v3d_get_job(v3d,
+                                          is_color_blit ? 1u : 0u,
+                                          surfaces,
+                                          is_color_blit ? NULL : dst_surf,
+                                          src_surf);
         job->msaa = msaa;
         job->tile_width = tile_width;
         job->tile_height = tile_height;
@@ -495,17 +508,28 @@ v3d_tlb_blit(struct pipe_context *pctx, struct pipe_blit_info *info)
                                          job->tile_height);
 
         job->needs_flush = true;
-        job->store |= PIPE_CLEAR_COLOR0;
         job->num_layers = info->dst.box.depth;
 
+        job->store = 0;
+        if (is_color_blit) {
+                job->store |= PIPE_CLEAR_COLOR0;
+                info->mask &= ~PIPE_MASK_RGBA;
+        }
+        if (is_depth_blit) {
+                job->store |= PIPE_CLEAR_DEPTH;
+                info->mask &= ~PIPE_MASK_Z;
+        }
+        if (is_stencil_blit){
+                job->store |= PIPE_CLEAR_STENCIL;
+                info->mask &= ~PIPE_MASK_S;
+        }
+
         v3d41_start_binning(v3d, job);
 
         v3d_job_submit(v3d, job);
 
         pipe_surface_reference(&dst_surf, NULL);
         pipe_surface_reference(&src_surf, NULL);
-
-        info->mask &= ~PIPE_MASK_RGBA;
 }
 
 /* Optimal hardware path for blitting pixels.
diff --git a/src/gallium/drivers/v3d/v3dx_rcl.c b/src/gallium/drivers/v3d/v3dx_rcl.c
index 0da01055114..3ecc054a49d 100644
--- a/src/gallium/drivers/v3d/v3dx_rcl.c
+++ b/src/gallium/drivers/v3d/v3dx_rcl.c
@@ -115,7 +115,7 @@ store_general(struct v3d_job *job,
               struct v3d_cl *cl, struct pipe_surface *psurf,
               int layer, int buffer, int pipe_bit,
               uint32_t *stores_pending, bool general_color_clear,
-              bool is_blit)
+              bool resolve_4x)
 {
         struct v3d_surface *surf = v3d_surface(psurf);
         bool separate_stencil = surf->separate_stencil && buffer == STENCIL;
@@ -159,10 +159,10 @@ store_general(struct v3d_job *job,
                         store.height_in_ub_or_stride = slice->stride;
                 }
 
-                assert(!is_blit || job->bbuf);
+                assert(!resolve_4x || job->bbuf);
                 if (psurf->texture->nr_samples > 1)
                         store.decimate_mode = V3D_DECIMATE_MODE_ALL_SAMPLES;
-                else if (is_blit && job->bbuf->texture->nr_samples > 1)
+                else if (resolve_4x && job->bbuf->texture->nr_samples > 1)
                         store.decimate_mode = V3D_DECIMATE_MODE_4X;
                 else
                         store.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0;
@@ -216,22 +216,23 @@ zs_buffer_from_pipe_bits(int pipe_clear_bits)
 static void
 v3d_rcl_emit_loads(struct v3d_job *job, struct v3d_cl *cl, int layer)
 {
-        uint32_t loads_pending = job->load;
-        uint32_t blit_pending = job->bbuf ? PIPE_CLEAR_COLOR0 : 0;
-
-        assert(!job->bbuf || V3D_VERSION >= 40);
-
-        /* When blitting, no color buffer is loaded; instead the blit source
-         * buffer is loaded.
+        /* When blitting, no color or zs buffer is loaded; instead the blit
+         * source buffer is loaded for the aspects that we are going to blit.
          */
         assert(!job->bbuf || job->load == 0);
+        assert(!job->bbuf || job->nr_cbufs <= 1);
+        assert(!job->bbuf || V3D_VERSION >= 40);
+
+        uint32_t loads_pending = job->bbuf ? job->store : job->load;
 
         for (int i = 0; i < job->nr_cbufs; i++) {
                 uint32_t bit = PIPE_CLEAR_COLOR0 << i;
                 if (!(loads_pending & bit))
                         continue;
 
-                struct pipe_surface *psurf = job->cbufs[i];
+                struct pipe_surface *psurf = job->bbuf ? job->bbuf : job->cbufs[i];
+                assert(!job->bbuf || i == 0);
+
                 if (!psurf || (V3D_VERSION < 40 &&
                                psurf->texture->nr_samples <= 1)) {
                         continue;
@@ -241,27 +242,22 @@ v3d_rcl_emit_loads(struct v3d_job *job, struct v3d_cl *cl, int layer)
                              bit, &loads_pending);
         }
 
-        if (blit_pending) {
-                load_general(cl, job->bbuf, RENDER_TARGET_0, layer,
-                             PIPE_CLEAR_COLOR0, &blit_pending);
-                assert(blit_pending == 0);
-        }
-
         if ((loads_pending & PIPE_CLEAR_DEPTHSTENCIL) &&
             (V3D_VERSION >= 40 ||
              (job->zsbuf && job->zsbuf->texture->nr_samples > 1))) {
-                struct v3d_resource *rsc = v3d_resource(job->zsbuf->texture);
+                struct pipe_surface *src = job->bbuf ? job->bbuf : job->zsbuf;
+                struct v3d_resource *rsc = v3d_resource(src->texture);
 
                 if (rsc->separate_stencil &&
                     (loads_pending & PIPE_CLEAR_STENCIL)) {
-                        load_general(cl, job->zsbuf,
+                        load_general(cl, src,
                                      STENCIL, layer,
                                      PIPE_CLEAR_STENCIL,
                                      &loads_pending);
                 }
 
                 if (loads_pending & PIPE_CLEAR_DEPTHSTENCIL) {
-                        load_general(cl, job->zsbuf,
+                        load_general(cl, src,
                                      zs_buffer_from_pipe_bits(loads_pending),
                                      layer,
                                      loads_pending & PIPE_CLEAR_DEPTHSTENCIL,
@@ -331,7 +327,7 @@ v3d_rcl_emit_stores(struct v3d_job *job, struct v3d_cl *cl, int layer)
          * perspective.  Non-MSAA surfaces will use
          * STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED.
          */
-        assert(!job->bbuf || job->nr_cbufs == 1);
+        assert(!job->bbuf || job->nr_cbufs <= 1);
         for (int i = 0; i < job->nr_cbufs; i++) {
                 uint32_t bit = PIPE_CLEAR_COLOR0 << i;
                 if (!(job->store & bit))



More information about the mesa-commit mailing list