panfrost: Move the blend shader cache at the context level
authorBoris Brezillon <boris.brezillon@collabora.com>
Thu, 8 Oct 2020 12:17:23 +0000 (14:17 +0200)
committerMarge Bot <eric+marge@anholt.net>
Fri, 9 Oct 2020 14:16:41 +0000 (14:16 +0000)
Blend shaders can be shared among blend states, so let's move the blend
shader one level up so we don't have to re-create/re-compile shaders
when another blend state already asked for it.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7066>

src/gallium/drivers/panfrost/pan_blend.h
src/gallium/drivers/panfrost/pan_blend_cso.c
src/gallium/drivers/panfrost/pan_blend_shaders.c
src/gallium/drivers/panfrost/pan_blend_shaders.h
src/gallium/drivers/panfrost/pan_context.c
src/gallium/drivers/panfrost/pan_context.h

index 8e30d67..901d54a 100644 (file)
 
 struct panfrost_bo;
 
+struct panfrost_blend_shader_key {
+        /* RT format */
+        enum pipe_format format;
+
+        /* Render target */
+        unsigned rt : 3;
+
+        /* Blend shader uses blend constants */
+        unsigned has_constants : 1;
+
+        /* Logic Op info */
+        unsigned logicop_enable : 1;
+        unsigned logicop_func:4;
+
+        struct pipe_rt_blend_state equation;
+};
+
 /* An internal blend shader descriptor, from the compiler */
 
 struct panfrost_blend_shader {
+        struct panfrost_blend_shader_key key;
         struct panfrost_context *ctx;
 
         nir_shader *nir;
 
-        /* Render target */
-        unsigned rt;
-
-        /* RT format */
-        enum pipe_format format;
-
         /* Blend constants */
         float constants[4];
 
@@ -92,11 +104,6 @@ struct panfrost_blend_rt {
 
         /* Properties of the blend mode */
         bool opaque, load_dest, no_colour;
-
-        /* Regardless of fixed-function blending, this is a map of pipe_format
-         * to panfrost_blend_shader */
-
-        struct hash_table_u64 *shaders;
 };
 
 struct panfrost_blend_state {
index e1f279d..15308d2 100644 (file)
@@ -77,16 +77,30 @@ panfrost_get_blend_shader(struct panfrost_context *ctx,
         assert(fmt != 0);
 
         /* Check the cache. Key by the RT and format */
-        struct hash_table_u64 *shaders = blend->rt[rt].shaders;
-        unsigned key = (fmt << 4) | ((constants != NULL) << 3) | rt;
+        struct hash_table *shaders = ctx->blend_shaders;
+        struct panfrost_blend_shader_key key = {
+                .rt = rt,
+                .format = fmt,
+                .has_constants = constants != NULL,
+                .logicop_enable = blend->base.logicop_enable,
+        };
 
-        struct panfrost_blend_shader *shader =
-                _mesa_hash_table_u64_search(shaders, key);
+        if (blend->base.logicop_enable) {
+                key.logicop_func = blend->base.logicop_func;
+        } else {
+                unsigned idx = blend->base.independent_blend_enable ? rt : 0;
+
+                if (blend->base.rt[idx].blend_enable)
+                        key.equation = blend->base.rt[idx];
+        }
+
+        struct hash_entry *he = _mesa_hash_table_search(shaders, &key);
+        struct panfrost_blend_shader *shader = he ? he->data : NULL;
 
         if (!shader) {
                 /* Cache miss. Build one instead, cache it, and go */
-                shader = panfrost_create_blend_shader(ctx, blend, fmt, rt);
-                _mesa_hash_table_u64_insert(shaders, key, shader);
+                shader = panfrost_create_blend_shader(ctx, blend, &key);
+                _mesa_hash_table_insert(shaders, &shader->key, shader);
         }
 
         panfrost_compile_blend_shader(shader, constants);
@@ -114,7 +128,6 @@ panfrost_create_blend_state(struct pipe_context *pipe,
                 struct pipe_rt_blend_state pipe = blend->rt[g];
 
                 struct panfrost_blend_rt *rt = &so->rt[c];
-                rt->shaders = _mesa_hash_table_u64_create(so);
 
                 /* Logic ops are always shader */
                 if (blend->logicop_enable) {
index b0c6d27..fee3bbe 100644 (file)
@@ -132,23 +132,21 @@ nir_iclamp(nir_builder *b, nir_ssa_def *v, int32_t lo, int32_t hi)
 struct panfrost_blend_shader *
 panfrost_create_blend_shader(struct panfrost_context *ctx,
                              struct panfrost_blend_state *state,
-                             enum pipe_format format,
-                             unsigned rt)
+                             const struct panfrost_blend_shader_key *key)
 {
-        struct panfrost_blend_shader *res = rzalloc(state, struct panfrost_blend_shader);
+        struct panfrost_blend_shader *res = rzalloc(ctx, struct panfrost_blend_shader);
 
         res->ctx = ctx;
-        res->rt = rt;
-        res->format = format;
+        res->key = *key;
 
         /* Build the shader */
 
-        nir_shader *shader = nir_shader_create(state, MESA_SHADER_FRAGMENT, &midgard_nir_options, NULL);
+        nir_shader *shader = nir_shader_create(ctx, MESA_SHADER_FRAGMENT, &midgard_nir_options, NULL);
         nir_function *fn = nir_function_create(shader, "main");
         nir_function_impl *impl = nir_function_impl_create(fn);
 
         const struct util_format_description *format_desc =
-                util_format_description(format);
+                util_format_description(key->format);
 
         nir_alu_type T = pan_unpacked_type_for_format(format_desc);
         enum glsl_base_type g =
@@ -201,8 +199,8 @@ panfrost_create_blend_shader(struct panfrost_context *ctx,
         /* Build a trivial blend shader */
         nir_store_var(b, c_out, s_src[0], 0xFF);
 
-        nir_lower_blend_options options = nir_make_options(&state->base, rt);
-        options.format = format;
+        nir_lower_blend_options options = nir_make_options(&state->base, key->rt);
+        options.format = key->format;
         options.src1 = s_src[1];
 
         if (T == nir_type_float16)
@@ -235,8 +233,8 @@ panfrost_compile_blend_shader(struct panfrost_blend_shader *shader,
         struct panfrost_compile_inputs inputs = {
                 .gpu_id = dev->gpu_id,
                 .is_blend = true,
-                .blend.rt = shader->rt,
-                .rt_formats = {shader->format},
+                .blend.rt = shader->key.rt,
+                .rt_formats = {shader->key.format},
         };
 
         if (constants)
index 9200489..3c47f0b 100644 (file)
@@ -34,8 +34,7 @@
 struct panfrost_blend_shader *
 panfrost_create_blend_shader(struct panfrost_context *ctx,
                              struct panfrost_blend_state *state,
-                             enum pipe_format format,
-                             unsigned rt);
+                             const struct panfrost_blend_shader_key *key);
 
 void
 panfrost_compile_blend_shader(struct panfrost_blend_shader *shader,
index 06afce0..adc0cd8 100644 (file)
@@ -1504,6 +1504,16 @@ panfrost_set_stream_output_targets(struct pipe_context *pctx,
         so->num_targets = num_targets;
 }
 
+static uint32_t panfrost_shader_key_hash(const void *key)
+{
+        return _mesa_hash_data(key, sizeof(struct panfrost_blend_shader_key));
+}
+
+static bool panfrost_shader_key_equal(const void *a, const void *b)
+{
+        return !memcmp(a, b, sizeof(struct panfrost_blend_shader_key));
+}
+
 struct pipe_context *
 panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
 {
@@ -1607,11 +1617,11 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
 
         panfrost_batch_init(ctx);
 
-        if (!(dev->quirks & IS_BIFROST)) {
-                ctx->blit_blend = rzalloc(ctx, struct panfrost_blend_state);
-                for (unsigned c = 0; c < PIPE_MAX_COLOR_BUFS; ++c)
-                        ctx->blit_blend->rt[c].shaders = _mesa_hash_table_u64_create(ctx);
-        }
+        ctx->blit_blend = rzalloc(ctx, struct panfrost_blend_state);
+        ctx->blend_shaders =
+                _mesa_hash_table_create(ctx,
+                                        panfrost_shader_key_hash,
+                                        panfrost_shader_key_equal);
 
         /* By default mask everything on */
         ctx->sample_mask = ~0;
index 130989f..f725113 100644 (file)
@@ -179,6 +179,7 @@ struct panfrost_context {
         unsigned min_samples;
 
         struct panfrost_blend_state *blit_blend;
+        struct hash_table *blend_shaders;
 };
 
 /* Corresponds to the CSO */