Mesa (main): panfrost: Constant stencil value tracking

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jun 9 09:04:58 UTC 2022


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

Author: Icecream95 <ixn at disroot.org>
Date:   Thu May  5 13:50:16 2022 +1200

panfrost: Constant stencil value tracking

If stencil is constant across the resource, then it can be treated as
if it was cleared.

Improves performance in applications which create a stencil buffer but
do not use it. Originally the same was done for depth to help some 2D
applications, but that gave mixed results so the patch was dropped.

v2: Don't do anything if a fragment job wouldn't be needed otherwise.
v3: Set stencil_value when a batch is cleared (Alyssa)
v4: Handle clears when the stencil is already known (Alyssa)
v5: Make sure shared resources are not used (Alyssa)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16646>

---

 src/gallium/drivers/panfrost/pan_job.c      | 30 ++++++++++++++++++++++++++++-
 src/gallium/drivers/panfrost/pan_resource.c |  8 ++++++++
 src/gallium/drivers/panfrost/pan_resource.h |  6 ++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c
index 3d1a472de31..7c8df123a01 100644
--- a/src/gallium/drivers/panfrost/pan_job.c
+++ b/src/gallium/drivers/panfrost/pan_job.c
@@ -656,6 +656,12 @@ panfrost_batch_submit_ioctl(struct panfrost_batch *batch,
         return 0;
 }
 
+static bool
+panfrost_has_fragment_job(struct panfrost_batch *batch)
+{
+        return batch->scoreboard.first_tiler || batch->clear;
+}
+
 /* Submit both vertex/tiler and fragment jobs for a batch, possibly with an
  * outsync corresponding to the later of the two (since there will be an
  * implicit dep between them) */
@@ -670,7 +676,7 @@ panfrost_batch_submit_jobs(struct panfrost_batch *batch,
         struct panfrost_device *dev = pan_device(pscreen);
         bool has_draws = batch->scoreboard.first_job;
         bool has_tiler = batch->scoreboard.first_tiler;
-        bool has_frag = has_tiler || batch->clear;
+        bool has_frag = panfrost_has_fragment_job(batch);
         int ret = 0;
 
         /* Take the submit lock to make sure no tiler jobs from other context
@@ -736,6 +742,28 @@ panfrost_batch_submit(struct panfrost_context *ctx,
         if (!batch->scoreboard.first_job && !batch->clear)
                 goto out;
 
+        if (batch->key.zsbuf && panfrost_has_fragment_job(batch)) {
+                struct pipe_surface *surf = batch->key.zsbuf;
+                struct panfrost_resource *z_rsrc = pan_resource(surf->texture);
+
+                /* Shared depth/stencil resources are not supported, and would
+                 * break this optimisation. */
+                assert(!(z_rsrc->base.bind & (PIPE_BIND_SHARED |
+                                              PIPE_BIND_SCANOUT |
+                                              PIPE_BIND_DISPLAY_TARGET)));
+
+                if (batch->clear & PIPE_CLEAR_STENCIL) {
+                        z_rsrc->stencil_value = batch->clear_stencil;
+                        z_rsrc->constant_stencil = true;
+                } else if (z_rsrc->constant_stencil) {
+                        batch->clear_stencil = z_rsrc->stencil_value;
+                        batch->clear |= PIPE_CLEAR_STENCIL;
+                }
+
+                if (batch->draws & PIPE_CLEAR_STENCIL)
+                        z_rsrc->constant_stencil = false;
+        }
+
         struct pan_fb_info fb;
         struct pan_image_view rts[8], zs, s;
 
diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c
index 8ae980e9a77..fcf5114eb11 100644
--- a/src/gallium/drivers/panfrost/pan_resource.c
+++ b/src/gallium/drivers/panfrost/pan_resource.c
@@ -719,6 +719,8 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
 
                 so->image.data.bo =
                         panfrost_bo_create(dev, so->image.layout.data_size, PAN_BO_DELAY_MMAP, label);
+
+                so->constant_stencil = true;
         }
 
         if (drm_is_afbc(so->image.layout.modifier))
@@ -962,6 +964,9 @@ panfrost_ptr_map(struct pipe_context *pctx,
         pipe_resource_reference(&transfer->base.resource, resource);
         *out_transfer = &transfer->base;
 
+        if (usage & PIPE_MAP_WRITE)
+                rsrc->constant_stencil = false;
+
         /* We don't have s/w routines for AFBC, so use a staging texture */
         if (drm_is_afbc(rsrc->image.layout.modifier)) {
                 struct panfrost_resource *staging = pan_alloc_staging(ctx, rsrc, level, box);
@@ -1361,6 +1366,9 @@ panfrost_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *pr
 {
         struct panfrost_context *ctx = pan_context(pctx);
         struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
+        struct panfrost_resource *rsrc = pan_resource(prsrc);
+
+        rsrc->constant_stencil = true;
 
         /* Handle the glInvalidateFramebuffer case */
         if (batch->key.zsbuf && batch->key.zsbuf->texture == prsrc)
diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h
index 1d7bb817816..06ced7bd5af 100644
--- a/src/gallium/drivers/panfrost/pan_resource.h
+++ b/src/gallium/drivers/panfrost/pan_resource.h
@@ -82,6 +82,12 @@ struct panfrost_resource {
         /* Used to decide when to convert to another modifier */
         uint16_t modifier_updates;
 
+        /* Do all pixels have the same stencil value? */
+        bool constant_stencil;
+
+        /* The stencil value if constant_stencil is set */
+        uint8_t stencil_value;
+
         /* Cached min/max values for index buffers */
         struct panfrost_minmax_cache *index_cache;
 };



More information about the mesa-commit mailing list