Mesa (master): panfrost: LogicOp support

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Feb 20 13:02:36 UTC 2020


Module: Mesa
Branch: master
Commit: 068806c9f6be9bab84ed0d4868f16705cf4c7e6d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=068806c9f6be9bab84ed0d4868f16705cf4c7e6d

Author: Icecream95 <ixn at keemail.me>
Date:   Thu Feb 20 17:59:16 2020 +1300

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 at 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>

---

 src/gallium/drivers/panfrost/nir/nir_lower_blend.c | 67 ++++++++++++++++++++++
 src/gallium/drivers/panfrost/nir/nir_lower_blend.h |  3 +
 src/gallium/drivers/panfrost/pan_blend_cso.c       | 19 +++---
 src/gallium/drivers/panfrost/pan_blend_shaders.c   |  8 +++
 4 files changed, 88 insertions(+), 9 deletions(-)

diff --git a/src/gallium/drivers/panfrost/nir/nir_lower_blend.c b/src/gallium/drivers/panfrost/nir/nir_lower_blend.c
index 4f3a91945e5..a2ff37922d9 100644
--- a/src/gallium/drivers/panfrost/nir/nir_lower_blend.c
+++ b/src/gallium/drivers/panfrost/nir/nir_lower_blend.c
@@ -156,6 +156,70 @@ nir_color_mask(
    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,
  * return the blended color
  */
@@ -166,6 +230,9 @@ nir_blend(
    nir_lower_blend_options options,
    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 */
    nir_ssa_def *bconst = nir_load_blend_const_color_rgba(b);
 
diff --git a/src/gallium/drivers/panfrost/nir/nir_lower_blend.h b/src/gallium/drivers/panfrost/nir/nir_lower_blend.h
index d150e99c72f..99530c3e973 100644
--- a/src/gallium/drivers/panfrost/nir/nir_lower_blend.h
+++ b/src/gallium/drivers/panfrost/nir/nir_lower_blend.h
@@ -48,6 +48,9 @@ typedef struct {
 
    /* 4-bit colormask. 0x0 for none, 0xF for RGBA, 0x1 for R */
    unsigned colormask;
+
+   bool logicop_enable;
+   unsigned logicop_func;
 } nir_lower_blend_options;
 
 void nir_lower_blend(nir_shader *shader, nir_lower_blend_options options);
diff --git a/src/gallium/drivers/panfrost/pan_blend_cso.c b/src/gallium/drivers/panfrost/pan_blend_cso.c
index 94f229b620d..8b4635ca286 100644
--- a/src/gallium/drivers/panfrost/pan_blend_cso.c
+++ b/src/gallium/drivers/panfrost/pan_blend_cso.c
@@ -107,7 +107,6 @@ panfrost_create_blend_state(struct pipe_context *pipe,
         so->base = *blend;
 
         /* TODO: The following features are not yet implemented */
-        assert(!blend->logicop_enable);
         assert(!blend->alpha_to_coverage);
         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 */
 
-                unsigned g =
-                        blend->independent_blend_enable ? c : 0;
+                if (!blend->logicop_enable) {
+                        unsigned g =
+                                blend->independent_blend_enable ? c : 0;
 
-                rt->has_fixed_function =
-                        panfrost_make_fixed_blend_mode(
-                                &blend->rt[g],
-                                &rt->equation,
-                                &rt->constant_mask,
-                                blend->rt[g].colormask);
+                        rt->has_fixed_function =
+                                panfrost_make_fixed_blend_mode(
+                                        &blend->rt[g],
+                                        &rt->equation,
+                                        &rt->constant_mask,
+                                        blend->rt[g].colormask);
+                }
 
                 /* Regardless if that works, we also need to initialize
                  * the blend shaders */
diff --git a/src/gallium/drivers/panfrost/pan_blend_shaders.c b/src/gallium/drivers/panfrost/pan_blend_shaders.c
index cca2eb567b5..0f0e1b5ffd9 100644
--- a/src/gallium/drivers/panfrost/pan_blend_shaders.c
+++ b/src/gallium/drivers/panfrost/pan_blend_shaders.c
@@ -89,6 +89,14 @@ nir_make_options(const struct pipe_blend_state *blend, unsigned i)
 {
         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 */
 
         nir_lower_blend_channel rgb = {



More information about the mesa-commit mailing list