[Mesa-dev] [PATCH 2/2] intel/blorp: Take an explicit filter parameter in blorp_blit

Jason Ekstrand jason at jlekstrand.net
Tue Jun 26 20:46:14 UTC 2018


This lets us move the glBlitFramebuffer nonsense into the GL driver and
make the usage of BLORP mutch more explicit and obvious as to what it's
doing.
---
 src/intel/blorp/blorp.h               |  3 +-
 src/intel/blorp/blorp_blit.c          | 44 ++-----------------
 src/intel/vulkan/anv_blorp.c          | 34 +++++++++++----
 src/mesa/drivers/dri/i965/brw_blorp.c | 63 ++++++++++++++++++++++++++-
 4 files changed, 93 insertions(+), 51 deletions(-)

diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h
index 6e2f888d17f..ee343a4a6bb 100644
--- a/src/intel/blorp/blorp.h
+++ b/src/intel/blorp/blorp.h
@@ -139,7 +139,8 @@ blorp_blit(struct blorp_batch *batch,
            float src_x1, float src_y1,
            float dst_x0, float dst_y0,
            float dst_x1, float dst_y1,
-           uint32_t filter, bool mirror_x, bool mirror_y);
+           enum blorp_filter filter,
+           bool mirror_x, bool mirror_y);
 
 void
 blorp_copy(struct blorp_batch *batch,
diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c
index bdd7c667205..2b8a11eab50 100644
--- a/src/intel/blorp/blorp_blit.c
+++ b/src/intel/blorp/blorp_blit.c
@@ -2207,7 +2207,8 @@ blorp_blit(struct blorp_batch *batch,
            float src_x1, float src_y1,
            float dst_x0, float dst_y0,
            float dst_x1, float dst_y1,
-           GLenum filter, bool mirror_x, bool mirror_y)
+           enum blorp_filter filter,
+           bool mirror_x, bool mirror_y)
 {
    struct blorp_params params;
    blorp_params_init(&params);
@@ -2236,14 +2237,10 @@ blorp_blit(struct blorp_batch *batch,
    params.dst.view.swizzle = dst_swizzle;
 
    struct brw_blorp_blit_prog_key wm_prog_key = {
-      .shader_type = BLORP_SHADER_TYPE_BLIT
+      .shader_type = BLORP_SHADER_TYPE_BLIT,
+      .filter = filter,
    };
 
-   /* Scaled blitting or not. */
-   const bool blit_scaled =
-      ((dst_x1 - dst_x0) == (src_x1 - src_x0) &&
-       (dst_y1 - dst_y0) == (src_y1 - src_y0)) ? false : true;
-
    /* Scaling factors used for bilinear filtering in multisample scaled
     * blits.
     */
@@ -2253,39 +2250,6 @@ blorp_blit(struct blorp_batch *batch,
       wm_prog_key.x_scale = 2.0f;
    wm_prog_key.y_scale = params.src.surf.samples / wm_prog_key.x_scale;
 
-   const bool bilinear_filter = filter == GL_LINEAR &&
-                                params.src.surf.samples <= 1 &&
-                                params.dst.surf.samples <= 1;
-
-   /* We are downsampling a non-integer color buffer, so blend.
-    *
-    * Regarding integer color buffers, the OpenGL ES 3.2 spec says:
-    *
-    *    "If the source formats are integer types or stencil values, a
-    *    single sample's value is selected for each pixel."
-    *
-    * This implies we should not blend in that case.
-    */
-   const bool blend =
-      (params.src.surf.usage & ISL_SURF_USAGE_DEPTH_BIT) == 0 &&
-      (params.src.surf.usage & ISL_SURF_USAGE_STENCIL_BIT) == 0 &&
-      !isl_format_has_int_channel(params.src.surf.format) &&
-      params.src.surf.samples > 1 &&
-      params.dst.surf.samples <= 1;
-
-   if (blend && !blit_scaled) {
-      wm_prog_key.filter = BLORP_FILTER_AVERAGE;
-   } else if (blend && blit_scaled) {
-      wm_prog_key.filter = BLORP_FILTER_BILINEAR;
-   } else if (bilinear_filter) {
-      wm_prog_key.filter = BLORP_FILTER_BILINEAR;
-   } else {
-      if (params.src.surf.samples > 1)
-         wm_prog_key.filter = BLORP_FILTER_SAMPLE_0;
-      else
-         wm_prog_key.filter = BLORP_FILTER_NEAREST;
-   }
-
    params.wm_inputs.rect_grid.x1 =
       minify(params.src.surf.logical_level0_px.width, src_level) *
       wm_prog_key.x_scale - 1.0f;
diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index ec4a7756bb6..72b5b37f4cc 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -514,13 +514,13 @@ void anv_CmdBlitImage(
 
    struct blorp_surf src, dst;
 
-   uint32_t gl_filter;
+   enum blorp_filter blorp_filter;
    switch (filter) {
    case VK_FILTER_NEAREST:
-      gl_filter = 0x2600; /* GL_NEAREST */
+      blorp_filter = BLORP_FILTER_NEAREST;
       break;
    case VK_FILTER_LINEAR:
-      gl_filter = 0x2601; /* GL_LINEAR */
+      blorp_filter = BLORP_FILTER_BILINEAR;
       break;
    default:
       unreachable("Invalid filter");
@@ -605,7 +605,7 @@ void anv_CmdBlitImage(
                     dst_format.isl_format, dst_format.swizzle,
                     src_x0, src_y0, src_x1, src_y1,
                     dst_x0, dst_y0, dst_x1, dst_y1,
-                    gl_filter, flip_x, flip_y);
+                    blorp_filter, flip_x, flip_y);
       }
 
    }
@@ -1172,7 +1172,8 @@ resolve_surface(struct blorp_batch *batch,
                 struct blorp_surf *dst_surf,
                 uint32_t dst_level, uint32_t dst_layer,
                 uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y,
-                uint32_t width, uint32_t height)
+                uint32_t width, uint32_t height,
+                enum blorp_filter filter)
 {
    blorp_blit(batch,
               src_surf, src_level, src_layer,
@@ -1181,7 +1182,7 @@ resolve_surface(struct blorp_batch *batch,
               ISL_FORMAT_UNSUPPORTED, ISL_SWIZZLE_IDENTITY,
               src_x, src_y, src_x + width, src_y + height,
               dst_x, dst_y, dst_x + width, dst_y + height,
-              0x2600 /* GL_NEAREST */, false, false);
+              filter, false, false);
 }
 
 static void
@@ -1220,13 +1221,22 @@ resolve_image(struct anv_device *device,
                                         dst_surf.aux_usage,
                                         dst_level, dst_layer, 1);
 
+      enum blorp_filter filter;
+      if ((src_surf.surf->usage & ISL_SURF_USAGE_DEPTH_BIT) ||
+          (src_surf.surf->usage & ISL_SURF_USAGE_STENCIL_BIT) ||
+          isl_format_has_int_channel(src_surf.surf->format)) {
+         filter = BLORP_FILTER_SAMPLE_0;
+      } else {
+         filter = BLORP_FILTER_AVERAGE;
+      }
+
       assert(!src_image->format->can_ycbcr);
       assert(!dst_image->format->can_ycbcr);
 
       resolve_surface(batch,
                       &src_surf, src_level, src_layer,
                       &dst_surf, dst_level, dst_layer,
-                      src_x, src_y, dst_x, dst_y, width, height);
+                      src_x, src_y, dst_x, dst_y, width, height, filter);
    }
 }
 
@@ -1341,6 +1351,13 @@ anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer)
          assert(src_iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT &&
                 dst_iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT);
 
+         enum blorp_filter filter;
+         if (isl_format_has_int_channel(src_iview->planes[0].isl.format)) {
+            filter = BLORP_FILTER_SAMPLE_0;
+         } else {
+            filter = BLORP_FILTER_AVERAGE;
+         }
+
          struct blorp_surf src_surf, dst_surf;
          get_blorp_surf_for_anv_image(cmd_buffer->device, src_iview->image,
                                       VK_IMAGE_ASPECT_COLOR_BIT,
@@ -1382,7 +1399,8 @@ anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer)
                             base_dst_layer + i,
                             render_area.offset.x, render_area.offset.y,
                             render_area.offset.x, render_area.offset.y,
-                            render_area.extent.width, render_area.extent.height);
+                            render_area.extent.width, render_area.extent.height,
+                            filter);
          }
       }
 
diff --git a/src/mesa/drivers/dri/i965/brw_blorp.c b/src/mesa/drivers/dri/i965/brw_blorp.c
index 8c6d77e1b7d..1a239ea5c2e 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp.c
+++ b/src/mesa/drivers/dri/i965/brw_blorp.c
@@ -287,7 +287,7 @@ brw_blorp_blit_miptrees(struct brw_context *brw,
                         float src_x1, float src_y1,
                         float dst_x0, float dst_y0,
                         float dst_x1, float dst_y1,
-                        GLenum filter, bool mirror_x, bool mirror_y,
+                        GLenum gl_filter, bool mirror_x, bool mirror_y,
                         bool decode_srgb, bool encode_srgb)
 {
    const struct gen_device_info *devinfo = &brw->screen->devinfo;
@@ -324,6 +324,65 @@ brw_blorp_blit_miptrees(struct brw_context *brw,
       src_format = dst_format = MESA_FORMAT_R_FLOAT32;
    }
 
+   enum blorp_filter blorp_filter;
+   if (fabs(dst_x1 - dst_x0) == fabs(src_x1 - src_x0) &&
+       fabs(dst_y1 - dst_y0) == fabs(src_y1 - src_y0)) {
+      if (src_mt->surf.samples > 1 && dst_mt->surf.samples <= 1) {
+         /* From the OpenGL ES 3.2 specification, section 16.2.1:
+          *
+          *    "If the read framebuffer is multisampled (its effective value
+          *    of SAMPLE_BUFFERS is one) and the draw framebuffer is not (its
+          *    value of SAMPLE_BUFFERS is zero), the samples corresponding to
+          *    each pixel location in the source are converted to a single
+          *    sample before being written to the destination.  The filter
+          *    parameter is ignored. If the source formats are integer types
+          *    or stencil values, a single sample’s value is selected for each
+          *    pixel.  If the source formats are floating-point or normalized
+          *    types, the sample values for each pixel are resolved in an
+          *    implementation-dependent manner.  If the source formats are
+          *    depth values, sample values are resolved in an implementation-
+          *    dependent manner where the result will be between the minimum
+          *    and maximum depth values in the pixel."
+          *
+          * For depth and stencil resolves, we choose to always use the value
+          * at sample 0.
+          */
+         GLenum base_format = _mesa_get_format_base_format(src_mt->format);
+         if (base_format == GL_DEPTH_COMPONENT ||
+             base_format == GL_STENCIL_INDEX ||
+             base_format == GL_DEPTH_STENCIL ||
+             _mesa_is_format_integer(src_mt->format)) {
+            /* The OpenGL ES 3.2 spec says:
+             *
+             *    "If the source formats are integer types or stencil values,
+             *    a single sample's value is selected for each pixel."
+             *
+             * Just take sample 0 in this case.
+             */
+            blorp_filter = BLORP_FILTER_SAMPLE_0;
+         } else {
+            blorp_filter = BLORP_FILTER_AVERAGE;
+         }
+      } else {
+         /* From the OpenGL 4.6 specification, section 18.3.1:
+          *
+          *    "If the source and destination dimensions are identical, no
+          *    filtering is applied."
+          *
+          * Using BLORP_FILTER_NONE will also handle the upsample case by
+          * replicating the one value in the source to all values in the
+          * destination.
+          */
+         blorp_filter = BLORP_FILTER_NONE;
+      }
+   } else if (gl_filter == GL_LINEAR ||
+              gl_filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
+              gl_filter == GL_SCALED_RESOLVE_NICEST_EXT) {
+      blorp_filter = BLORP_FILTER_BILINEAR;
+   } else {
+      blorp_filter = BLORP_FILTER_NEAREST;
+   }
+
    enum isl_format src_isl_format =
       brw_blorp_to_isl_format(brw, src_format, false);
    enum isl_aux_usage src_aux_usage =
@@ -369,7 +428,7 @@ brw_blorp_blit_miptrees(struct brw_context *brw,
               dst_isl_format, ISL_SWIZZLE_IDENTITY,
               src_x0, src_y0, src_x1, src_y1,
               dst_x0, dst_y0, dst_x1, dst_y1,
-              filter, mirror_x, mirror_y);
+              blorp_filter, mirror_x, mirror_y);
    blorp_batch_finish(&batch);
 
    intel_miptree_finish_write(brw, dst_mt, dst_level, dst_layer, 1,
-- 
2.17.1



More information about the mesa-dev mailing list