panfrost: Rework fixed-function blending
The fixed-function blend logic uses the following equation: A + B x C. A, B and C are configurable and can be complemented with negation (for A and B) or inversion (for C) modifiers. Let's rework the blending code to take that into account. Note that we need to update the checksum of a few traces because the equations we use have changed, leading to small deviations on the final images. Indeed, there are several valid options for a given GL blend equation, but the operand selection probably has an impact on the rounding, leading to those mismatch. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6980>
This commit is contained in:
parent
f2044044e6
commit
713419eef0
|
@ -45,9 +45,9 @@ traces:
|
||||||
- path: gputest/triangle.trace
|
- path: gputest/triangle.trace
|
||||||
expectations:
|
expectations:
|
||||||
- device: gl-panfrost-t860
|
- device: gl-panfrost-t860
|
||||||
checksum: 6def0c34ade7d4ec930b45d0eef6e46a
|
checksum: 75c5a2e261d576d115a659f6cd52a90d
|
||||||
- device: gl-panfrost-t760
|
- device: gl-panfrost-t760
|
||||||
checksum: 6def0c34ade7d4ec930b45d0eef6e46a
|
checksum: 75c5a2e261d576d115a659f6cd52a90d
|
||||||
- path: humus/Portals.trace
|
- path: humus/Portals.trace
|
||||||
expectations:
|
expectations:
|
||||||
- device: gl-panfrost-t860
|
- device: gl-panfrost-t860
|
||||||
|
@ -190,11 +190,11 @@ traces:
|
||||||
- path: gputest/pixmark-julia-fp32.trace
|
- path: gputest/pixmark-julia-fp32.trace
|
||||||
expectations:
|
expectations:
|
||||||
- device: gl-panfrost-t860
|
- device: gl-panfrost-t860
|
||||||
checksum: 03c268b0afaf341b4d8226cc6892273a
|
checksum: d85b6967b7c768f28395c5c5dfbcfe3e
|
||||||
- path: gputest/plot3d.trace
|
- path: gputest/plot3d.trace
|
||||||
expectations:
|
expectations:
|
||||||
- device: gl-panfrost-t860
|
- device: gl-panfrost-t860
|
||||||
checksum: 522afab0fd4bbabbc2f78735646069d8
|
checksum: 991efbfd046f70e1fd965d3983bb2965
|
||||||
- path: humus/AmbientAperture.trace
|
- path: humus/AmbientAperture.trace
|
||||||
expectations:
|
expectations:
|
||||||
- device: gl-panfrost-t860
|
- device: gl-panfrost-t860
|
||||||
|
|
|
@ -68,7 +68,7 @@ struct panfrost_blend_shader_final {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct panfrost_blend_equation_final {
|
struct panfrost_blend_equation_final {
|
||||||
struct mali_blend_equation_packed equation;
|
struct MALI_BLEND_EQUATION equation;
|
||||||
float constant;
|
float constant;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ struct panfrost_blend_rt {
|
||||||
* fixed-function configuration for this blend state */
|
* fixed-function configuration for this blend state */
|
||||||
|
|
||||||
bool has_fixed_function;
|
bool has_fixed_function;
|
||||||
struct mali_blend_equation_packed equation;
|
struct MALI_BLEND_EQUATION equation;
|
||||||
|
|
||||||
/* Mask of blend color components read */
|
/* Mask of blend color components read */
|
||||||
unsigned constant_mask;
|
unsigned constant_mask;
|
||||||
|
|
|
@ -129,8 +129,17 @@ panfrost_create_blend_state(struct pipe_context *pipe,
|
||||||
&rt->equation,
|
&rt->equation,
|
||||||
&rt->constant_mask);
|
&rt->constant_mask);
|
||||||
|
|
||||||
if (rt->has_fixed_function)
|
if (rt->has_fixed_function) {
|
||||||
rt->opaque = (rt->equation.opaque[0] == 0xf0122122);
|
rt->opaque = pipe.rgb_src_factor == PIPE_BLENDFACTOR_ONE &&
|
||||||
|
pipe.rgb_dst_factor == PIPE_BLENDFACTOR_ZERO &&
|
||||||
|
(pipe.rgb_func == PIPE_BLEND_ADD ||
|
||||||
|
pipe.rgb_func == PIPE_BLEND_SUBTRACT) &&
|
||||||
|
pipe.alpha_src_factor == PIPE_BLENDFACTOR_ONE &&
|
||||||
|
pipe.alpha_dst_factor == PIPE_BLENDFACTOR_ZERO &&
|
||||||
|
(pipe.alpha_func == PIPE_BLEND_ADD ||
|
||||||
|
pipe.alpha_func == PIPE_BLEND_SUBTRACT) &&
|
||||||
|
pipe.colormask == 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
rt->load_dest = util_blend_uses_dest(pipe)
|
rt->load_dest = util_blend_uses_dest(pipe)
|
||||||
|| pipe.colormask != 0xF;
|
|| pipe.colormask != 0xF;
|
||||||
|
|
|
@ -28,76 +28,7 @@
|
||||||
#include "gallium/auxiliary/util/u_blend.h"
|
#include "gallium/auxiliary/util/u_blend.h"
|
||||||
#include "util/format/u_format.h"
|
#include "util/format/u_format.h"
|
||||||
|
|
||||||
/*
|
/* Implements fixed-function blending on Midgard. */
|
||||||
* Implements fixed-function blending on Midgard.
|
|
||||||
*
|
|
||||||
* Midgard splits blending into a fixed-function fast path and a programmable
|
|
||||||
* slow path. The fixed function blending architecture is based on "dominant"
|
|
||||||
* blend factors. Blending is encoded separately (but identically) between RGB
|
|
||||||
* and alpha functions.
|
|
||||||
*
|
|
||||||
* Essentially, for a given blending operation, there is a single dominant
|
|
||||||
* factor. The following dominant factors are possible:
|
|
||||||
*
|
|
||||||
* - zero
|
|
||||||
* - source color
|
|
||||||
* - destination color
|
|
||||||
* - source alpha
|
|
||||||
* - destination alpha
|
|
||||||
* - constant float
|
|
||||||
*
|
|
||||||
* Further, a dominant factor's arithmetic compliment could be used. For
|
|
||||||
* instance, to encode GL_ONE_MINUS_SOURCE_ALPHA, the dominant factor would be
|
|
||||||
* MALI_DOMINANT_SRC_ALPHA with the complement_dominant bit set.
|
|
||||||
*
|
|
||||||
* A single constant float can be passed to the fixed-function hardware,
|
|
||||||
* allowing CONSTANT_ALPHA support. Further, if all components of the constant
|
|
||||||
* glBlendColor are identical, CONSTANT_COLOR can be implemented with the
|
|
||||||
* constant float mode. If the components differ, programmable blending is
|
|
||||||
* required.
|
|
||||||
*
|
|
||||||
* The nondominant factor can be either:
|
|
||||||
*
|
|
||||||
* - the same as the dominant factor (MALI_BLEND_NON_MIRROR)
|
|
||||||
* - zero (MALI_BLEND_NON_ZERO)
|
|
||||||
*
|
|
||||||
* Exactly one of the blend operation's source or destination can be used as
|
|
||||||
* the dominant factor; this is selected by the
|
|
||||||
* MALI_BLEND_DOM_SOURCE/DESTINATION flag.
|
|
||||||
*
|
|
||||||
* By default, all blending follows the standard OpenGL addition equation:
|
|
||||||
*
|
|
||||||
* out = source_value * source_factor + destination_value * destination_factor
|
|
||||||
*
|
|
||||||
* By setting the negate_source or negate_dest bits, other blend functions can
|
|
||||||
* be created. For instance, for SUBTRACT mode, set the "negate destination"
|
|
||||||
* flag, and similarly for REVERSE_SUBTRACT with "negate source".
|
|
||||||
*
|
|
||||||
* Finally, there is a "clip modifier" controlling the final blending
|
|
||||||
* behaviour, allowing for the following modes:
|
|
||||||
*
|
|
||||||
* - normal
|
|
||||||
* - force source factor to one (MALI_BLEND_MODE_SOURCE_ONE)
|
|
||||||
* - force destination factor to one (MALI_BLEND_MODE_DEST_ONE)
|
|
||||||
*
|
|
||||||
* The clipping flags can be used to encode blend modes where the nondominant
|
|
||||||
* factor is ONE.
|
|
||||||
*
|
|
||||||
* As an example putting it all together, to encode the following blend state:
|
|
||||||
*
|
|
||||||
* glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
|
||||||
* glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE);
|
|
||||||
*
|
|
||||||
* We need the following configuration:
|
|
||||||
*
|
|
||||||
* - negate source (for REVERSE_SUBTRACT)
|
|
||||||
* - dominant factor "source alpha"
|
|
||||||
* - complement dominant
|
|
||||||
* - source dominant
|
|
||||||
* - force destination to ONE
|
|
||||||
*
|
|
||||||
* The following routines implement this fixed function blending encoding
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Not all formats can be blended by fixed-function hardware */
|
/* Not all formats can be blended by fixed-function hardware */
|
||||||
|
|
||||||
|
@ -161,54 +92,6 @@ uncomplement_factor(int factor)
|
||||||
return (complement == -1) ? factor : complement;
|
return (complement == -1) ? factor : complement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Attempt to find the dominant factor given a particular factor, complementing
|
|
||||||
* as necessary */
|
|
||||||
|
|
||||||
static bool
|
|
||||||
panfrost_make_dominant_factor(unsigned src_factor, enum mali_dominant_factor *factor)
|
|
||||||
{
|
|
||||||
switch (src_factor) {
|
|
||||||
case PIPE_BLENDFACTOR_SRC_COLOR:
|
|
||||||
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
|
|
||||||
*factor = MALI_DOMINANT_SRC_COLOR;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
|
||||||
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
|
|
||||||
*factor = MALI_DOMINANT_SRC_ALPHA;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PIPE_BLENDFACTOR_DST_COLOR:
|
|
||||||
case PIPE_BLENDFACTOR_INV_DST_COLOR:
|
|
||||||
*factor = MALI_DOMINANT_DST_COLOR;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PIPE_BLENDFACTOR_DST_ALPHA:
|
|
||||||
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
|
|
||||||
*factor = MALI_DOMINANT_DST_ALPHA;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PIPE_BLENDFACTOR_ONE:
|
|
||||||
case PIPE_BLENDFACTOR_ZERO:
|
|
||||||
*factor = MALI_DOMINANT_ZERO;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
|
||||||
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
|
|
||||||
case PIPE_BLENDFACTOR_CONST_COLOR:
|
|
||||||
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
|
|
||||||
*factor = MALI_DOMINANT_CONSTANT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* Fancy blend modes not supported */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if this is a special edge case blend factor, which may require the use
|
/* Check if this is a special edge case blend factor, which may require the use
|
||||||
* of clip modifiers */
|
* of clip modifiers */
|
||||||
|
|
||||||
|
@ -218,98 +101,154 @@ is_edge_blendfactor(unsigned factor)
|
||||||
return factor == PIPE_BLENDFACTOR_ONE || factor == PIPE_BLENDFACTOR_ZERO;
|
return factor == PIPE_BLENDFACTOR_ONE || factor == PIPE_BLENDFACTOR_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the actual fixed function encoding. Encode the function with negate
|
static bool
|
||||||
* bits. Check for various cases to work out the dominant/nondominant split and
|
factor_is_supported(unsigned factor)
|
||||||
* accompanying flags. */
|
{
|
||||||
|
return factor != PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE &&
|
||||||
|
factor != PIPE_BLENDFACTOR_SRC1_COLOR &&
|
||||||
|
factor != PIPE_BLENDFACTOR_SRC1_ALPHA &&
|
||||||
|
factor != PIPE_BLENDFACTOR_INV_SRC1_COLOR &&
|
||||||
|
factor != PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
panfrost_make_fixed_blend_part(unsigned func, unsigned src_factor, unsigned dst_factor, unsigned *out)
|
can_use_fixed_function_blend(unsigned blend_func,
|
||||||
|
unsigned src_factor,
|
||||||
|
unsigned dest_factor)
|
||||||
{
|
{
|
||||||
struct mali_blend_mode part = { 0 };
|
if (blend_func != PIPE_BLEND_ADD &&
|
||||||
|
blend_func != PIPE_BLEND_SUBTRACT &&
|
||||||
|
blend_func != PIPE_BLEND_REVERSE_SUBTRACT)
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Make sure that the blend function is representible */
|
if (!factor_is_supported(src_factor) ||
|
||||||
|
!factor_is_supported(dest_factor))
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (func) {
|
if (src_factor != dest_factor &&
|
||||||
case PIPE_BLEND_ADD:
|
src_factor != complement_factor(dest_factor) &&
|
||||||
|
complement_factor(src_factor) != dest_factor &&
|
||||||
|
!is_edge_blendfactor(src_factor) &&
|
||||||
|
!is_edge_blendfactor(dest_factor))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void to_c_factor(unsigned factor, struct MALI_BLEND_FUNCTION *function)
|
||||||
|
{
|
||||||
|
if (complement_factor(factor) >= 0)
|
||||||
|
function->invert_c = true;
|
||||||
|
|
||||||
|
switch (uncomplement_factor(factor)) {
|
||||||
|
case PIPE_BLENDFACTOR_ONE:
|
||||||
|
case PIPE_BLENDFACTOR_ZERO:
|
||||||
|
function->invert_c = factor == PIPE_BLENDFACTOR_ONE;
|
||||||
|
function->c = MALI_BLEND_OPERAND_C_ZERO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* TODO: Reenable subtraction modes when those fixed */
|
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
||||||
case PIPE_BLEND_SUBTRACT:
|
function->c = MALI_BLEND_OPERAND_C_SRC_ALPHA;
|
||||||
case PIPE_BLEND_REVERSE_SUBTRACT:
|
break;
|
||||||
|
|
||||||
|
case PIPE_BLENDFACTOR_DST_ALPHA:
|
||||||
|
function->c = MALI_BLEND_OPERAND_C_DEST_ALPHA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_BLENDFACTOR_SRC_COLOR:
|
||||||
|
function->c = MALI_BLEND_OPERAND_C_SRC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_BLENDFACTOR_DST_COLOR:
|
||||||
|
function->c = MALI_BLEND_OPERAND_C_DEST;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||||
|
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||||
|
function->c = MALI_BLEND_OPERAND_C_CONSTANT;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
unreachable("Invalid blend factor");
|
||||||
}
|
}
|
||||||
|
|
||||||
part.clip_modifier = MALI_BLEND_MOD_NORMAL;
|
}
|
||||||
|
|
||||||
/* Decide which is dominant, source or destination. If one is an edge
|
static bool
|
||||||
* case, use the other as a factor. If they're the same, it doesn't
|
to_panfrost_function(unsigned blend_func,
|
||||||
* matter; we just mirror. If they're different non-edge-cases, you
|
unsigned src_factor,
|
||||||
* need a blend shader (don't do that). */
|
unsigned dest_factor,
|
||||||
|
struct MALI_BLEND_FUNCTION *function)
|
||||||
|
{
|
||||||
|
if (!can_use_fixed_function_blend(blend_func, src_factor, dest_factor))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (is_edge_blendfactor(dst_factor)) {
|
if (src_factor == PIPE_BLENDFACTOR_ZERO) {
|
||||||
part.dominant = MALI_BLEND_DOM_SOURCE;
|
function->a = MALI_BLEND_OPERAND_A_ZERO;
|
||||||
part.nondominant_mode = MALI_BLEND_NON_ZERO;
|
function->b = MALI_BLEND_OPERAND_B_DEST;
|
||||||
|
if (blend_func == PIPE_BLEND_SUBTRACT)
|
||||||
|
function->negate_b = true;
|
||||||
|
to_c_factor(dest_factor, function);
|
||||||
|
} else if (src_factor == PIPE_BLENDFACTOR_ONE) {
|
||||||
|
function->a = MALI_BLEND_OPERAND_A_SRC;
|
||||||
|
function->b = MALI_BLEND_OPERAND_B_DEST;
|
||||||
|
if (blend_func == PIPE_BLEND_SUBTRACT)
|
||||||
|
function->negate_b = true;
|
||||||
|
else if (blend_func == PIPE_BLEND_REVERSE_SUBTRACT)
|
||||||
|
function->negate_a = true;
|
||||||
|
to_c_factor(dest_factor, function);
|
||||||
|
} else if (dest_factor == PIPE_BLENDFACTOR_ZERO) {
|
||||||
|
function->a = MALI_BLEND_OPERAND_A_ZERO;
|
||||||
|
function->b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
|
if (blend_func == PIPE_BLEND_REVERSE_SUBTRACT)
|
||||||
|
function->negate_b = true;
|
||||||
|
to_c_factor(src_factor, function);
|
||||||
|
} else if (dest_factor == PIPE_BLENDFACTOR_ONE) {
|
||||||
|
function->a = MALI_BLEND_OPERAND_A_DEST;
|
||||||
|
function->b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
|
if (blend_func == PIPE_BLEND_SUBTRACT)
|
||||||
|
function->negate_a = true;
|
||||||
|
else if (blend_func == PIPE_BLEND_REVERSE_SUBTRACT)
|
||||||
|
function->negate_b = true;
|
||||||
|
to_c_factor(src_factor, function);
|
||||||
|
} else if (src_factor == dest_factor) {
|
||||||
|
function->a = MALI_BLEND_OPERAND_A_ZERO;
|
||||||
|
to_c_factor(src_factor, function);
|
||||||
|
|
||||||
if (dst_factor == PIPE_BLENDFACTOR_ONE)
|
switch (blend_func) {
|
||||||
part.clip_modifier = MALI_BLEND_MOD_DEST_ONE;
|
case PIPE_BLEND_ADD:
|
||||||
} else if (is_edge_blendfactor(src_factor)) {
|
function->b = MALI_BLEND_OPERAND_B_SRC_PLUS_DEST;
|
||||||
part.dominant = MALI_BLEND_DOM_DESTINATION;
|
break;
|
||||||
part.nondominant_mode = MALI_BLEND_NON_ZERO;
|
case PIPE_BLEND_REVERSE_SUBTRACT:
|
||||||
|
function->negate_b = true;
|
||||||
if (src_factor == PIPE_BLENDFACTOR_ONE)
|
/* fall-through */
|
||||||
part.clip_modifier = MALI_BLEND_MOD_SOURCE_ONE;
|
case PIPE_BLEND_SUBTRACT:
|
||||||
} else if (src_factor == dst_factor) {
|
function->b = MALI_BLEND_OPERAND_B_SRC_MINUS_DEST;
|
||||||
/* XXX: Why? */
|
break;
|
||||||
part.dominant = func == PIPE_BLEND_ADD ?
|
default:
|
||||||
MALI_BLEND_DOM_DESTINATION : MALI_BLEND_DOM_SOURCE;
|
unreachable("Invalid blend function");
|
||||||
|
}
|
||||||
part.nondominant_mode = MALI_BLEND_NON_MIRROR;
|
|
||||||
} else if (src_factor == complement_factor(dst_factor)) {
|
|
||||||
/* TODO: How does this work exactly? */
|
|
||||||
part.dominant = MALI_BLEND_DOM_SOURCE;
|
|
||||||
part.nondominant_mode = MALI_BLEND_NON_MIRROR;
|
|
||||||
part.clip_modifier = MALI_BLEND_MOD_DEST_ONE;
|
|
||||||
|
|
||||||
/* The complement is handled by the clip modifier, don't set a
|
|
||||||
* complement flag */
|
|
||||||
|
|
||||||
dst_factor = src_factor;
|
|
||||||
} else if (dst_factor == complement_factor(src_factor)) {
|
|
||||||
part.dominant = MALI_BLEND_DOM_SOURCE;
|
|
||||||
part.nondominant_mode = MALI_BLEND_NON_MIRROR;
|
|
||||||
part.clip_modifier = MALI_BLEND_MOD_SOURCE_ONE;
|
|
||||||
|
|
||||||
src_factor = dst_factor;
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
assert(src_factor == complement_factor(dest_factor) ||
|
||||||
|
complement_factor(src_factor) == dest_factor);
|
||||||
|
|
||||||
|
function->a = MALI_BLEND_OPERAND_A_DEST;
|
||||||
|
to_c_factor(src_factor, function);
|
||||||
|
|
||||||
|
switch (blend_func) {
|
||||||
|
case PIPE_BLEND_ADD:
|
||||||
|
function->b = MALI_BLEND_OPERAND_B_SRC_MINUS_DEST;
|
||||||
|
break;
|
||||||
|
case PIPE_BLEND_REVERSE_SUBTRACT:
|
||||||
|
function->b = MALI_BLEND_OPERAND_B_SRC_PLUS_DEST;
|
||||||
|
function->negate_b = true;
|
||||||
|
break;
|
||||||
|
case PIPE_BLEND_SUBTRACT:
|
||||||
|
function->b = MALI_BLEND_OPERAND_B_SRC_PLUS_DEST;
|
||||||
|
function->negate_a = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned in_dominant_factor =
|
|
||||||
part.dominant == MALI_BLEND_DOM_SOURCE ? src_factor : dst_factor;
|
|
||||||
|
|
||||||
if (part.clip_modifier == MALI_BLEND_MOD_NORMAL && in_dominant_factor == PIPE_BLENDFACTOR_ONE) {
|
|
||||||
part.clip_modifier = part.dominant == MALI_BLEND_DOM_SOURCE ? MALI_BLEND_MOD_SOURCE_ONE : MALI_BLEND_MOD_DEST_ONE;
|
|
||||||
in_dominant_factor = PIPE_BLENDFACTOR_ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mali_dominant_factor dominant_factor;
|
|
||||||
|
|
||||||
if (!panfrost_make_dominant_factor(in_dominant_factor, &dominant_factor))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
part.dominant_factor = dominant_factor;
|
|
||||||
part.complement_dominant = util_blend_factor_is_inverted(in_dominant_factor);
|
|
||||||
|
|
||||||
/* It's not clear what this does, but fixes some ADD blending tests.
|
|
||||||
* More research is needed XXX */
|
|
||||||
|
|
||||||
if ((part.clip_modifier == MALI_BLEND_MOD_SOURCE_ONE) && (part.dominant == MALI_BLEND_DOM_SOURCE))
|
|
||||||
part.negate_dest = true;
|
|
||||||
|
|
||||||
/* Write out mode */
|
|
||||||
memcpy(out, &part, sizeof(part));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,19 +279,20 @@ panfrost_constant_mask(unsigned *factors, unsigned num_factors)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
panfrost_make_fixed_blend_mode(
|
panfrost_make_fixed_blend_mode(const struct pipe_rt_blend_state blend,
|
||||||
struct pipe_rt_blend_state blend,
|
struct MALI_BLEND_EQUATION *equation,
|
||||||
struct mali_blend_equation_packed *out,
|
unsigned *constant_mask)
|
||||||
unsigned *constant_mask)
|
|
||||||
{
|
{
|
||||||
/* If no blending is enabled, default back on `replace` mode */
|
/* If no blending is enabled, default back on `replace` mode */
|
||||||
|
|
||||||
if (!blend.blend_enable) {
|
if (!blend.blend_enable) {
|
||||||
pan_pack(out, BLEND_EQUATION, cfg) {
|
equation->color_mask = blend.colormask;
|
||||||
cfg.color_mask = blend.colormask;
|
equation->rgb.a = MALI_BLEND_OPERAND_A_SRC;
|
||||||
cfg.rgb_mode = cfg.alpha_mode = 0x122;
|
equation->rgb.b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
}
|
equation->rgb.c = MALI_BLEND_OPERAND_C_ZERO;
|
||||||
|
equation->alpha.a = MALI_BLEND_OPERAND_A_SRC;
|
||||||
|
equation->alpha.b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
|
equation->alpha.c = MALI_BLEND_OPERAND_C_ZERO;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,25 +308,16 @@ panfrost_make_fixed_blend_mode(
|
||||||
*constant_mask = panfrost_constant_mask(factors, ARRAY_SIZE(factors));
|
*constant_mask = panfrost_constant_mask(factors, ARRAY_SIZE(factors));
|
||||||
|
|
||||||
/* Try to compile the actual fixed-function blend */
|
/* Try to compile the actual fixed-function blend */
|
||||||
|
if (!to_panfrost_function(blend.rgb_func, blend.rgb_src_factor,
|
||||||
unsigned rgb_mode = 0;
|
blend.rgb_dst_factor,
|
||||||
unsigned alpha_mode = 0;
|
&equation->rgb))
|
||||||
|
|
||||||
if (!panfrost_make_fixed_blend_part(
|
|
||||||
blend.rgb_func, blend.rgb_src_factor, blend.rgb_dst_factor,
|
|
||||||
&rgb_mode))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!panfrost_make_fixed_blend_part(
|
if (!to_panfrost_function(blend.alpha_func, blend.alpha_src_factor,
|
||||||
blend.alpha_func, blend.alpha_src_factor, blend.alpha_dst_factor,
|
blend.alpha_dst_factor,
|
||||||
&alpha_mode))
|
&equation->alpha))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pan_pack(out, BLEND_EQUATION, cfg) {
|
equation->color_mask = blend.colormask;
|
||||||
cfg.color_mask = blend.colormask;
|
|
||||||
cfg.rgb_mode = rgb_mode;
|
|
||||||
cfg.alpha_mode = alpha_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,14 +28,14 @@
|
||||||
#include "pipe/p_state.h"
|
#include "pipe/p_state.h"
|
||||||
#include "pipe/p_defines.h"
|
#include "pipe/p_defines.h"
|
||||||
#include <midgard_pack.h>
|
#include <midgard_pack.h>
|
||||||
|
#include "pan_blend.h"
|
||||||
|
|
||||||
struct panfrost_blend_state;
|
struct panfrost_blend_state;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
panfrost_make_fixed_blend_mode(
|
panfrost_make_fixed_blend_mode(const struct pipe_rt_blend_state blend,
|
||||||
const struct pipe_rt_blend_state blend,
|
struct MALI_BLEND_EQUATION *equation,
|
||||||
struct mali_blend_equation_packed *out,
|
unsigned *constant_mask);
|
||||||
unsigned *constant_mask);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
panfrost_can_fixed_blend(enum pipe_format format);
|
panfrost_can_fixed_blend(enum pipe_format format);
|
||||||
|
|
|
@ -307,8 +307,12 @@ panfrost_emit_bifrost_blend(struct panfrost_batch *batch,
|
||||||
enum pipe_format format = batch->key.cbufs[i]->format;
|
enum pipe_format format = batch->key.cbufs[i]->format;
|
||||||
const struct util_format_description *format_desc;
|
const struct util_format_description *format_desc;
|
||||||
format_desc = util_format_description(format);
|
format_desc = util_format_description(format);
|
||||||
|
struct mali_blend_equation_packed peq;
|
||||||
|
|
||||||
brts[i].equation = blend[i].equation.equation;
|
pan_pack(&peq, BLEND_EQUATION, cfg) {
|
||||||
|
cfg = blend[i].equation.equation;
|
||||||
|
}
|
||||||
|
brts[i].equation = peq;
|
||||||
|
|
||||||
/* TODO: this is a bit more complicated */
|
/* TODO: this is a bit more complicated */
|
||||||
brts[i].constant = blend[i].equation.constant;
|
brts[i].constant = blend[i].equation.constant;
|
||||||
|
@ -338,7 +342,13 @@ panfrost_emit_midgard_blend(struct panfrost_batch *batch,
|
||||||
if (rt_count == 0) {
|
if (rt_count == 0) {
|
||||||
/* Disable blending for depth-only */
|
/* Disable blending for depth-only */
|
||||||
pan_pack(rts, MIDGARD_BLEND, cfg) {
|
pan_pack(rts, MIDGARD_BLEND, cfg) {
|
||||||
cfg.equation = 0xf0122122; /* Replace */
|
cfg.equation.color_mask = 0xf;
|
||||||
|
cfg.equation.rgb.a = MALI_BLEND_OPERAND_A_SRC;
|
||||||
|
cfg.equation.rgb.b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
|
cfg.equation.rgb.c = MALI_BLEND_OPERAND_C_ZERO;
|
||||||
|
cfg.equation.alpha.a = MALI_BLEND_OPERAND_A_SRC;
|
||||||
|
cfg.equation.alpha.b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
|
cfg.equation.alpha.c = MALI_BLEND_OPERAND_C_ZERO;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -357,7 +367,7 @@ panfrost_emit_midgard_blend(struct panfrost_batch *batch,
|
||||||
if (blend[i].is_shader) {
|
if (blend[i].is_shader) {
|
||||||
cfg.shader = blend[i].shader.gpu | blend[i].shader.first_tag;
|
cfg.shader = blend[i].shader.gpu | blend[i].shader.first_tag;
|
||||||
} else {
|
} else {
|
||||||
cfg.equation = blend[i].equation.equation.opaque[0];
|
cfg.equation = blend[i].equation.equation;
|
||||||
cfg.constant = blend[i].equation.constant;
|
cfg.constant = blend[i].equation.constant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -460,7 +470,7 @@ panfrost_prepare_midgard_fs_state(struct panfrost_context *ctx,
|
||||||
state->sfbd_blend_shader = blend[0].shader.gpu |
|
state->sfbd_blend_shader = blend[0].shader.gpu |
|
||||||
blend[0].shader.first_tag;
|
blend[0].shader.first_tag;
|
||||||
} else {
|
} else {
|
||||||
state->sfbd_blend_equation = blend[0].equation.equation.opaque[0];
|
state->sfbd_blend_equation = blend[0].equation.equation;
|
||||||
state->sfbd_blend_constant = blend[0].equation.constant;
|
state->sfbd_blend_constant = blend[0].equation.constant;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -38,51 +38,6 @@ typedef uint32_t u32;
|
||||||
typedef uint64_t u64;
|
typedef uint64_t u64;
|
||||||
typedef uint64_t mali_ptr;
|
typedef uint64_t mali_ptr;
|
||||||
|
|
||||||
enum mali_nondominant_mode {
|
|
||||||
MALI_BLEND_NON_MIRROR = 0,
|
|
||||||
MALI_BLEND_NON_ZERO = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mali_dominant_blend {
|
|
||||||
MALI_BLEND_DOM_SOURCE = 0,
|
|
||||||
MALI_BLEND_DOM_DESTINATION = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mali_dominant_factor {
|
|
||||||
MALI_DOMINANT_UNK0 = 0,
|
|
||||||
MALI_DOMINANT_ZERO = 1,
|
|
||||||
MALI_DOMINANT_SRC_COLOR = 2,
|
|
||||||
MALI_DOMINANT_DST_COLOR = 3,
|
|
||||||
MALI_DOMINANT_UNK4 = 4,
|
|
||||||
MALI_DOMINANT_SRC_ALPHA = 5,
|
|
||||||
MALI_DOMINANT_DST_ALPHA = 6,
|
|
||||||
MALI_DOMINANT_CONSTANT = 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum mali_blend_modifier {
|
|
||||||
MALI_BLEND_MOD_UNK0 = 0,
|
|
||||||
MALI_BLEND_MOD_NORMAL = 1,
|
|
||||||
MALI_BLEND_MOD_SOURCE_ONE = 2,
|
|
||||||
MALI_BLEND_MOD_DEST_ONE = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mali_blend_mode {
|
|
||||||
enum mali_blend_modifier clip_modifier : 2;
|
|
||||||
unsigned unused_0 : 1;
|
|
||||||
unsigned negate_source : 1;
|
|
||||||
|
|
||||||
enum mali_dominant_blend dominant : 1;
|
|
||||||
|
|
||||||
enum mali_nondominant_mode nondominant_mode : 1;
|
|
||||||
|
|
||||||
unsigned unused_1 : 1;
|
|
||||||
|
|
||||||
unsigned negate_dest : 1;
|
|
||||||
|
|
||||||
enum mali_dominant_factor dominant_factor : 3;
|
|
||||||
unsigned complement_dominant : 1;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
/* Compressed per-pixel formats. Each of these formats expands to one to four
|
/* Compressed per-pixel formats. Each of these formats expands to one to four
|
||||||
* floating-point or integer numbers, as defined by the OpenGL specification.
|
* floating-point or integer numbers, as defined by the OpenGL specification.
|
||||||
* There are various places in OpenGL where the user can specify a compressed
|
* There are various places in OpenGL where the user can specify a compressed
|
||||||
|
|
|
@ -1185,15 +1185,19 @@ pandecode_vertex_tiler_postfix_pre(
|
||||||
|
|
||||||
if (!is_bifrost) {
|
if (!is_bifrost) {
|
||||||
/* TODO: Blend shaders routing/disasm */
|
/* TODO: Blend shaders routing/disasm */
|
||||||
union midgard_blend blend;
|
pandecode_log("SFBD Blend:\n");
|
||||||
|
pandecode_indent++;
|
||||||
if (state.multisample_misc.sfbd_blend_shader) {
|
if (state.multisample_misc.sfbd_blend_shader) {
|
||||||
blend.shader = state.sfbd_blend_shader;
|
pandecode_shader_address("Shader", state.sfbd_blend_shader);
|
||||||
} else {
|
} else {
|
||||||
blend.equation.opaque[0] = state.sfbd_blend_equation;
|
DUMP_UNPACKED(BLEND_EQUATION, state.sfbd_blend_equation, "Equation:\n");
|
||||||
blend.constant = state.sfbd_blend_constant;
|
pandecode_prop("Constant = %f", state.sfbd_blend_constant);
|
||||||
}
|
}
|
||||||
mali_ptr shader = pandecode_midgard_blend(&blend, state.multisample_misc.sfbd_blend_shader);
|
pandecode_indent--;
|
||||||
if (shader & ~0xF)
|
pandecode_log("\n");
|
||||||
|
|
||||||
|
mali_ptr shader = state.sfbd_blend_shader & ~0xF;
|
||||||
|
if (state.multisample_misc.sfbd_blend_shader && shader)
|
||||||
pandecode_blend_shader_disassemble(shader, job_no, job_type, false, gpu_id);
|
pandecode_blend_shader_disassemble(shader, job_no, job_type, false, gpu_id);
|
||||||
}
|
}
|
||||||
pandecode_indent--;
|
pandecode_indent--;
|
||||||
|
|
|
@ -285,10 +285,43 @@
|
||||||
<field name="Divisor" size="32" start="3:0" type="uint"/>
|
<field name="Divisor" size="32" start="3:0" type="uint"/>
|
||||||
</struct>
|
</struct>
|
||||||
|
|
||||||
|
<enum name="Blend Operand A">
|
||||||
|
<value name="Zero" value="1"/>
|
||||||
|
<value name="Src" value="2"/>
|
||||||
|
<value name="Dest" value="3"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<enum name="Blend Operand B">
|
||||||
|
<value name="Src Minus Dest" value="0"/>
|
||||||
|
<value name="Src Plus Dest" value="1"/>
|
||||||
|
<value name="Src" value="2"/>
|
||||||
|
<value name="Dest" value="3"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<enum name="Blend Operand C">
|
||||||
|
<value name="Zero" value="1"/>
|
||||||
|
<value name="Src" value="2"/>
|
||||||
|
<value name="Dest" value="3"/>
|
||||||
|
<value name="Src x 2" value="4"/>
|
||||||
|
<value name="Src Alpha" value="5"/>
|
||||||
|
<value name="Dest Alpha" value="6"/>
|
||||||
|
<value name="Constant" value="7"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<struct name="Blend Function" no-direct-packing="true">
|
||||||
|
<!-- Blend equation: A + (B * C) -->
|
||||||
|
<field name="A" size="2" start="0" type="Blend Operand A"/>
|
||||||
|
<field name="Negate A" size="1" start="3" type="bool"/>
|
||||||
|
<field name="B" size="2" start="4" type="Blend Operand B"/>
|
||||||
|
<field name="Negate B" size="1" start="7" type="bool"/>
|
||||||
|
<field name="C" size="3" start="8" type="Blend Operand C"/>
|
||||||
|
<field name="Invert C" size="1" start="11" type="bool"/>
|
||||||
|
</struct>
|
||||||
|
|
||||||
<struct name="Blend Equation" size="1">
|
<struct name="Blend Equation" size="1">
|
||||||
<field name="RGB Mode" size="12" start="0" type="uint"/>
|
<field name="RGB" size="12" start="0:0" type="Blend Function"/>
|
||||||
<field name="Alpha Mode" size="12" start="12" type="uint"/>
|
<field name="Alpha" size="12" start="0:12" type="Blend Function"/>
|
||||||
<field name="Color mask" size="4" start="28" type="uint" default="15"/>
|
<field name="Color Mask" size="4" start="0:28" type="uint"/>
|
||||||
</struct>
|
</struct>
|
||||||
|
|
||||||
<struct name="Blend Flags" size="1">
|
<struct name="Blend Flags" size="1">
|
||||||
|
@ -301,7 +334,7 @@
|
||||||
|
|
||||||
<struct name="Midgard Blend" size="4">
|
<struct name="Midgard Blend" size="4">
|
||||||
<field name="Flags" size="32" start="0:0" type="Blend Flags"/>
|
<field name="Flags" size="32" start="0:0" type="Blend Flags"/>
|
||||||
<field name="Equation" size="32" start="2:0" type="uint"/> <!-- XXX -->
|
<field name="Equation" size="32" start="2:0" type="Blend Equation"/>
|
||||||
<field name="Constant" size="32" start="3:0" type="float"/>
|
<field name="Constant" size="32" start="3:0" type="float"/>
|
||||||
<field name="Shader" size="64" start="2:0" type="address"/>
|
<field name="Shader" size="64" start="2:0" type="address"/>
|
||||||
</struct>
|
</struct>
|
||||||
|
@ -553,7 +586,7 @@
|
||||||
<field name="Preload" size="32" start="12:0" type="Preload"/>
|
<field name="Preload" size="32" start="12:0" type="Preload"/>
|
||||||
<field name="Thread Balancing" size="16" start="13:0" type="uint"/>
|
<field name="Thread Balancing" size="16" start="13:0" type="uint"/>
|
||||||
<field name="SFBD Blend Shader" size="64" start="14:0" type="address"/>
|
<field name="SFBD Blend Shader" size="64" start="14:0" type="address"/>
|
||||||
<field name="SFBD Blend Equation" size="32" start="14:0" type="uint"/>
|
<field name="SFBD Blend Equation" size="32" start="14:0" type="Blend Equation"/>
|
||||||
<field name="SFBD Blend Constant" size="32" start="15:0" type="float"/>
|
<field name="SFBD Blend Constant" size="32" start="15:0" type="float"/>
|
||||||
</struct>
|
</struct>
|
||||||
|
|
||||||
|
|
|
@ -207,16 +207,6 @@ panfrost_load_midg(
|
||||||
cfg.format = (MALI_CHANNEL_R << 0) | (MALI_CHANNEL_G << 3) | (MALI_RGBA32F << 12);
|
cfg.format = (MALI_CHANNEL_R << 0) | (MALI_CHANNEL_G << 3) | (MALI_RGBA32F << 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mali_blend_equation_packed eq;
|
|
||||||
|
|
||||||
pan_pack(&eq, BLEND_EQUATION, cfg) {
|
|
||||||
cfg.rgb_mode = 0x122;
|
|
||||||
cfg.alpha_mode = 0x122;
|
|
||||||
|
|
||||||
if (loc < FRAG_RESULT_DATA0)
|
|
||||||
cfg.color_mask = 0x0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Determine the sampler type needed. Stencil is always sampled as
|
/* Determine the sampler type needed. Stencil is always sampled as
|
||||||
* UINT. Pure (U)INT is always (U)INT. Everything else is FLOAT. */
|
* UINT. Pure (U)INT is always (U)INT. Everything else is FLOAT. */
|
||||||
|
|
||||||
|
@ -271,7 +261,15 @@ panfrost_load_midg(
|
||||||
if (cfg.multisample_misc.sfbd_blend_shader) {
|
if (cfg.multisample_misc.sfbd_blend_shader) {
|
||||||
cfg.sfbd_blend_shader = blend_shader;
|
cfg.sfbd_blend_shader = blend_shader;
|
||||||
} else {
|
} else {
|
||||||
cfg.sfbd_blend_equation = eq.opaque[0];
|
cfg.sfbd_blend_equation.rgb.a = MALI_BLEND_OPERAND_A_SRC;
|
||||||
|
cfg.sfbd_blend_equation.rgb.b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
|
cfg.sfbd_blend_equation.rgb.c = MALI_BLEND_OPERAND_C_ZERO;
|
||||||
|
cfg.sfbd_blend_equation.alpha.a = MALI_BLEND_OPERAND_A_SRC;
|
||||||
|
cfg.sfbd_blend_equation.alpha.b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
|
cfg.sfbd_blend_equation.alpha.c = MALI_BLEND_OPERAND_C_ZERO;
|
||||||
|
|
||||||
|
if (loc >= FRAG_RESULT_DATA0)
|
||||||
|
cfg.sfbd_blend_equation.color_mask = 0xf;
|
||||||
cfg.sfbd_blend_constant = 0;
|
cfg.sfbd_blend_constant = 0;
|
||||||
}
|
}
|
||||||
} else if (!(pool->dev->quirks & IS_BIFROST)) {
|
} else if (!(pool->dev->quirks & IS_BIFROST)) {
|
||||||
|
@ -313,6 +311,20 @@ panfrost_load_midg(
|
||||||
void *dest = shader_meta_t.cpu + MALI_RENDERER_STATE_LENGTH + sizeof(struct midgard_blend_rt) * i;
|
void *dest = shader_meta_t.cpu + MALI_RENDERER_STATE_LENGTH + sizeof(struct midgard_blend_rt) * i;
|
||||||
|
|
||||||
if (loc == (FRAG_RESULT_DATA0 + i)) {
|
if (loc == (FRAG_RESULT_DATA0 + i)) {
|
||||||
|
struct mali_blend_equation_packed eq;
|
||||||
|
|
||||||
|
pan_pack(&eq, BLEND_EQUATION, cfg) {
|
||||||
|
cfg.rgb.a = MALI_BLEND_OPERAND_A_SRC;
|
||||||
|
cfg.rgb.b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
|
cfg.rgb.c = MALI_BLEND_OPERAND_C_ZERO;
|
||||||
|
cfg.alpha.a = MALI_BLEND_OPERAND_A_SRC;
|
||||||
|
cfg.alpha.b = MALI_BLEND_OPERAND_B_SRC;
|
||||||
|
cfg.alpha.c = MALI_BLEND_OPERAND_C_ZERO;
|
||||||
|
|
||||||
|
if (loc >= FRAG_RESULT_DATA0)
|
||||||
|
cfg.color_mask = 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
union midgard_blend replace = {
|
union midgard_blend replace = {
|
||||||
.equation = eq
|
.equation = eq
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue