panfrost: Move blend properties to CSO create
authorAlyssa Rosenzweig <alyssa@collabora.com>
Fri, 14 May 2021 16:55:49 +0000 (12:55 -0400)
committerMarge Bot <eric+marge@anholt.net>
Tue, 18 May 2021 22:51:56 +0000 (22:51 +0000)
Fixes: 93824b6451a ("panfrost: Move the blend logic out of the gallium driver")
Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10869>

src/gallium/drivers/panfrost/pan_blend_cso.c
src/gallium/drivers/panfrost/pan_blend_cso.h
src/gallium/drivers/panfrost/pan_cmdstream.c

index cafd8aa..a4c996b 100644 (file)
@@ -66,6 +66,7 @@ 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;
 
@@ -76,24 +77,44 @@ panfrost_create_blend_state(struct pipe_context *pipe,
 
         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 = &so->pan.rts[c].equation;
-
-                equation->color_mask = pipe->colormask;
-                equation->blend_enable = pipe->blend_enable;
-                if (!equation->blend_enable)
-                        continue;
-
-                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);
+                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;
         }
 
         return so;
@@ -145,20 +166,20 @@ panfrost_get_blend_for_context(struct panfrost_context *ctx, unsigned rti, struc
 
         /* First, we'll try fixed function, matching equation and constant */
         const struct pan_blend_equation eq = pan_blend.rts[rti].equation;
-        unsigned constant_mask = pan_blend_constant_mask(eq);
+        bool ff = blend->info[rti].fixed_function;
 
-        bool ff = pan_blend_can_fixed_function(eq);
-        ff &= pan_blend_is_homogenous_constant(constant_mask, ctx->blend_color.color);
-        ff &= (pan_blend_supports_constant(dev->arch, rti) || !constant_mask);
-        ff &= !pan_blend.logicop_enable;
+        /* Not all formats are blendable, check if this one is */
         ff &= panfrost_blendable_formats[fmt].internal;
 
+        /* There are hazards around constants, check that */
+        ff &= pan_blend_is_homogenous_constant(blend->info[rti].constant_mask,
+                        ctx->blend_color.color);
+
         if (ff) {
                 struct panfrost_blend_final final = {
-                        .load_dest = pan_blend_reads_dest(pan_blend.rts[rti].equation),
-                        .equation.constant = pan_blend_get_constant(constant_mask, ctx->blend_color.color),
-                        .opaque = pan_blend_is_opaque(pan_blend.rts[rti].equation),
-                        .no_colour = pan_blend.rts[rti].equation.color_mask == 0,
+                        .equation.constant = pan_blend_get_constant(
+                                        blend->info[rti].constant_mask,
+                                        ctx->blend_color.color),
                 };
 
                 pan_blend_to_fixed_function_equation(eq, &final.equation.equation);
@@ -204,8 +225,6 @@ panfrost_get_blend_for_context(struct panfrost_context *ctx, unsigned rti, struc
                         .first_tag = shader->first_tag,
                         .gpu = (*bo)->ptr.gpu + *shader_offset,
                 },
-                .load_dest = pan_blend.logicop_enable ||
-                        pan_blend_reads_dest(pan_blend.rts[rti].equation),
         };
 
         *shader_offset += shader->binary.size;
index 7cabaae..95c03c6 100644 (file)
@@ -69,9 +69,18 @@ struct panfrost_blend_equation_final {
         float constant;
 };
 
+struct pan_blend_info {
+        unsigned constant_mask : 4;
+        bool fixed_function : 1;
+        bool no_colour : 1;
+        bool load_dest : 1;
+        bool opaque : 1;
+};
+
 struct panfrost_blend_state {
         struct pipe_blend_state base;
         struct pan_blend_state pan;
+        struct pan_blend_info info[PIPE_MAX_COLOR_BUFS];
 };
 
 /* Container for a final blend state, specialized to constants and a
@@ -81,15 +90,6 @@ struct panfrost_blend_final {
         /* Set for a shader, clear for an equation */
         bool is_shader;
 
-        /* Set if this is the replace mode */
-        bool opaque;
-
-        /* Set if destination is loaded */
-        bool load_dest;
-
-        /* Set if the colour mask is 0x0 (nothing is written) */
-        bool no_colour;
-
         union {
                 struct panfrost_blend_shader_final shader;
                 struct panfrost_blend_equation_final equation;
index b57177c..cf587a3 100644 (file)
@@ -260,7 +260,7 @@ void panfrost_sampler_desc_init_bifrost(const struct pipe_sampler_state *cso,
 static bool
 panfrost_fs_required(
                 struct panfrost_shader_state *fs,
-                struct panfrost_blend_final *blend,
+                struct panfrost_blend_state *blend,
                 struct pipe_framebuffer_state *state)
 {
         /* If we generally have side effects */
@@ -269,7 +269,7 @@ panfrost_fs_required(
 
         /* If colour is written we need to execute */
         for (unsigned i = 0; i < state->nr_cbufs; ++i) {
-                if (!blend[i].no_colour && state->cbufs[i])
+                if (state->cbufs[i] && !blend->info[i].no_colour)
                         return true;
         }
 
@@ -308,8 +308,10 @@ panfrost_emit_bifrost_blend(struct panfrost_batch *batch,
                             void *rts)
 {
         unsigned rt_count = batch->key.nr_cbufs;
-        const struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
-        struct panfrost_shader_state *fs = panfrost_get_shader_state(batch->ctx, PIPE_SHADER_FRAGMENT);
+        struct panfrost_context *ctx = batch->ctx;
+        const struct panfrost_blend_state *so = ctx->blend;
+        const struct panfrost_device *dev = pan_device(ctx->base.screen);
+        struct panfrost_shader_state *fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
 
         /* Always have at least one render target for depth-only passes */
         for (unsigned i = 0; i < MAX2(rt_count, 1); ++i) {
@@ -324,14 +326,16 @@ panfrost_emit_bifrost_blend(struct panfrost_batch *batch,
                 }
 
                 pan_pack(rts + i * MALI_BLEND_LENGTH, BLEND, cfg) {
-                        if (blend[i].no_colour) {
+                        struct pan_blend_info info = so->info[i];
+
+                        if (info.no_colour) {
                                 cfg.enable = false;
                         } else {
                                 cfg.srgb = util_format_is_srgb(batch->key.cbufs[i]->format);
-                                cfg.load_destination = blend[i].load_dest;
+                                cfg.load_destination = info.load_dest;
 
-                                cfg.round_to_fb_precision = !batch->ctx->blend->base.dither;
-                                cfg.alpha_to_one = batch->ctx->blend->base.alpha_to_one;
+                                cfg.round_to_fb_precision = !ctx->blend->base.dither;
+                                cfg.alpha_to_one = ctx->blend->base.alpha_to_one;
                         }
 
                         if (blend[i].is_shader) {
@@ -367,10 +371,9 @@ panfrost_emit_bifrost_blend(struct panfrost_batch *batch,
                                 constant <<= 16 - chan_size;
                                 cfg.bifrost.constant = constant;
 
-                                if (blend[i].opaque)
-                                        cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_OPAQUE;
-                                else
-                                        cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_FIXED_FUNCTION;
+                                cfg.bifrost.internal.mode = info.opaque ?
+                                        MALI_BIFROST_BLEND_MODE_OPAQUE :
+                                        MALI_BIFROST_BLEND_MODE_FIXED_FUNCTION;
 
                                 /* If we want the conversion to work properly,
                                  * num_comps must be set to 4
@@ -392,6 +395,8 @@ panfrost_emit_midgard_blend(struct panfrost_batch *batch,
                             void *rts)
 {
         unsigned rt_count = batch->key.nr_cbufs;
+        struct panfrost_context *ctx = batch->ctx;
+        const struct panfrost_blend_state *so = ctx->blend;
 
         /* Always have at least one render target for depth-only passes */
         for (unsigned i = 0; i < MAX2(rt_count, 1); ++i) {
@@ -411,15 +416,17 @@ panfrost_emit_midgard_blend(struct panfrost_batch *batch,
                 }
 
                 pan_pack(rts + i * MALI_BLEND_LENGTH, BLEND, cfg) {
-                        if (blend[i].no_colour) {
+                        struct pan_blend_info info = so->info[i];
+
+                        if (info.no_colour) {
                                 cfg.enable = false;
                                 continue;
                         }
 
                         cfg.srgb = util_format_is_srgb(batch->key.cbufs[i]->format);
-                        cfg.load_destination = blend[i].load_dest;
-                        cfg.round_to_fb_precision = !batch->ctx->blend->base.dither;
-                        cfg.alpha_to_one = batch->ctx->blend->base.alpha_to_one;
+                        cfg.load_destination = info.load_dest;
+                        cfg.round_to_fb_precision = !ctx->blend->base.dither;
+                        cfg.alpha_to_one = ctx->blend->base.alpha_to_one;
                         cfg.midgard.blend_shader = blend[i].is_shader;
                         if (blend[i].is_shader) {
                                 cfg.midgard.shader_pc = blend[i].shader.gpu | blend[i].shader.first_tag;
@@ -436,6 +443,7 @@ panfrost_emit_blend(struct panfrost_batch *batch, void *rts,
                 struct panfrost_blend_final *blend)
 {
         const struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
+        struct panfrost_blend_state *so = batch->ctx->blend;
 
         if (pan_is_bifrost(dev))
                 panfrost_emit_bifrost_blend(batch, blend, rts);
@@ -443,7 +451,7 @@ panfrost_emit_blend(struct panfrost_batch *batch, void *rts,
                 panfrost_emit_midgard_blend(batch, blend, rts);
 
         for (unsigned i = 0; i < batch->key.nr_cbufs; ++i) {
-                if (!blend[i].no_colour && batch->key.cbufs[i]) {
+                if (!so->info[i].no_colour && batch->key.cbufs[i]) {
                         batch->draws |= (PIPE_CLEAR_COLOR0 << i);
                         batch->resolve |= (PIPE_CLEAR_COLOR0 << i);
                 }
@@ -457,9 +465,10 @@ panfrost_prepare_bifrost_fs_state(struct panfrost_context *ctx,
 {
         const struct panfrost_device *dev = pan_device(ctx->base.screen);
         struct panfrost_shader_state *fs = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
-        bool alpha_to_coverage = ctx->blend->base.alpha_to_coverage;
+        struct panfrost_blend_state *so = ctx->blend;
+        bool alpha_to_coverage = so->base.alpha_to_coverage;
 
-        if (!panfrost_fs_required(fs, blend, &ctx->pipe_framebuffer)) {
+        if (!panfrost_fs_required(fs, so, &ctx->pipe_framebuffer)) {
                 state->properties.bifrost.shader_modifies_coverage = true;
                 state->properties.bifrost.allow_forward_pixel_to_kill = true;
                 state->properties.bifrost.allow_forward_pixel_to_be_killed = true;
@@ -475,7 +484,7 @@ panfrost_prepare_bifrost_fs_state(struct panfrost_context *ctx,
                 for (unsigned i = 0; i < ctx->pipe_framebuffer.nr_cbufs; ++i) {
                         if (ctx->pipe_framebuffer.cbufs[i]) {
                                 rt_mask |= (1 << i);
-                                blend_reads_dest |= blend[i].load_dest;
+                                blend_reads_dest |= so->info[i].load_dest;
                         }
                 }
 
@@ -505,7 +514,7 @@ panfrost_prepare_midgard_fs_state(struct panfrost_context *ctx,
         unsigned rt_count = ctx->pipe_framebuffer.nr_cbufs;
         bool alpha_to_coverage = ctx->blend->base.alpha_to_coverage;
 
-        if (!panfrost_fs_required(fs, blend, &ctx->pipe_framebuffer)) {
+        if (!panfrost_fs_required(fs, ctx->blend, &ctx->pipe_framebuffer)) {
                 state->shader.shader = 0x1;
                 state->properties.midgard.work_register_count = 1;
                 state->properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION;
@@ -548,12 +557,13 @@ panfrost_prepare_midgard_fs_state(struct panfrost_context *ctx,
         }
 
         if (dev->quirks & MIDGARD_SFBD && ctx->pipe_framebuffer.nr_cbufs > 0) {
-                state->multisample_misc.sfbd_load_destination = blend[0].load_dest;
+                struct panfrost_blend_state *so = ctx->blend;
+                state->multisample_misc.sfbd_load_destination = so->info[0].load_dest;
                 state->multisample_misc.sfbd_blend_shader = blend[0].is_shader;
-                state->stencil_mask_misc.sfbd_write_enable = !blend[0].no_colour;
+                state->stencil_mask_misc.sfbd_write_enable = !so->info[0].no_colour;
                 state->stencil_mask_misc.sfbd_srgb = util_format_is_srgb(ctx->pipe_framebuffer.cbufs[0]->format);
-                state->stencil_mask_misc.sfbd_dither_disable = !ctx->blend->base.dither;
-                state->stencil_mask_misc.sfbd_alpha_to_one = ctx->blend->base.alpha_to_one;
+                state->stencil_mask_misc.sfbd_dither_disable = !so->base.dither;
+                state->stencil_mask_misc.sfbd_alpha_to_one = so->base.alpha_to_one;
 
                 if (blend[0].is_shader) {
                         state->sfbd_blend_shader = blend[0].shader.gpu |