Mesa (main): panfrost: Move blend CSO to cmdstream/context

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jul 7 13:34:29 UTC 2021


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

Author: Alyssa Rosenzweig <alyssa at collabora.com>
Date:   Tue Jul  6 17:53:15 2021 -0400

panfrost: Move blend CSO to cmdstream/context

Create is hardware specifc, bind/delete/set_colour is not.

Signed-off-by: Alyssa Rosenzweig <alyssa at collabora.com>
Acked-by: Boris Brezillon <boris.brezillon at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11745>

---

 src/gallium/drivers/panfrost/meson.build     |   1 -
 src/gallium/drivers/panfrost/pan_blend_cso.c | 229 ---------------------------
 src/gallium/drivers/panfrost/pan_blend_cso.h |   3 -
 src/gallium/drivers/panfrost/pan_cmdstream.c | 100 ++++++++++++
 src/gallium/drivers/panfrost/pan_context.c   |  93 ++++++++++-
 5 files changed, 192 insertions(+), 234 deletions(-)

diff --git a/src/gallium/drivers/panfrost/meson.build b/src/gallium/drivers/panfrost/meson.build
index dc00072aa0a..1be1635d5f6 100644
--- a/src/gallium/drivers/panfrost/meson.build
+++ b/src/gallium/drivers/panfrost/meson.build
@@ -29,7 +29,6 @@ files_panfrost = files(
   'pan_blit.c',
   'pan_job.c',
   'pan_assemble.c',
-  'pan_blend_cso.c',
   'pan_cmdstream.c',
   'pan_compute.c',
   'pan_mempool.c',
diff --git a/src/gallium/drivers/panfrost/pan_blend_cso.c b/src/gallium/drivers/panfrost/pan_blend_cso.c
deleted file mode 100644
index 7d63b807fb3..00000000000
--- a/src/gallium/drivers/panfrost/pan_blend_cso.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2019 Collabora, Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors (Collabora):
- *   Alyssa Rosenzweig <alyssa.rosenzweig at collabora.com>
- *
- */
-
-#include <stdio.h>
-#include "util/u_memory.h"
-#include "gallium/auxiliary/util/u_blend.h"
-#include "pan_context.h"
-#include "pan_blend_cso.h"
-#include "pan_bo.h"
-#include "panfrost-quirks.h"
-
-/* A given Gallium blend state can be encoded to the hardware in numerous,
- * dramatically divergent ways due to the interactions of blending with
- * framebuffer formats. Conceptually, there are two modes:
- *
- * - Fixed-function blending (for suitable framebuffer formats, suitable blend
- *   state, and suitable blend constant)
- *
- * - Blend shaders (for everything else)
- *
- * A given Gallium blend configuration will compile to exactly one
- * fixed-function blend state, if it compiles to any, although the constant
- * will vary across runs as that is tracked outside of the Gallium CSO.
- *
- * However, that same blend configuration will compile to many different blend
- * shaders, depending on the framebuffer formats active. The rationale is that
- * blend shaders override not just fixed-function blending but also
- * fixed-function format conversion, so blend shaders are keyed to a particular
- * framebuffer format. As an example, the tilebuffer format is identical for
- * RG16F and RG16UI -- both are simply 32-bit raw pixels -- so both require
- * blend shaders.
- *
- * All of this state is encapsulated in the panfrost_blend_state struct
- * (our subclass of pipe_blend_state).
- */
-
-/* Create a blend CSO. Essentially, try to compile a fixed-function
- * expression and initialize blend shaders */
-
-static void *
-panfrost_create_blend_state(struct pipe_context *pipe,
-                            const struct pipe_blend_state *blend)
-{
-        struct panfrost_context *ctx = pan_context(pipe);
-        struct panfrost_device *dev = pan_device(pipe->screen);
-        struct panfrost_blend_state *so = rzalloc(ctx, struct panfrost_blend_state);
-        so->base = *blend;
-
-        so->pan.logicop_enable = blend->logicop_enable;
-        so->pan.logicop_func = blend->logicop_func;
-        so->pan.rt_count = blend->max_rt + 1;
-
-        for (unsigned c = 0; c < so->pan.rt_count; ++c) {
-                unsigned g = blend->independent_blend_enable ? c : 0;
-                const struct pipe_rt_blend_state pipe = blend->rt[g];
-                struct pan_blend_equation equation;
-
-                equation.color_mask = pipe.colormask;
-                equation.blend_enable = pipe.blend_enable;
-
-                if (pipe.blend_enable) {
-                        equation.rgb_func = util_blend_func_to_shader(pipe.rgb_func);
-                        equation.rgb_src_factor = util_blend_factor_to_shader(pipe.rgb_src_factor);
-                        equation.rgb_invert_src_factor = util_blend_factor_is_inverted(pipe.rgb_src_factor);
-                        equation.rgb_dst_factor = util_blend_factor_to_shader(pipe.rgb_dst_factor);
-                        equation.rgb_invert_dst_factor = util_blend_factor_is_inverted(pipe.rgb_dst_factor);
-                        equation.alpha_func = util_blend_func_to_shader(pipe.alpha_func);
-                        equation.alpha_src_factor = util_blend_factor_to_shader(pipe.alpha_src_factor);
-                        equation.alpha_invert_src_factor = util_blend_factor_is_inverted(pipe.alpha_src_factor);
-                        equation.alpha_dst_factor = util_blend_factor_to_shader(pipe.alpha_dst_factor);
-                        equation.alpha_invert_dst_factor = util_blend_factor_is_inverted(pipe.alpha_dst_factor);
-                }
-
-                /* Determine some common properties */
-                unsigned constant_mask = pan_blend_constant_mask(equation);
-                so->info[c] = (struct pan_blend_info) {
-                        .no_colour = (equation.color_mask == 0),
-                        .opaque = pan_blend_is_opaque(equation),
-                        .constant_mask = constant_mask,
-
-                        /* TODO: check the dest for the logicop */
-                        .load_dest = blend->logicop_enable ||
-                                pan_blend_reads_dest(equation),
-
-                        /* Could this possibly be fixed-function? */
-                        .fixed_function = !blend->logicop_enable &&
-                                pan_blend_can_fixed_function(equation) &&
-                                (!constant_mask ||
-                                 pan_blend_supports_constant(dev->arch, c))
-                };
-
-                so->pan.rts[c].equation = equation;
-
-                /* Bifrost needs to know if any render target loads its
-                 * destination in the hot draw path, so precompute this */
-                if (so->info[c].load_dest)
-                        so->load_dest_mask |= BITFIELD_BIT(c);
-
-                /* Converting equations to Mali style is expensive, do it at
-                 * CSO create time instead of draw-time */
-                if (so->info[c].fixed_function) {
-                        pan_pack(&so->equation[c], BLEND_EQUATION, cfg)
-                                pan_blend_to_fixed_function_equation(equation, &cfg);
-                }
-        }
-
-        return so;
-}
-
-static void
-panfrost_bind_blend_state(struct pipe_context *pipe, void *cso)
-{
-        struct panfrost_context *ctx = pan_context(pipe);
-        ctx->blend = cso;
-        ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER;
-}
-
-static void
-panfrost_delete_blend_state(struct pipe_context *pipe, void *cso)
-{
-        ralloc_free(cso);
-}
-
-static void
-panfrost_set_blend_color(struct pipe_context *pipe,
-                         const struct pipe_blend_color *blend_color)
-{
-        struct panfrost_context *ctx = pan_context(pipe);
-        ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER;
-
-        if (blend_color)
-                ctx->blend_color = *blend_color;
-}
-
-/* Create a final blend given the context */
-
-mali_ptr
-panfrost_get_blend(struct panfrost_batch *batch, unsigned rti, struct panfrost_bo **bo, unsigned *shader_offset)
-{
-        struct panfrost_context *ctx = batch->ctx;
-        struct panfrost_device *dev = pan_device(ctx->base.screen);
-        struct panfrost_blend_state *blend = ctx->blend;
-        struct pan_blend_info info = blend->info[rti];
-        struct pipe_surface *surf = batch->key.cbufs[rti];
-        enum pipe_format fmt = surf->format;
-
-        /* Use fixed-function if the equation permits, the format is blendable,
-         * and no more than one unique constant is accessed */
-        if (info.fixed_function && panfrost_blendable_formats[fmt].internal &&
-                        pan_blend_is_homogenous_constant(info.constant_mask,
-                                ctx->blend_color.color)) {
-                return 0;
-        }
-
-        /* Otherwise, we need to grab a shader */
-        struct pan_blend_state pan_blend = blend->pan;
-        unsigned nr_samples = surf->nr_samples ? : surf->texture->nr_samples;
-
-        pan_blend.rts[rti].format = fmt;
-        pan_blend.rts[rti].nr_samples = nr_samples;
-        memcpy(pan_blend.constants, ctx->blend_color.color,
-               sizeof(pan_blend.constants));
-
-        /* Upload the shader, sharing a BO */
-        if (!(*bo)) {
-                *bo = panfrost_batch_create_bo(batch, 4096, PAN_BO_EXECUTE,
-                                PIPE_SHADER_FRAGMENT, "Blend shader");
-        }
-
-        struct panfrost_shader_state *ss = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
-
-        /* Default for Midgard */
-        nir_alu_type col0_type = nir_type_float32;
-        nir_alu_type col1_type = nir_type_float32;
-
-        /* Bifrost has per-output types, respect them */
-        if (pan_is_bifrost(dev)) {
-                col0_type = ss->info.bifrost.blend[rti].type;
-                col1_type = ss->info.bifrost.blend_src1_type;
-        }
-
-        pthread_mutex_lock(&dev->blend_shaders.lock);
-        struct pan_blend_shader_variant *shader =
-                pan_blend_get_shader_locked(dev, &pan_blend,
-                                col0_type, col1_type, rti);
-
-        /* Size check and upload */
-        unsigned offset = *shader_offset;
-        assert((offset + shader->binary.size) < 4096);
-        memcpy((*bo)->ptr.cpu + offset, shader->binary.data, shader->binary.size);
-        *shader_offset += shader->binary.size;
-        pthread_mutex_unlock(&dev->blend_shaders.lock);
-
-        return ((*bo)->ptr.gpu + offset) | shader->first_tag;
-}
-
-void
-panfrost_blend_context_init(struct pipe_context *pipe)
-{
-        pipe->create_blend_state = panfrost_create_blend_state;
-        pipe->bind_blend_state   = panfrost_bind_blend_state;
-        pipe->delete_blend_state = panfrost_delete_blend_state;
-
-        pipe->set_blend_color = panfrost_set_blend_color;
-}
diff --git a/src/gallium/drivers/panfrost/pan_blend_cso.h b/src/gallium/drivers/panfrost/pan_blend_cso.h
index 5e7940f5b16..ee2c7a350d1 100644
--- a/src/gallium/drivers/panfrost/pan_blend_cso.h
+++ b/src/gallium/drivers/panfrost/pan_blend_cso.h
@@ -52,9 +52,6 @@ struct panfrost_blend_state {
         unsigned load_dest_mask : PIPE_MAX_COLOR_BUFS;
 };
 
-void
-panfrost_blend_context_init(struct pipe_context *pipe);
-
 mali_ptr
 panfrost_get_blend(struct panfrost_batch *batch, unsigned rt, struct panfrost_bo **bo, unsigned *shader_offset);
 
diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c
index 84d1865eb9a..e5f972ff3d5 100644
--- a/src/gallium/drivers/panfrost/pan_cmdstream.c
+++ b/src/gallium/drivers/panfrost/pan_cmdstream.c
@@ -30,6 +30,7 @@
 #include "util/u_draw.h"
 #include "util/u_memory.h"
 #include "indices/u_primconvert.h"
+#include "gallium/auxiliary/util/u_blend.h"
 
 #include "panfrost-quirks.h"
 
@@ -3423,6 +3424,104 @@ panfrost_create_sampler_view(
         return (struct pipe_sampler_view *) so;
 }
 
+/* A given Gallium blend state can be encoded to the hardware in numerous,
+ * dramatically divergent ways due to the interactions of blending with
+ * framebuffer formats. Conceptually, there are two modes:
+ *
+ * - Fixed-function blending (for suitable framebuffer formats, suitable blend
+ *   state, and suitable blend constant)
+ *
+ * - Blend shaders (for everything else)
+ *
+ * A given Gallium blend configuration will compile to exactly one
+ * fixed-function blend state, if it compiles to any, although the constant
+ * will vary across runs as that is tracked outside of the Gallium CSO.
+ *
+ * However, that same blend configuration will compile to many different blend
+ * shaders, depending on the framebuffer formats active. The rationale is that
+ * blend shaders override not just fixed-function blending but also
+ * fixed-function format conversion, so blend shaders are keyed to a particular
+ * framebuffer format. As an example, the tilebuffer format is identical for
+ * RG16F and RG16UI -- both are simply 32-bit raw pixels -- so both require
+ * blend shaders.
+ *
+ * All of this state is encapsulated in the panfrost_blend_state struct
+ * (our subclass of pipe_blend_state).
+ */
+
+/* Create a blend CSO. Essentially, try to compile a fixed-function
+ * expression and initialize blend shaders */
+
+static void *
+panfrost_create_blend_state(struct pipe_context *pipe,
+                            const struct pipe_blend_state *blend)
+{
+        struct panfrost_context *ctx = pan_context(pipe);
+        struct panfrost_device *dev = pan_device(pipe->screen);
+        struct panfrost_blend_state *so = rzalloc(ctx, struct panfrost_blend_state);
+        so->base = *blend;
+
+        so->pan.logicop_enable = blend->logicop_enable;
+        so->pan.logicop_func = blend->logicop_func;
+        so->pan.rt_count = blend->max_rt + 1;
+
+        for (unsigned c = 0; c < so->pan.rt_count; ++c) {
+                unsigned g = blend->independent_blend_enable ? c : 0;
+                const struct pipe_rt_blend_state pipe = blend->rt[g];
+                struct pan_blend_equation equation;
+
+                equation.color_mask = pipe.colormask;
+                equation.blend_enable = pipe.blend_enable;
+
+                if (pipe.blend_enable) {
+                        equation.rgb_func = util_blend_func_to_shader(pipe.rgb_func);
+                        equation.rgb_src_factor = util_blend_factor_to_shader(pipe.rgb_src_factor);
+                        equation.rgb_invert_src_factor = util_blend_factor_is_inverted(pipe.rgb_src_factor);
+                        equation.rgb_dst_factor = util_blend_factor_to_shader(pipe.rgb_dst_factor);
+                        equation.rgb_invert_dst_factor = util_blend_factor_is_inverted(pipe.rgb_dst_factor);
+                        equation.alpha_func = util_blend_func_to_shader(pipe.alpha_func);
+                        equation.alpha_src_factor = util_blend_factor_to_shader(pipe.alpha_src_factor);
+                        equation.alpha_invert_src_factor = util_blend_factor_is_inverted(pipe.alpha_src_factor);
+                        equation.alpha_dst_factor = util_blend_factor_to_shader(pipe.alpha_dst_factor);
+                        equation.alpha_invert_dst_factor = util_blend_factor_is_inverted(pipe.alpha_dst_factor);
+                }
+
+                /* Determine some common properties */
+                unsigned constant_mask = pan_blend_constant_mask(equation);
+                so->info[c] = (struct pan_blend_info) {
+                        .no_colour = (equation.color_mask == 0),
+                        .opaque = pan_blend_is_opaque(equation),
+                        .constant_mask = constant_mask,
+
+                        /* TODO: check the dest for the logicop */
+                        .load_dest = blend->logicop_enable ||
+                                pan_blend_reads_dest(equation),
+
+                        /* Could this possibly be fixed-function? */
+                        .fixed_function = !blend->logicop_enable &&
+                                pan_blend_can_fixed_function(equation) &&
+                                (!constant_mask ||
+                                 pan_blend_supports_constant(dev->arch, c))
+                };
+
+                so->pan.rts[c].equation = equation;
+
+                /* Bifrost needs to know if any render target loads its
+                 * destination in the hot draw path, so precompute this */
+                if (so->info[c].load_dest)
+                        so->load_dest_mask |= BITFIELD_BIT(c);
+
+                /* Converting equations to Mali style is expensive, do it at
+                 * CSO create time instead of draw-time */
+                if (so->info[c].fixed_function) {
+                        pan_pack(&so->equation[c], BLEND_EQUATION, cfg)
+                                pan_blend_to_fixed_function_equation(equation, &cfg);
+                }
+        }
+
+        return so;
+}
+
 static void
 prepare_rsd(struct panfrost_device *dev,
             struct panfrost_shader_state *state,
@@ -3459,4 +3558,5 @@ panfrost_cmdstream_context_init(struct pipe_context *pipe)
         pipe->create_depth_stencil_alpha_state = panfrost_create_depth_stencil_state;
         pipe->create_sampler_view = panfrost_create_sampler_view;
         pipe->create_sampler_state = panfrost_create_sampler_state;
+        pipe->create_blend_state = panfrost_create_blend_state;
 }
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index dbce6fd7cbd..04659fe6eff 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -134,6 +134,93 @@ panfrost_generic_cso_delete(struct pipe_context *pctx, void *hwcso)
         free(hwcso);
 }
 
