panfrost: LogicOp support
The generated shaders are definitely not optimal, but for a feature hardly anyone uses, it's probably good enough. The XScreensaver demos quasicrystal, blitspin, bouboule, crystal and munch now seem to work, with no obvious problems. Currently this only works for 8-bit textures. Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3887> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3887>
This commit is contained in:
parent
5bfd363be4
commit
068806c9f6
|
@ -156,6 +156,70 @@ nir_color_mask(
|
||||||
return nir_vec(b, masked, 4);
|
return nir_vec(b, masked, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nir_ssa_def *
|
||||||
|
nir_logicop_func(
|
||||||
|
nir_builder *b,
|
||||||
|
unsigned func,
|
||||||
|
nir_ssa_def *src, nir_ssa_def *dst)
|
||||||
|
{
|
||||||
|
switch (func) {
|
||||||
|
case PIPE_LOGICOP_CLEAR:
|
||||||
|
return nir_imm_ivec4(b, 0, 0, 0, 0);
|
||||||
|
case PIPE_LOGICOP_NOR:
|
||||||
|
return nir_inot(b, nir_ior(b, src, dst));
|
||||||
|
case PIPE_LOGICOP_AND_INVERTED:
|
||||||
|
return nir_iand(b, nir_inot(b, src), dst);
|
||||||
|
case PIPE_LOGICOP_COPY_INVERTED:
|
||||||
|
return nir_inot(b, src);
|
||||||
|
case PIPE_LOGICOP_AND_REVERSE:
|
||||||
|
return nir_iand(b, src, nir_inot(b, dst));
|
||||||
|
case PIPE_LOGICOP_INVERT:
|
||||||
|
return nir_inot(b, dst);
|
||||||
|
case PIPE_LOGICOP_XOR:
|
||||||
|
return nir_ixor(b, src, dst);
|
||||||
|
case PIPE_LOGICOP_NAND:
|
||||||
|
return nir_inot(b, nir_iand(b, src, dst));
|
||||||
|
case PIPE_LOGICOP_AND:
|
||||||
|
return nir_iand(b, src, dst);
|
||||||
|
case PIPE_LOGICOP_EQUIV:
|
||||||
|
return nir_inot(b, nir_ixor(b, src, dst));
|
||||||
|
case PIPE_LOGICOP_NOOP:
|
||||||
|
return dst;
|
||||||
|
case PIPE_LOGICOP_OR_INVERTED:
|
||||||
|
return nir_ior(b, nir_inot(b, src), dst);
|
||||||
|
case PIPE_LOGICOP_COPY:
|
||||||
|
return src;
|
||||||
|
case PIPE_LOGICOP_OR_REVERSE:
|
||||||
|
return nir_ior(b, src, nir_inot(b, dst));
|
||||||
|
case PIPE_LOGICOP_OR:
|
||||||
|
return nir_ior(b, src, dst);
|
||||||
|
case PIPE_LOGICOP_SET:
|
||||||
|
return nir_imm_ivec4(b, ~0, ~0, ~0, ~0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable("Invalid logciop function");
|
||||||
|
}
|
||||||
|
|
||||||
|
static nir_ssa_def *
|
||||||
|
nir_blend_logicop(
|
||||||
|
nir_builder *b,
|
||||||
|
nir_lower_blend_options options,
|
||||||
|
nir_ssa_def *src, nir_ssa_def *dst)
|
||||||
|
{
|
||||||
|
/* TODO: Support other sizes */
|
||||||
|
nir_ssa_def *factor = nir_imm_float(b, 255);
|
||||||
|
|
||||||
|
src = nir_fmin(b, nir_fmax(b, src, nir_imm_float(b, -1)), nir_imm_float(b, 1));
|
||||||
|
src = nir_f2u32(b, nir_fround_even(b, nir_fmul(b, src, factor)));
|
||||||
|
|
||||||
|
dst = nir_fmin(b, nir_fmax(b, dst, nir_imm_float(b, -1)), nir_imm_float(b, 1));
|
||||||
|
dst = nir_f2u32(b, nir_fround_even(b, nir_fmul(b, dst, factor)));
|
||||||
|
|
||||||
|
nir_ssa_def *out = nir_logicop_func(b, options.logicop_func, src, dst);
|
||||||
|
|
||||||
|
return nir_fdiv(b, nir_u2f32(b, out), factor);
|
||||||
|
}
|
||||||
|
|
||||||
/* Given a blend state, the source color, and the destination color,
|
/* Given a blend state, the source color, and the destination color,
|
||||||
* return the blended color
|
* return the blended color
|
||||||
*/
|
*/
|
||||||
|
@ -166,6 +230,9 @@ nir_blend(
|
||||||
nir_lower_blend_options options,
|
nir_lower_blend_options options,
|
||||||
nir_ssa_def *src, nir_ssa_def *dst)
|
nir_ssa_def *src, nir_ssa_def *dst)
|
||||||
{
|
{
|
||||||
|
if (options.logicop_enable)
|
||||||
|
return nir_blend_logicop(b, options, src, dst);
|
||||||
|
|
||||||
/* Grab the blend constant ahead of time */
|
/* Grab the blend constant ahead of time */
|
||||||
nir_ssa_def *bconst = nir_load_blend_const_color_rgba(b);
|
nir_ssa_def *bconst = nir_load_blend_const_color_rgba(b);
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,9 @@ typedef struct {
|
||||||
|
|
||||||
/* 4-bit colormask. 0x0 for none, 0xF for RGBA, 0x1 for R */
|
/* 4-bit colormask. 0x0 for none, 0xF for RGBA, 0x1 for R */
|
||||||
unsigned colormask;
|
unsigned colormask;
|
||||||
|
|
||||||
|
bool logicop_enable;
|
||||||
|
unsigned logicop_func;
|
||||||
} nir_lower_blend_options;
|
} nir_lower_blend_options;
|
||||||
|
|
||||||
void nir_lower_blend(nir_shader *shader, nir_lower_blend_options options);
|
void nir_lower_blend(nir_shader *shader, nir_lower_blend_options options);
|
||||||
|
|
|
@ -107,7 +107,6 @@ panfrost_create_blend_state(struct pipe_context *pipe,
|
||||||
so->base = *blend;
|
so->base = *blend;
|
||||||
|
|
||||||
/* TODO: The following features are not yet implemented */
|
/* TODO: The following features are not yet implemented */
|
||||||
assert(!blend->logicop_enable);
|
|
||||||
assert(!blend->alpha_to_coverage);
|
assert(!blend->alpha_to_coverage);
|
||||||
assert(!blend->alpha_to_one);
|
assert(!blend->alpha_to_one);
|
||||||
|
|
||||||
|
@ -119,15 +118,17 @@ panfrost_create_blend_state(struct pipe_context *pipe,
|
||||||
|
|
||||||
/* Without indep blending, the first RT settings replicate */
|
/* Without indep blending, the first RT settings replicate */
|
||||||
|
|
||||||
unsigned g =
|
if (!blend->logicop_enable) {
|
||||||
blend->independent_blend_enable ? c : 0;
|
unsigned g =
|
||||||
|
blend->independent_blend_enable ? c : 0;
|
||||||
|
|
||||||
rt->has_fixed_function =
|
rt->has_fixed_function =
|
||||||
panfrost_make_fixed_blend_mode(
|
panfrost_make_fixed_blend_mode(
|
||||||
&blend->rt[g],
|
&blend->rt[g],
|
||||||
&rt->equation,
|
&rt->equation,
|
||||||
&rt->constant_mask,
|
&rt->constant_mask,
|
||||||
blend->rt[g].colormask);
|
blend->rt[g].colormask);
|
||||||
|
}
|
||||||
|
|
||||||
/* Regardless if that works, we also need to initialize
|
/* Regardless if that works, we also need to initialize
|
||||||
* the blend shaders */
|
* the blend shaders */
|
||||||
|
|
|
@ -89,6 +89,14 @@ nir_make_options(const struct pipe_blend_state *blend, unsigned i)
|
||||||
{
|
{
|
||||||
nir_lower_blend_options options;
|
nir_lower_blend_options options;
|
||||||
|
|
||||||
|
if (blend->logicop_enable) {
|
||||||
|
options.logicop_enable = true;
|
||||||
|
options.logicop_func = blend->logicop_func;
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
options.logicop_enable = false;
|
||||||
|
|
||||||
/* If blend is disabled, we just use replace mode */
|
/* If blend is disabled, we just use replace mode */
|
||||||
|
|
||||||
nir_lower_blend_channel rgb = {
|
nir_lower_blend_channel rgb = {
|
||||||
|
|
Loading…
Reference in New Issue