[Mesa-dev] [PATCH v2 00/37] panfrost: Support batch pipelining

Boris Brezillon boris.brezillon at collabora.com
Wed Sep 18 08:01:04 UTC 2019


+Rob

On Tue, 17 Sep 2019 17:13:04 +0200
Boris Brezillon <boris.brezillon at collabora.com> wrote:

> On Tue, 17 Sep 2019 08:36:56 -0400
> Alyssa Rosenzweig <alyssa at rosenzweig.io> wrote:
> 
> > "Can't use pipe_framebuffer_state as a hash key" Is this still relevant?
> > I thought we did this.  
> 
> I did this yes. I thought it was only a problem for the wallpaper
> draw, but it's actually wrong for any kind of blit where src and
> dst point to the same resource, you're right. I guess the solution
> would be to not use util_framebuffer_state_equal() but compare the
> resources pointed by surfaces contained in the fb state, and not hash
> the fb state directly, but hash its resource pointers instead (pretty
> much what was done before my patch :-/).

I tried implementing my own hash/compare funcs for the FBO key (instead
of using util_framebuffer_state_equal() and hashing the whole struct)
based on the freedreno logic, and I added an assert to see if there was
cases where util_framebuffer_state_equal() was returning something
different (see the below diff). There are indeed 2 deqp-gles2 tests that
trigger this assert.

So, now the question is, is it worth fixing, or can we live with the
extra batch addition because we can't figure out that 2 FBOs are identical
in rare occasions.

There's still something I don't understand in the freedreno logic: they
say they don't want to retain refs to the surface pointed by the fb
state, because refcounting gets messy then, but I don't get why, especially
since they retain refs to the resources pointed by those surfaces.

Anyway, I guess all of this can be sorted out after this series has landed.

--->8---
diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c
index 04257727ee0a..a90c427f6042 100644
--- a/src/gallium/drivers/panfrost/pan_job.c
+++ b/src/gallium/drivers/panfrost/pan_job.c
@@ -100,6 +100,74 @@ panfrost_batch_fence_reference(struct panfrost_batch_fence *fence)
         pipe_reference(NULL, &fence->reference);
 }
 
+static bool
+panfrost_batch_surf_compare(const struct pipe_surface *a,
+                            const struct pipe_surface *b)
+{
+        if (!a || !b)
+                return a == b;
+
+        if (a->texture != b->texture ||
+            memcmp(&a->u, &b->u, sizeof(a->u)) ||
+            a->nr_samples != b->nr_samples ||
+            a->format != b->format)
+                return false;
+
+        return true;
+}
+
+static bool
+panfrost_batch_compare(const void *a, const void *b)
+{
+        const struct pipe_framebuffer_state *fba = a, *fbb = b;
+        unsigned i;
+
+        if (fba->width != fbb->width || fba->height != fbb->height ||
+            fba->layers != fbb->layers || fba->samples != fbb->samples ||
+            fba->nr_cbufs != fbb->nr_cbufs)
+                return false;
+
+        for (i = 0; i < fba->nr_cbufs; i++) {
+                if (!panfrost_batch_surf_compare(fba->cbufs[i], fbb->cbufs[i]))
+                        return false;
+        }
+
+        return panfrost_batch_surf_compare(fba->zsbuf, fbb->zsbuf);
+}
+
+static uint32_t
+panfrost_batch_surf_hash(uint32_t hash, const struct pipe_surface *surf)
+{
+        uint32_t fmt_samples = surf ? (surf->format | (surf->nr_samples << 16)) : 0;
+        struct pipe_resource *rsrc = surf ? surf->texture : NULL;
+        union pipe_surface_desc dummy_desc = { };
+
+        hash = _mesa_fnv32_1a_accumulate_block(hash, &rsrc, sizeof(rsrc));
+        hash = _mesa_fnv32_1a_accumulate_block(hash,
+                                               surf ? &surf->u : &dummy_desc,
+                                               sizeof(surf->u));
+        return _mesa_fnv32_1a_accumulate_block(hash, &fmt_samples,
+                                               sizeof(fmt_samples));
+}
+
+static uint32_t
+panfrost_batch_hash(const void *key)
+{
+        const struct pipe_framebuffer_state *fb = key;
+        uint64_t header = fb->width | fb->height << 16 |
+                          (uint64_t)fb->layers << 32 |
+                          (uint64_t)fb->samples << 48 |
+                          (uint64_t)fb->nr_cbufs << 56;
+        uint32_t hash = _mesa_fnv32_1a_offset_bias;
+        unsigned i;
+
+        hash = _mesa_fnv32_1a_accumulate_block(hash, &header, sizeof(header));
+        for (i = 0; i < ARRAY_SIZE(fb->cbufs); i++)
+                hash = panfrost_batch_surf_hash(hash, fb->cbufs[i]);
+
+        return panfrost_batch_surf_hash(hash, fb->zsbuf);
+}
+
 static struct panfrost_batch *
 panfrost_create_batch(struct panfrost_context *ctx,
                       const struct pipe_framebuffer_state *key)
@@ -252,8 +320,10 @@ panfrost_get_batch(struct panfrost_context *ctx,
         struct hash_entry *entry = _mesa_hash_table_search(ctx->fbo_to_batch,
                                                            key);
 
-        if (entry)
+        if (entry) {
+                assert(util_framebuffer_state_equal(entry->key, key));
                 return entry->data;
+        }
 
         /* Otherwise, let's create a job */
 
@@ -1115,18 +1185,6 @@ panfrost_batch_clear(struct panfrost_batch *batch,
                                      ctx->pipe_framebuffer.height);
 }
 
-static bool
-panfrost_batch_compare(const void *a, const void *b)
-{
-        return util_framebuffer_state_equal(a, b);
-}
-
-static uint32_t
-panfrost_batch_hash(const void *key)
-{
-        return _mesa_hash_data(key, sizeof(struct pipe_framebuffer_state));
-}
-
 /* Given a new bounding rectangle (scissor), let the job cover the union of the
  * new and old bounding rectangles */


More information about the mesa-dev mailing list