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:
committed by
Marge Bot
parent
95e306dc84
commit
0228ccf857
@@ -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))
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user