From 0228ccf8579cd999eaa185df6945a349c01c6aa1 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 30 Jul 2021 19:28:37 -0400 Subject: [PATCH] panfrost: Leverage Bifrost's 2*src blend factor Bifrost adds a value for the C factor equaling 2*src. This does not correspond directly to API blend modes so it is not too useful in general. However, it's required for src*dest + dest*src blending to be done in hardware instead of a blend shader. GFXbench uses that blend mode, so it must be important ;-) Signed-off-by: Alyssa Rosenzweig Part-of: --- src/gallium/drivers/panfrost/pan_cmdstream.c | 4 +- src/panfrost/lib/pan_blend.c | 60 +++++++++++++++++--- src/panfrost/lib/pan_blend.h | 11 +++- src/panfrost/lib/tests/test-blend.c | 4 +- src/panfrost/vulkan/panvk_pipeline.c | 3 +- 5 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index cfc1413fa53..309a1dd21e4 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -3435,6 +3435,7 @@ panfrost_create_blend_state(struct pipe_context *pipe, /* Determine some common properties */ unsigned constant_mask = pan_blend_constant_mask(equation); + const bool supports_2src = pan_blend_supports_2src(PAN_ARCH); so->info[c] = (struct pan_blend_info) { .no_colour = (equation.color_mask == 0), .opaque = pan_blend_is_opaque(equation), @@ -3446,7 +3447,8 @@ panfrost_create_blend_state(struct pipe_context *pipe, /* Could this possibly be fixed-function? */ .fixed_function = !blend->logicop_enable && - pan_blend_can_fixed_function(equation) && + pan_blend_can_fixed_function(equation, + supports_2src) && (!constant_mask || pan_blend_supports_constant(PAN_ARCH, c)) }; diff --git a/src/panfrost/lib/pan_blend.c b/src/panfrost/lib/pan_blend.c index 38d3ab39d4c..083a58aab3d 100644 --- a/src/panfrost/lib/pan_blend.c +++ b/src/panfrost/lib/pan_blend.c @@ -47,11 +47,42 @@ factor_is_supported(enum blend_factor factor) factor != BLEND_FACTOR_SRC1_ALPHA; } +/* OpenGL allows encoding (src*dest + dest*src) which is incompatiblle with + * Midgard style blending since there are two multiplies. However, it may be + * factored as 2*src*dest = dest*(2*src), which can be encoded on Bifrost as 0 + * + dest * (2*src) wih the new source_2 value of C. Detect this case. */ + +static bool +is_2srcdest(enum blend_func blend_func, + enum blend_factor src_factor, + bool invert_src, + enum blend_factor dest_factor, + bool invert_dest, + bool is_alpha) +{ + return (blend_func == BLEND_FUNC_ADD) && + ((src_factor == BLEND_FACTOR_DST_COLOR) || + ((src_factor == BLEND_FACTOR_DST_ALPHA) && is_alpha)) && + ((dest_factor == BLEND_FACTOR_SRC_COLOR) || + ((dest_factor == BLEND_FACTOR_SRC_ALPHA) && is_alpha)) && + !invert_src && !invert_dest; +} + static bool can_fixed_function_equation(enum blend_func blend_func, enum blend_factor src_factor, - enum blend_factor dest_factor) + bool invert_src, + enum blend_factor dest_factor, + bool invert_dest, + bool is_alpha, + bool supports_2src) { + if (is_2srcdest(blend_func, src_factor, invert_src, + dest_factor, invert_dest, is_alpha)) { + + return supports_2src; + } + if (blend_func != BLEND_FUNC_ADD && blend_func != BLEND_FUNC_SUBTRACT && blend_func != BLEND_FUNC_REVERSE_SUBTRACT) @@ -108,15 +139,22 @@ pan_blend_is_homogenous_constant(unsigned mask, const float *constants) /* Determines if an equation can run in fixed function */ bool -pan_blend_can_fixed_function(const struct pan_blend_equation equation) +pan_blend_can_fixed_function(const struct pan_blend_equation equation, + bool supports_2src) { return !equation.blend_enable || (can_fixed_function_equation(equation.rgb_func, equation.rgb_src_factor, - equation.rgb_dst_factor) && + equation.rgb_invert_src_factor, + equation.rgb_dst_factor, + equation.rgb_invert_dst_factor, + false, supports_2src) && can_fixed_function_equation(equation.alpha_func, equation.alpha_src_factor, - equation.alpha_dst_factor)); + equation.alpha_invert_src_factor, + equation.alpha_dst_factor, + equation.alpha_invert_dst_factor, + true, supports_2src)); } static enum mali_blend_operand_c @@ -153,9 +191,11 @@ to_panfrost_function(enum blend_func blend_func, bool invert_src, enum blend_factor dest_factor, bool invert_dest, + bool is_alpha, struct MALI_BLEND_FUNCTION *function) { - assert(can_fixed_function_equation(blend_func, src_factor, dest_factor)); + assert(can_fixed_function_equation(blend_func, src_factor, invert_src, + dest_factor, invert_dest, is_alpha, true)); if (src_factor == BLEND_FACTOR_ZERO && !invert_src) { function->a = MALI_BLEND_OPERAND_A_ZERO; @@ -207,6 +247,12 @@ to_panfrost_function(enum blend_func blend_func, default: unreachable("Invalid blend function"); } + } else if (is_2srcdest(blend_func, src_factor, invert_src, dest_factor, + invert_dest, is_alpha)) { + /* src*dest + dest*src = 2*src*dest = 0 + dest*(2*src) */ + function->a = MALI_BLEND_OPERAND_A_ZERO; + function->b = MALI_BLEND_OPERAND_B_DEST; + function->c = MALI_BLEND_OPERAND_C_SRC_X_2; } else { assert(src_factor == dest_factor && invert_src != invert_dest); @@ -308,14 +354,14 @@ pan_blend_to_fixed_function_equation(const struct pan_blend_equation equation, equation.rgb_invert_src_factor, equation.rgb_dst_factor, equation.rgb_invert_dst_factor, - &out->rgb); + false, &out->rgb); to_panfrost_function(equation.alpha_func, equation.alpha_src_factor, equation.alpha_invert_src_factor, equation.alpha_dst_factor, equation.alpha_invert_dst_factor, - &out->alpha); + true, &out->alpha); out->color_mask = equation.color_mask; } diff --git a/src/panfrost/lib/pan_blend.h b/src/panfrost/lib/pan_blend.h index 397022c7c6d..cb5cdac9578 100644 --- a/src/panfrost/lib/pan_blend.h +++ b/src/panfrost/lib/pan_blend.h @@ -99,7 +99,8 @@ bool pan_blend_reads_dest(const struct pan_blend_equation eq); bool -pan_blend_can_fixed_function(const struct pan_blend_equation equation); +pan_blend_can_fixed_function(const struct pan_blend_equation equation, + bool supports_2src); bool pan_blend_is_opaque(const struct pan_blend_equation eq); @@ -127,6 +128,14 @@ pan_blend_supports_constant(unsigned arch, unsigned rt) return !((arch == 6) || (arch == 7 && rt > 0)); } +/* The SOURCE_2 value is new in Bifrost */ + +static inline bool +pan_blend_supports_2src(unsigned arch) +{ + return (arch >= 6); +} + bool pan_blend_is_homogenous_constant(unsigned mask, const float *constants); diff --git a/src/panfrost/lib/tests/test-blend.c b/src/panfrost/lib/tests/test-blend.c index b088415f364..f61943dfe72 100644 --- a/src/panfrost/lib/tests/test-blend.c +++ b/src/panfrost/lib/tests/test-blend.c @@ -204,9 +204,9 @@ int main(int argc, const char **argv) ASSERT_EQ(T.constant_mask, pan_blend_constant_mask(T.eq)); ASSERT_EQ(T.reads_dest, pan_blend_reads_dest(T.eq)); ASSERT_EQ(T.opaque, pan_blend_is_opaque(T.eq)); - ASSERT_EQ(T.fixed_function, pan_blend_can_fixed_function(T.eq)); + ASSERT_EQ(T.fixed_function, pan_blend_can_fixed_function(T.eq, true)); - if (pan_blend_can_fixed_function(T.eq)) { + if (pan_blend_can_fixed_function(T.eq, true)) { ASSERT_EQ(T.hardware, pan_pack_blend(T.eq)); } } diff --git a/src/panfrost/vulkan/panvk_pipeline.c b/src/panfrost/vulkan/panvk_pipeline.c index b12aae573ce..8dbe76070a5 100644 --- a/src/panfrost/vulkan/panvk_pipeline.c +++ b/src/panfrost/vulkan/panvk_pipeline.c @@ -565,7 +565,8 @@ panvk_blend_needs_lowering(const struct panfrost_device *dev, if (!pan_blend_is_homogenous_constant(constant_mask, state->constants)) return true; - return !pan_blend_can_fixed_function(state->rts[rt].equation); + bool supports_2src = pan_blend_supports_2src(dev->arch); + return !pan_blend_can_fixed_function(state->rts[rt].equation, supports_2src); } static void