diff --git a/src/gallium/drivers/panfrost/pan_blend_cso.c b/src/gallium/drivers/panfrost/pan_blend_cso.c index e7c4bd87d2a..fca7e64a022 100644 --- a/src/gallium/drivers/panfrost/pan_blend_cso.c +++ b/src/gallium/drivers/panfrost/pan_blend_cso.c @@ -144,10 +144,16 @@ panfrost_get_blend_for_context(struct panfrost_context *ctx, unsigned rti, struc sizeof(pan_blend.constants)); /* First, we'll try fixed function, matching equation and constant */ - if (pan_blend_can_fixed_function(dev, &pan_blend, rti)) { - const struct pan_blend_equation eq = pan_blend.rts[rti].equation; - unsigned constant_mask = pan_blend_constant_mask(eq); + const struct pan_blend_equation eq = pan_blend.rts[rti].equation; + unsigned constant_mask = pan_blend_constant_mask(eq); + 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; + ff &= panfrost_blendable_formats[fmt].internal; + + 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), diff --git a/src/panfrost/lib/pan_blend.c b/src/panfrost/lib/pan_blend.c index 2eabfc10513..21810e33ae9 100644 --- a/src/panfrost/lib/pan_blend.c +++ b/src/panfrost/lib/pan_blend.c @@ -86,61 +86,34 @@ pan_blend_constant_mask(const struct pan_blend_equation eq) blend_factor_constant_mask(eq.alpha_dst_factor); } -static bool -can_blend_constant(const struct panfrost_device *dev, - const struct pan_blend_state *state, - unsigned rt) +/* Only "homogenous" (scalar or vector with all components equal) constants are + * valid for fixed-function, so check for this condition */ + +bool +pan_blend_is_homogenous_constant(unsigned mask, float *constants) { - unsigned constant_mask = pan_blend_constant_mask(state->rts[rt].equation); - if (!constant_mask) - return true; + float constant = pan_blend_get_constant(mask, constants); - /* v6 doesn't support blend constants in FF blend equations. */ - if (dev->arch == 6) - return false; - - /* v7 only uses the constant from RT 0 (TODO: what if it's the same - * constant? or a constant is shared?) */ - if (dev->arch == 7 && rt > 0) - return false; - - float constant = pan_blend_get_constant(constant_mask, state->constants); - - u_foreach_bit(i, constant_mask) { - if (state->constants[i] != constant) + u_foreach_bit(i, mask) { + if (constants[i] != constant) return false; } return true; } +/* Determines if an equation can run in fixed function */ + bool -pan_blend_can_fixed_function(const struct panfrost_device *dev, - const struct pan_blend_state *state, - unsigned rt) +pan_blend_can_fixed_function(const struct pan_blend_equation equation) { - const struct pan_blend_rt_state *rt_state = &state->rts[rt]; - - /* LogicOp requires a blend shader */ - if (state->logicop_enable) - return false; - - /* Not all formats can be blended by fixed-function hardware */ - if (!panfrost_blendable_formats[rt_state->format].internal) - return false; - - if (!rt_state->equation.blend_enable) - return true; - - if (!can_blend_constant(dev, state, rt)) - return false; - - return can_fixed_function_equation(rt_state->equation.rgb_func, - rt_state->equation.rgb_src_factor, - rt_state->equation.rgb_dst_factor) && - can_fixed_function_equation(rt_state->equation.alpha_func, - rt_state->equation.alpha_src_factor, - rt_state->equation.alpha_dst_factor); + return !equation.blend_enable || + (can_fixed_function_equation(equation.rgb_func, + equation.rgb_src_factor, + equation.rgb_dst_factor) && + can_fixed_function_equation(equation.alpha_func, + equation.alpha_src_factor, + equation.alpha_dst_factor)); } static enum mali_blend_operand_c @@ -312,8 +285,6 @@ pan_blend_to_fixed_function_equation(ASSERTED const struct panfrost_device *dev, { const struct pan_blend_rt_state *rt_state = &state->rts[rt]; - assert(pan_blend_can_fixed_function(dev, state, rt)); - /* If no blending is enabled, default back on `replace` mode */ if (!rt_state->equation.blend_enable) { equation->color_mask = rt_state->equation.color_mask; diff --git a/src/panfrost/lib/pan_blend.h b/src/panfrost/lib/pan_blend.h index bcba3e87a91..b97d3938f04 100644 --- a/src/panfrost/lib/pan_blend.h +++ b/src/panfrost/lib/pan_blend.h @@ -100,9 +100,7 @@ bool pan_blend_reads_dest(const struct pan_blend_equation eq); bool -pan_blend_can_fixed_function(const struct panfrost_device *dev, - const struct pan_blend_state *state, - unsigned rt); +pan_blend_can_fixed_function(const struct pan_blend_equation equation); bool pan_blend_is_opaque(const struct pan_blend_equation eq); @@ -120,6 +118,19 @@ pan_blend_get_constant(unsigned mask, float *constants) return mask ? constants[ffs(mask) - 1] : 0.0; } +/* v6 doesn't support blend constants in FF blend equations whatsoever, and v7 + * only uses the constant from RT 0 (TODO: what if it's the same constant? or a + * constant is shared?) */ + +static inline bool +pan_blend_supports_constant(unsigned arch, unsigned rt) +{ + return !((arch == 6) || (arch == 7 && rt > 0)); +} + +bool +pan_blend_is_homogenous_constant(unsigned mask, float *constants); + void pan_blend_to_fixed_function_equation(const struct panfrost_device *dev, const struct pan_blend_state *state,