From 3943adbd916fd36aec0f3abbf5164ba600546515 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 14 May 2021 12:55:49 -0400 Subject: [PATCH] panfrost: Move blend properties to CSO create Fixes: 93824b6451a ("panfrost: Move the blend logic out of the gallium driver") Signed-off-by: Alyssa Rosenzweig Part-of: --- src/gallium/drivers/panfrost/pan_blend_cso.c | 73 ++++++++++++-------- src/gallium/drivers/panfrost/pan_blend_cso.h | 18 ++--- src/gallium/drivers/panfrost/pan_cmdstream.c | 60 +++++++++------- 3 files changed, 90 insertions(+), 61 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_blend_cso.c b/src/gallium/drivers/panfrost/pan_blend_cso.c index cafd8aa9d9b..a4c996b6b22 100644 --- a/src/gallium/drivers/panfrost/pan_blend_cso.c +++ b/src/gallium/drivers/panfrost/pan_blend_cso.c @@ -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; + 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 (!equation->blend_enable) - continue; + equation.color_mask = pipe.colormask; + equation.blend_enable = 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); + 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; diff --git a/src/gallium/drivers/panfrost/pan_blend_cso.h b/src/gallium/drivers/panfrost/pan_blend_cso.h index 7cabaae388d..95c03c6c323 100644 --- a/src/gallium/drivers/panfrost/pan_blend_cso.h +++ b/src/gallium/drivers/panfrost/pan_blend_cso.h @@ -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; diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index b57177c7585..cf587a389e6 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -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 |