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