Mesa (main): panfrost: Simplify shader key architecture

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon May 2 14:14:35 UTC 2022


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

Author: Alyssa Rosenzweig <alyssa at collabora.com>
Date:   Tue Apr 26 12:37:59 2022 -0400

panfrost: Simplify shader key architecture

Rather than clever key compare/initialize code, let's make the shader keys plain
old data. This makes it easier both to extend and to optimize the shader keys.

Keys are compared with a simple memcmp(). I considered a hash table but I don't
think we have enough variants (or large enough keys) to justify the overhead.

Signed-off-by: Alyssa Rosenzweig <alyssa at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16173>

---

 src/gallium/drivers/panfrost/pan_assemble.c |  4 +-
 src/gallium/drivers/panfrost/pan_context.c  | 60 ++++++++++-------------------
 src/gallium/drivers/panfrost/pan_context.h  | 21 ++++++++--
 3 files changed, 39 insertions(+), 46 deletions(-)

diff --git a/src/gallium/drivers/panfrost/pan_assemble.c b/src/gallium/drivers/panfrost/pan_assemble.c
index af01b3dab1f..6d10b2deb60 100644
--- a/src/gallium/drivers/panfrost/pan_assemble.c
+++ b/src/gallium/drivers/panfrost/pan_assemble.c
@@ -49,7 +49,7 @@ panfrost_shader_compile(struct pipe_screen *pscreen,
 
         /* Lower this early so the backends don't have to worry about it */
         if (s->info.stage == MESA_SHADER_FRAGMENT)
-                NIR_PASS_V(s, nir_lower_fragcolor, state->nr_cbufs);
+                NIR_PASS_V(s, nir_lower_fragcolor, state->key.fs.nr_cbufs);
 
         /* Call out to Midgard compiler given the above NIR */
         struct panfrost_compile_inputs inputs = {
@@ -57,7 +57,7 @@ panfrost_shader_compile(struct pipe_screen *pscreen,
                 .shaderdb = !!(dev->debug & PAN_DBG_PRECOMPILE),
         };
 
-        memcpy(inputs.rt_formats, state->rt_formats, sizeof(inputs.rt_formats));
+        memcpy(inputs.rt_formats, state->key.fs.rt_formats, sizeof(inputs.rt_formats));
 
         struct util_dynarray binary;
 
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index f4e2249e5e0..0ede262299e 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -360,18 +360,22 @@ panfrost_bind_sampler_states(
                 memcpy(ctx->samplers[shader], sampler, num_sampler * sizeof (void *));
 }
 
-static bool
-panfrost_variant_matches(
-        struct panfrost_context *ctx,
-        struct panfrost_shader_state *variant,
-        enum pipe_shader_type type)
+static void
+panfrost_build_key(struct panfrost_context *ctx,
+                   struct panfrost_shader_key *key,
+                   nir_shader *nir)
 {
-        if (variant->info.stage == MESA_SHADER_FRAGMENT &&
-            variant->info.fs.outputs_read) {
-                struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
+        /* We don't currently have vertex shader variants */
+        if (nir->info.stage != MESA_SHADER_FRAGMENT)
+               return;
+
+        struct panfrost_device *dev = pan_device(ctx->base.screen);
+        struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
+
+        key->fs.nr_cbufs = fb->nr_cbufs;
 
-                unsigned i;
-                BITSET_FOREACH_SET(i, &variant->info.fs.outputs_read, 8) {
+        if (dev->arch <= 5) {
+                u_foreach_bit(i, (nir->info.outputs_read >> FRAG_RESULT_DATA0)) {
                         enum pipe_format fmt = PIPE_FORMAT_R8G8B8A8_UNORM;
 
                         if ((fb->nr_cbufs > i) && fb->cbufs[i])
@@ -380,17 +384,9 @@ panfrost_variant_matches(
                         if (panfrost_blendable_formats_v6[fmt].internal)
                                 fmt = PIPE_FORMAT_NONE;
 
-                        if (variant->rt_formats[i] != fmt)
-                                return false;
+                        key->fs.rt_formats[i] = fmt;
                 }
         }
-
-        if (variant->info.stage == MESA_SHADER_FRAGMENT &&
-            variant->nr_cbufs != ctx->pipe_framebuffer.nr_cbufs)
-                return false;
-
-        /* Otherwise, we're good to go */
-        return true;
 }
 
 /**
@@ -453,8 +449,11 @@ panfrost_bind_shader_state(
 
         simple_mtx_lock(&variants->lock);
 
+        struct panfrost_shader_key key = { 0 };
+        panfrost_build_key(ctx, &key, variants->nir);
+
         for (unsigned i = 0; i < variants->variant_count; ++i) {
-                if (panfrost_variant_matches(ctx, &variants->variants[i], type)) {
+                if (memcmp(&key, &variants->variants[i].key, sizeof(key)) == 0) {
                         variant = i;
                         break;
                 }
@@ -483,32 +482,13 @@ panfrost_bind_shader_state(
                                (variants->variant_space - old_space) * msize);
                 }
 
-                struct panfrost_shader_state *v =
-                                &variants->variants[variant];
-
-                if (type == PIPE_SHADER_FRAGMENT) {
-                        struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
-                        v->nr_cbufs = fb->nr_cbufs;
-
-                        for (unsigned i = 0; i < fb->nr_cbufs; ++i) {
-                                enum pipe_format fmt = PIPE_FORMAT_R8G8B8A8_UNORM;
-
-                                if ((fb->nr_cbufs > i) && fb->cbufs[i])
-                                        fmt = fb->cbufs[i]->format;
-
-                                if (panfrost_blendable_formats_v6[fmt].internal)
-                                        fmt = PIPE_FORMAT_NONE;
-
-                                v->rt_formats[i] = fmt;
-                        }
-                }
+                variants->variants[variant].key = key;
         }
 
         /* Select this variant */
         variants->active_variant = variant;
 
         struct panfrost_shader_state *shader_state = &variants->variants[variant];
-        assert(panfrost_variant_matches(ctx, shader_state, type));
 
         /* We finally have a variant, so compile it */
 
diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h
index 15b5cd59996..b4ad06dbd14 100644
--- a/src/gallium/drivers/panfrost/pan_context.h
+++ b/src/gallium/drivers/panfrost/pan_context.h
@@ -252,7 +252,22 @@ struct pan_linkage {
 #define RSD_WORDS 16
 
 /* Variants bundle together to form the backing CSO, bundling multiple
- * shaders with varying emulated features baked in */
+ * shaders with varying emulated features baked in
+ */
+struct panfrost_fs_key {
+        /* Number of colour buffers */
+        unsigned nr_cbufs;
+
+        /* Midgard shaders that read the tilebuffer must be keyed for
+         * non-blendable formats
+         */
+        enum pipe_format rt_formats[8];
+};
+
+struct panfrost_shader_key {
+        /* If we need vertex shader keys, union it in */
+        struct panfrost_fs_key fs;
+};
 
 /* A shader state corresponds to the actual, current variant of the shader */
 struct panfrost_shader_state {
@@ -273,9 +288,7 @@ struct panfrost_shader_state {
         struct pipe_stream_output_info stream_output;
         uint64_t so_mask;
 
-        /* Variants */
-        enum pipe_format rt_formats[8];
-        unsigned nr_cbufs;
+        struct panfrost_shader_key key;
 
         /* Mask of state that dirties the sysvals */
         unsigned dirty_3d, dirty_shader;



More information about the mesa-commit mailing list