Mesa (main): panfrost: Leverage Bifrost's 2*src blend factor

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Aug 11 18:32:48 UTC 2021


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

Author: Alyssa Rosenzweig <alyssa at collabora.com>
Date:   Fri Jul 30 19:28:37 2021 -0400

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 <alyssa at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12152>

---

 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



More information about the mesa-commit mailing list