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@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12152>
This commit is contained in:
Alyssa Rosenzweig
2021-07-30 19:28:37 -04:00
committed by Marge Bot
parent 95e306dc84
commit 0228ccf857
5 changed files with 70 additions and 12 deletions
+3 -1
View File
@@ -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))
};
+53 -7
View File
@@ -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;
}
+10 -1
View File
@@ -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);
+2 -2
View File
@@ -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));
}
}
+2 -1
View File
@@ -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