[Mesa-dev] [PATCH] llvmpipe: separate logicop / mask / color mask from blending

sroland at vmware.com sroland at vmware.com
Thu Jan 5 00:13:06 UTC 2017


From: Roland Scheidegger <sroland at vmware.com>

Doing these operations with blend format means that we have to convert
the destination into blend format, which is entirely pointless if we don't
do blending. For instance, we'd convert half floats to floats, or 10/10/10/2
to unorm16, just to apply the partial mask in that format (or color mask,
logic ops) which doesn't make sense.
So separate these operations from blending.
This patch doesn't change how these operations are done, they are still
done with blend format for now, just separates them. No functional change.

While here also skip the separate alpha conversion entirely if there's no
alpha blend (no functional change neither, llvm would drop it certainly).
---
 src/gallium/drivers/llvmpipe/lp_bld_blend.h     |   1 -
 src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c | 132 ++++++++---------------
 src/gallium/drivers/llvmpipe/lp_state_fs.c      | 137 +++++++++++++++++-------
 src/gallium/drivers/llvmpipe/lp_test_blend.c    |   2 +-
 4 files changed, 146 insertions(+), 126 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend.h b/src/gallium/drivers/llvmpipe/lp_bld_blend.h
index adfab85..f2bf4ae 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_blend.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_blend.h
@@ -65,7 +65,6 @@ lp_build_blend_aos(struct gallivm_state *gallivm,
                    LLVMValueRef src1,
                    LLVMValueRef src1_alpha,
                    LLVMValueRef dst,
-                   LLVMValueRef mask,
                    LLVMValueRef const_,
                    LLVMValueRef const_alpha,
                    const unsigned char swizzle[4],
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c
index 45c5c2b..e5b0825 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c
@@ -285,7 +285,6 @@ lp_build_blend_factor(struct lp_build_blend_aos_context *bld,
  * @param src1          second blend src (for dual source blend)
  * @param src1_alpha    second blend src alpha (if not included in src1)
  * @param dst           blend dst
- * @param mask          optional mask to apply to the blending result
  * @param const_        const blend color
  * @param const_alpha   const blend color alpha (if not included in const_)
  * @param swizzle       swizzle values for RGBA
@@ -303,7 +302,6 @@ lp_build_blend_aos(struct gallivm_state *gallivm,
                    LLVMValueRef src1,
                    LLVMValueRef src1_alpha,
                    LLVMValueRef dst,
-                   LLVMValueRef mask,
                    LLVMValueRef const_,
                    LLVMValueRef const_alpha,
                    const unsigned char swizzle[4],
@@ -317,6 +315,10 @@ lp_build_blend_aos(struct gallivm_state *gallivm,
    unsigned alpha_swizzle = PIPE_SWIZZLE_NONE;
    unsigned i;
 
+   boolean rgb_alpha_same = (state->rgb_src_factor == state->rgb_dst_factor &&
+                             state->alpha_src_factor == state->alpha_dst_factor) ||
+                            nr_channels == 1;
+
    desc = util_format_description(cbuf_format);
 
    /* Setup build context */
@@ -348,90 +350,48 @@ lp_build_blend_aos(struct gallivm_state *gallivm,
       bld.has_dst_alpha = desc->swizzle[3] <= PIPE_SWIZZLE_W;
    }
 
-   if (blend->logicop_enable) {
-      if(!type.floating) {
-         result = lp_build_logicop(gallivm->builder, blend->logicop_func, src, dst);
-      }
-      else {
-         result = src;
-      }
-   } else if (!state->blend_enable) {
-      result = src;
-   } else {
-      boolean rgb_alpha_same = (state->rgb_src_factor == state->rgb_dst_factor &&
-                                state->alpha_src_factor == state->alpha_dst_factor) ||
-                               nr_channels == 1;
-
-      src_factor = lp_build_blend_factor(&bld, state->rgb_src_factor,
-                                         state->alpha_src_factor,
-                                         alpha_swizzle,
-                                         nr_channels);
-
-      dst_factor = lp_build_blend_factor(&bld, state->rgb_dst_factor,
-                                         state->alpha_dst_factor,
-                                         alpha_swizzle,
-                                         nr_channels);
-
-      result = lp_build_blend(&bld.base,
-                              state->rgb_func,
-                              state->rgb_src_factor,
-                              state->rgb_dst_factor,
-                              src,
-                              dst,
-                              src_factor,
-                              dst_factor,
-                              rgb_alpha_same,
-                              false);
-
-      if(state->rgb_func != state->alpha_func && nr_channels > 1 &&
-                            alpha_swizzle != PIPE_SWIZZLE_NONE) {
-         LLVMValueRef alpha;
-
-         alpha = lp_build_blend(&bld.base,
-                                state->alpha_func,
-                                state->alpha_src_factor,
-                                state->alpha_dst_factor,
-                                src,
-                                dst,
-                                src_factor,
-                                dst_factor,
-                                rgb_alpha_same,
-                                false);
-
-         result = lp_build_blend_swizzle(&bld,
-                                         result,
-                                         alpha,
-                                         LP_BUILD_BLEND_SWIZZLE_RGBA,
-                                         alpha_swizzle,
-                                         nr_channels);
-      }
-   }
-
-   /* Check if color mask is necessary */
-   if (!util_format_colormask_full(desc, state->colormask)) {
-      LLVMValueRef color_mask;
-
-      color_mask = lp_build_const_mask_aos_swizzled(gallivm, bld.base.type,
-                                                    state->colormask, nr_channels, swizzle);
-      lp_build_name(color_mask, "color_mask");
-
-      /* Combine with input mask if necessary */
-      if (mask) {
-         /* We can be blending floating values but masks are always integer... */
-         unsigned floating = bld.base.type.floating;
-         bld.base.type.floating = 0;
-
-         mask = lp_build_and(&bld.base, color_mask, mask);
-
-         bld.base.type.floating = floating;
-      } else {
-         mask = color_mask;
-      }
-   }
-
-   /* Apply mask, if one exists */
-   if (mask) {
-      result = lp_build_select(&bld.base, mask, result, dst);
+   src_factor = lp_build_blend_factor(&bld, state->rgb_src_factor,
+                                      state->alpha_src_factor,
+                                      alpha_swizzle,
+                                      nr_channels);
+
+   dst_factor = lp_build_blend_factor(&bld, state->rgb_dst_factor,
+                                      state->alpha_dst_factor,
+                                      alpha_swizzle,
+                                      nr_channels);
+
+   result = lp_build_blend(&bld.base,
+                           state->rgb_func,
+                           state->rgb_src_factor,
+                           state->rgb_dst_factor,
+                           src,
+                           dst,
+                           src_factor,
+                           dst_factor,
+                           rgb_alpha_same,
+                           false);
+
+   if(state->rgb_func != state->alpha_func && nr_channels > 1 &&
+                         alpha_swizzle != PIPE_SWIZZLE_NONE) {
+      LLVMValueRef alpha;
+
+      alpha = lp_build_blend(&bld.base,
+                             state->alpha_func,
+                             state->alpha_src_factor,
+                             state->alpha_dst_factor,
+                             src,
+                             dst,
+                             src_factor,
+                             dst_factor,
+                             rgb_alpha_same,
+                             false);
+
+      result = lp_build_blend_swizzle(&bld,
+                                      result,
+                                      alpha,
+                                      LP_BUILD_BLEND_SWIZZLE_RGBA,
+                                      alpha_swizzle,
+                                      nr_channels);
    }
 
    return result;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index af47b52..27d6452 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -1749,6 +1749,11 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
 
    const boolean is_1d = variant->key.resource_1d;
    boolean twiddle_after_convert = FALSE;
+
+   const struct pipe_blend_state *blend = &variant->key.blend;
+   const struct pipe_rt_blend_state *state = &blend->rt[rt];
+   boolean has_blend = !blend->logicop_enable && state->blend_enable;
+
    unsigned num_fullblock_fs = is_1d ? 2 * num_fs : num_fs;
    LLVMValueRef fpstate = 0;
 
@@ -2057,14 +2062,14 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
    /*
     * Blend Colour conversion
     */
-   blend_color = lp_jit_context_f_blend_color(gallivm, context_ptr);
-   blend_color = LLVMBuildPointerCast(builder, blend_color,
-                    LLVMPointerType(lp_build_vec_type(gallivm, fs_type), 0), "");
-   blend_color = LLVMBuildLoad(builder, LLVMBuildGEP(builder, blend_color,
-                               &i32_zero, 1, ""), "");
-
-   /* Convert */
-   lp_build_conv(gallivm, fs_type, blend_type, &blend_color, 1, &blend_color, 1);
+   if (has_blend) {
+      blend_color = lp_jit_context_f_blend_color(gallivm, context_ptr);
+      blend_color = LLVMBuildPointerCast(builder, blend_color,
+                       LLVMPointerType(lp_build_vec_type(gallivm, fs_type), 0), "");
+      blend_color = LLVMBuildLoad(builder, LLVMBuildGEP(builder, blend_color,
+                                  &i32_zero, 1, ""), "");
+      lp_build_conv(gallivm, fs_type, blend_type, &blend_color, 1, &blend_color, 1);
+   }
 
    if (out_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
       /*
@@ -2092,20 +2097,27 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
       }
       /* probably can't be different than row_type but better safe than sorry... */
       lp_build_context_init(&f32_bld, gallivm, blend_type);
-      blend_color = lp_build_clamp(&f32_bld, blend_color, f32_bld.zero, f32_bld.one);
+      if (has_blend) {
+         blend_color = lp_build_clamp(&f32_bld, blend_color, f32_bld.zero, f32_bld.one);
+      }
    }
 
-   /* Extract alpha */
-   blend_alpha = lp_build_extract_broadcast(gallivm, blend_type, row_type, blend_color, lp_build_const_int32(gallivm, 3));
-
    /* Swizzle to appropriate channels, e.g. from RGBA to BGRA BGRA */
    pad_inline &= (dst_channels * (block_size / src_count) * row_type.width) != vector_width;
-   if (pad_inline) {
-      /* Use all 4 channels e.g. from RGBA RGBA to RGxx RGxx */
-      blend_color = lp_build_swizzle_aos_n(gallivm, blend_color, swizzle, TGSI_NUM_CHANNELS, row_type.length);
-   } else {
-      /* Only use dst_channels e.g. RGBA RGBA to RG RG xxxx */
-      blend_color = lp_build_swizzle_aos_n(gallivm, blend_color, swizzle, dst_channels, row_type.length);
+
+   if (has_blend) {
+      /* Extract alpha */
+      blend_alpha = lp_build_extract_broadcast(gallivm, blend_type, row_type, blend_color,
+                                               lp_build_const_int32(gallivm, 3));
+      if (pad_inline) {
+         /* Use all 4 channels e.g. from RGBA RGBA to RGxx RGxx */
+         blend_color = lp_build_swizzle_aos_n(gallivm, blend_color, swizzle,
+                                              TGSI_NUM_CHANNELS, row_type.length);
+      } else {
+         /* Only use dst_channels e.g. RGBA RGBA to RG RG xxxx */
+         blend_color = lp_build_swizzle_aos_n(gallivm, blend_color, swizzle,
+                                              dst_channels, row_type.length);
+      }
    }
 
    /*
@@ -2157,7 +2169,7 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
    /*
     * Alpha conversion
     */
-   if (!has_alpha) {
+   if (!has_alpha && has_blend) {
       struct lp_type alpha_type = fs_type;
       alpha_type.length = 4;
       convert_alpha(gallivm, row_type, alpha_type,
@@ -2299,28 +2311,77 @@ generate_unswizzled_blend(struct gallivm_state *gallivm,
    convert_to_blend_type(gallivm, block_size, out_format_desc, dst_type,
                          row_type, dst, src_count);
 
+   if (has_blend) {
+      int nr_channels = pad_inline ? 4 : dst_channels;
+      for (i = 0; i < src_count; ++i) {
+         src[i] = lp_build_blend_aos(gallivm,
+                                     &variant->key.blend,
+                                     out_format,
+                                     row_type,
+                                     rt,
+                                     src[i],
+                                     has_alpha ? NULL : src_alpha[i],
+                                     src1[i],
+                                     has_alpha ? NULL : src1_alpha[i],
+                                     dst[i],
+                                     blend_color,
+                                     has_alpha ? NULL : blend_alpha,
+                                     swizzle,
+                                     nr_channels);
+      }
+   }
+
    /*
-    * FIXME: Really should get logic ops / masks out of generic blend / row
-    * format. Logic ops will definitely not work on the blend float format
-    * used for SRGB here and I think OpenGL expects this to work as expected
-    * (that is incoming values converted to srgb then logic op applied).
+    * FIXME: mask / color mask / logic op should be done in dst format,
+    * not blend format (otherwise there's pointless conversion from
+    * dst to blend format when there's no blending).
     */
+   else if (blend->logicop_enable && !row_type.floating &&
+            out_format_desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
+      /*
+       * logicops are no-oped when format is srgb or float.
+       * However, blend still stays disabled in this case.
+       */
+      for (i = 0; i < src_count; ++i) {
+         src[i] = lp_build_logicop(gallivm->builder, blend->logicop_func,
+                                   src[i], dst[i]);
+      }
+   }
+
    for (i = 0; i < src_count; ++i) {
-      dst[i] = lp_build_blend_aos(gallivm,
-                                  &variant->key.blend,
-                                  out_format,
-                                  row_type,
-                                  rt,
-                                  src[i],
-                                  has_alpha ? NULL : src_alpha[i],
-                                  src1[i],
-                                  has_alpha ? NULL : src1_alpha[i],
-                                  dst[i],
-                                  partial_mask ? src_mask[i] : NULL,
-                                  blend_color,
-                                  has_alpha ? NULL : blend_alpha,
-                                  swizzle,
-                                  pad_inline ? 4 : dst_channels);
+      LLVMValueRef mask;
+      int nr_channels = pad_inline ? 4 : dst_channels;
+      struct lp_build_context bldmask;
+
+      lp_build_context_init(&bldmask, gallivm, row_type);
+
+      mask = partial_mask ? src_mask[i] : NULL;
+
+      /* Check if color mask is necessary */
+      if (!util_format_colormask_full(out_format_desc, state->colormask)) {
+         LLVMValueRef color_mask;
+
+         color_mask = lp_build_const_mask_aos_swizzled(gallivm, row_type,
+                                                       state->colormask,
+                                                       nr_channels, swizzle);
+         lp_build_name(color_mask, "color_mask");
+
+         /* Combine with input mask if necessary */
+         if (partial_mask) {
+
+            mask = LLVMBuildAnd(builder, color_mask, mask, "");
+
+         } else {
+            mask = color_mask;
+         }
+      }
+
+      /* Apply mask, if one exists */
+      if (mask) {
+         dst[i] = lp_build_select(&bldmask, mask, src[i], dst[i]);
+      } else {
+         dst[i] = src[i];
+      }
    }
 
    convert_from_blend_type(gallivm, block_size, out_format_desc,
diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c
index 13bed08..a1d4a1d 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_blend.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c
@@ -178,7 +178,7 @@ add_blend_test(struct gallivm_state *gallivm,
    con = LLVMBuildLoad(builder, const_ptr, "const");
 
    res = lp_build_blend_aos(gallivm, blend, format, type, rt, src, NULL,
-                            src1, NULL, dst, NULL, con, NULL, swizzle, 4);
+                            src1, NULL, dst, con, NULL, swizzle, 4);
 
    lp_build_name(res, "res");
 
-- 
2.7.4



More information about the mesa-dev mailing list