+static void
+panfrost_bind_blend_state(struct pipe_context *pipe, void *cso)
+{
+        struct panfrost_context *ctx = pan_context(pipe);
+        ctx->blend = cso;
+        ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER;
+}
+
+static void
+panfrost_delete_blend_state(struct pipe_context *pipe, void *cso)
+{
+        ralloc_free(cso);
+}
+
+static void
+panfrost_set_blend_color(struct pipe_context *pipe,
+                         const struct pipe_blend_color *blend_color)
+{
+        struct panfrost_context *ctx = pan_context(pipe);
+        ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER;
+
+        if (blend_color)
+                ctx->blend_color = *blend_color;
+}
+
+/* Create a final blend given the context */
+
+mali_ptr
+panfrost_get_blend(struct panfrost_batch *batch, unsigned rti, struct panfrost_bo **bo, unsigned *shader_offset)
+{
+        struct panfrost_context *ctx = batch->ctx;
+        struct panfrost_device *dev = pan_device(ctx->base.screen);
+        struct panfrost_blend_state *blend = ctx->blend;
+        struct pan_blend_info info = blend->info[rti];
+        struct pipe_surface *surf = batch->key.cbufs[rti];
+        enum pipe_format fmt = surf->format;
+
+        /* Use fixed-function if the equation permits, the format is blendable,
+         * and no more than one unique constant is accessed */
+        if (info.fixed_function && panfrost_blendable_formats[fmt].internal &&
+                        pan_blend_is_homogenous_constant(info.constant_mask,
+                                ctx->blend_color.color)) {
+                return 0;
+        }
+
+        /* Otherwise, we need to grab a shader */
+        struct pan_blend_state pan_blend = blend->pan;
+        unsigned nr_samples = surf->nr_samples ? : surf->texture->nr_samples;
+
+        pan_blend.rts[rti].format = fmt;
+        pan_blend.rts[rti].nr_samples = nr_samples;
+        memcpy(pan_blend.constants, ctx->blend_color.color,
+               sizeof(pan_blend.constants));
+
+        /* Upload the shader, sharing a BO */
+        if (!(*bo)) {
+                *bo = panfrost_batch_create_bo(batch, 4096, PAN_BO_EXECUTE,
+                                PIPE_SHADER_FRAGMENT, "Blend shader");
+        }
+
+        struct panfrost_shader_state *ss = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
+
+        /* Default for Midgard */
+        nir_alu_type col0_type = nir_type_float32;
+        nir_alu_type col1_type = nir_type_float32;
+
+        /* Bifrost has per-output types, respect them */
+        if (pan_is_bifrost(dev)) {
+                col0_type = ss->info.bifrost.blend[rti].type;
+                col1_type = ss->info.bifrost.blend_src1_type;
+        }
+
+        pthread_mutex_lock(&dev->blend_shaders.lock);
+        struct pan_blend_shader_variant *shader =
+                pan_blend_get_shader_locked(dev, &pan_blend,
+                                col0_type, col1_type, rti);
+
+        /* Size check and upload */
+        unsigned offset = *shader_offset;
+        assert((offset + shader->binary.size) < 4096);
+        memcpy((*bo)->ptr.cpu + offset, shader->binary.data, shader->binary.size);
+        *shader_offset += shader->binary.size;
+        pthread_mutex_unlock(&dev->blend_shaders.lock);
+
+        return ((*bo)->ptr.gpu + offset) | shader->first_tag;
+}
+
 static void
 panfrost_bind_rasterizer_state(
         struct pipe_context *pctx,
@@ -1031,9 +1118,13 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
         gallium->stream_output_target_destroy = panfrost_stream_output_target_destroy;
         gallium->set_stream_output_targets = panfrost_set_stream_output_targets;
 
+        gallium->bind_blend_state   = panfrost_bind_blend_state;
+        gallium->delete_blend_state = panfrost_delete_blend_state;
+
+        gallium->set_blend_color = panfrost_set_blend_color;
+
         panfrost_cmdstream_context_init(gallium);
         panfrost_resource_context_init(gallium);
-        panfrost_blend_context_init(gallium);
         panfrost_compute_context_init(gallium);
 
         gallium->stream_uploader = u_upload_create_default(gallium);



More information about the mesa-commit mailing list