intel/blorp: Add a blorp_filter enum for use in blorp_blit
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 20 Jun 2018 05:05:57 +0000 (22:05 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 18 Jul 2018 16:47:28 +0000 (09:47 -0700)
At the moment, this is entirely internal but we'll expose it to clients
of the BLORP API in the next commit.

Reviewed-by: Chad Versace <chadversary@chromium.org>
src/intel/blorp/blorp.h
src/intel/blorp/blorp_blit.c
src/intel/blorp/blorp_priv.h

index 0a10ff91576acae28dcdf51a49a4943cf515d5cc..6e2f888d17f20cfa826ca252d3d2662bdaa476f5 100644 (file)
@@ -119,6 +119,14 @@ struct blorp_surf
    uint32_t tile_x_sa, tile_y_sa;
 };
 
+enum blorp_filter {
+   BLORP_FILTER_NONE,
+   BLORP_FILTER_NEAREST,
+   BLORP_FILTER_BILINEAR,
+   BLORP_FILTER_SAMPLE_0,
+   BLORP_FILTER_AVERAGE,
+};
+
 void
 blorp_blit(struct blorp_batch *batch,
            const struct blorp_surf *src_surf,
index f719aac1b8694bf3f16202bcfe2942226d364ed3..cdabf441e52890740cce26ddf39381a47b0ba2ec 100644 (file)
@@ -70,9 +70,6 @@ static void
 brw_blorp_blit_vars_init(nir_builder *b, struct brw_blorp_blit_vars *v,
                          const struct brw_blorp_blit_prog_key *key)
 {
-    /* Blended and scaled blits never use pixel discard. */
-    assert(!key->use_kill || !(key->blend && key->blit_scaled));
-
 #define LOAD_INPUT(name, type)\
    v->v_##name = BLORP_CREATE_NIR_INPUT(b->shader, name, type);
 
@@ -1164,18 +1161,6 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
       assert(key->persample_msaa_dispatch);
    }
 
-   if (key->blend) {
-      /* We are blending, which means we won't have an opportunity to
-       * translate the tiling and sample count for the texture surface.  So
-       * the surface state for the texture must be configured with the correct
-       * tiling and sample count.
-       */
-      assert(!key->src_tiled_w);
-      assert(key->tex_samples == key->src_samples);
-      assert(key->tex_layout == key->src_layout);
-      assert(key->tex_samples > 0);
-   }
-
    if (key->persample_msaa_dispatch) {
       /* It only makes sense to do persample dispatch if the render target is
        * configured as multisampled.
@@ -1251,10 +1236,8 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
     * If we need to kill pixels that are outside the destination rectangle,
     * now is the time to do it.
     */
-   if (key->use_kill) {
-      assert(!(key->blend && key->blit_scaled));
+   if (key->use_kill)
       blorp_nir_discard_if_outside_rect(&b, dst_pos, &v);
-   }
 
    src_pos = blorp_blit_apply_transform(&b, nir_i2f32(&b, dst_pos), &v);
    if (dst_pos->num_components == 3) {
@@ -1277,7 +1260,82 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
     * that we want to texture from.  Exception: if we are blending, then S is
     * irrelevant, because we are going to fetch all samples.
     */
-   if (key->blend && !key->blit_scaled) {
+   switch (key->filter) {
+   case BLORP_FILTER_NONE:
+   case BLORP_FILTER_NEAREST:
+   case BLORP_FILTER_SAMPLE_0:
+      /* We're going to use texelFetch, so we need integers */
+      if (src_pos->num_components == 2) {
+         src_pos = nir_f2i32(&b, src_pos);
+      } else {
+         assert(src_pos->num_components == 3);
+         src_pos = nir_vec3(&b, nir_channel(&b, nir_f2i32(&b, src_pos), 0),
+                                nir_channel(&b, nir_f2i32(&b, src_pos), 1),
+                                nir_channel(&b, src_pos, 2));
+      }
+
+      /* We aren't blending, which means we just want to fetch a single
+       * sample from the source surface.  The address that we want to fetch
+       * from is related to the X, Y and S values according to the formula:
+       *
+       * (X, Y, S) = decode_msaa(src_samples, detile(src_tiling, offset)).
+       *
+       * If the actual tiling and sample count of the source surface are
+       * not the same as the configuration of the texture, then we need to
+       * adjust the coordinates to compensate for the difference.
+       */
+      if (tex_tiled_w != key->src_tiled_w ||
+          key->tex_samples != key->src_samples ||
+          key->tex_layout != key->src_layout) {
+         src_pos = blorp_nir_encode_msaa(&b, src_pos, key->src_samples,
+                                         key->src_layout);
+         /* Now (X, Y, S) = detile(src_tiling, offset) */
+         if (tex_tiled_w != key->src_tiled_w)
+            src_pos = blorp_nir_retile_w_to_y(&b, src_pos);
+         /* Now (X, Y, S) = detile(tex_tiling, offset) */
+         src_pos = blorp_nir_decode_msaa(&b, src_pos, key->tex_samples,
+                                         key->tex_layout);
+      }
+
+      if (key->need_src_offset)
+         src_pos = nir_iadd(&b, src_pos, nir_load_var(&b, v.v_src_offset));
+
+      /* Now (X, Y, S) = decode_msaa(tex_samples, detile(tex_tiling, offset)).
+       *
+       * In other words: X, Y, and S now contain values which, when passed to
+       * the texturing unit, will cause data to be read from the correct
+       * memory location.  So we can fetch the texel now.
+       */
+      if (key->src_samples == 1) {
+         color = blorp_nir_txf(&b, &v, src_pos, key->texture_data_type);
+      } else {
+         nir_ssa_def *mcs = NULL;
+         if (key->tex_aux_usage == ISL_AUX_USAGE_MCS)
+            mcs = blorp_blit_txf_ms_mcs(&b, &v, src_pos);
+
+         color = blorp_nir_txf_ms(&b, &v, src_pos, mcs, key->texture_data_type);
+      }
+      break;
+
+   case BLORP_FILTER_BILINEAR:
+      assert(!key->src_tiled_w);
+      assert(key->tex_samples == key->src_samples);
+      assert(key->tex_layout == key->src_layout);
+
+      if (key->src_samples == 1) {
+         color = blorp_nir_tex(&b, &v, key, src_pos);
+      } else {
+         assert(!key->use_kill);
+         color = blorp_nir_manual_blend_bilinear(&b, src_pos, key->src_samples,
+                                                 key, &v);
+      }
+      break;
+
+   case BLORP_FILTER_AVERAGE:
+      assert(!key->src_tiled_w);
+      assert(key->tex_samples == key->src_samples);
+      assert(key->tex_layout == key->src_layout);
+
       /* Resolves (effecively) use texelFetch, so we need integers and we
        * don't care about the sample index if we got one.
        */
@@ -1302,65 +1360,10 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
                                                 key->tex_aux_usage,
                                                 key->texture_data_type);
       }
-   } else if (key->blend && key->blit_scaled) {
-      assert(!key->use_kill);
-      color = blorp_nir_manual_blend_bilinear(&b, src_pos, key->src_samples, key, &v);
-   } else {
-      if (key->bilinear_filter) {
-         color = blorp_nir_tex(&b, &v, key, src_pos);
-      } else {
-         /* We're going to use texelFetch, so we need integers */
-         if (src_pos->num_components == 2) {
-            src_pos = nir_f2i32(&b, src_pos);
-         } else {
-            assert(src_pos->num_components == 3);
-            src_pos = nir_vec3(&b, nir_channel(&b, nir_f2i32(&b, src_pos), 0),
-                                   nir_channel(&b, nir_f2i32(&b, src_pos), 1),
-                                   nir_channel(&b, src_pos, 2));
-         }
+      break;
 
-         /* We aren't blending, which means we just want to fetch a single
-          * sample from the source surface.  The address that we want to fetch
-          * from is related to the X, Y and S values according to the formula:
-          *
-          * (X, Y, S) = decode_msaa(src_samples, detile(src_tiling, offset)).
-          *
-          * If the actual tiling and sample count of the source surface are
-          * not the same as the configuration of the texture, then we need to
-          * adjust the coordinates to compensate for the difference.
-          */
-         if (tex_tiled_w != key->src_tiled_w ||
-             key->tex_samples != key->src_samples ||
-             key->tex_layout != key->src_layout) {
-            src_pos = blorp_nir_encode_msaa(&b, src_pos, key->src_samples,
-                                            key->src_layout);
-            /* Now (X, Y, S) = detile(src_tiling, offset) */
-            if (tex_tiled_w != key->src_tiled_w)
-               src_pos = blorp_nir_retile_w_to_y(&b, src_pos);
-            /* Now (X, Y, S) = detile(tex_tiling, offset) */
-            src_pos = blorp_nir_decode_msaa(&b, src_pos, key->tex_samples,
-                                            key->tex_layout);
-         }
-
-         if (key->need_src_offset)
-            src_pos = nir_iadd(&b, src_pos, nir_load_var(&b, v.v_src_offset));
-
-         /* Now (X, Y, S) = decode_msaa(tex_samples, detile(tex_tiling, offset)).
-          *
-          * In other words: X, Y, and S now contain values which, when passed to
-          * the texturing unit, will cause data to be read from the correct
-          * memory location.  So we can fetch the texel now.
-          */
-         if (key->src_samples == 1) {
-            color = blorp_nir_txf(&b, &v, src_pos, key->texture_data_type);
-         } else {
-            nir_ssa_def *mcs = NULL;
-            if (key->tex_aux_usage == ISL_AUX_USAGE_MCS)
-               mcs = blorp_blit_txf_ms_mcs(&b, &v, src_pos);
-
-            color = blorp_nir_txf_ms(&b, &v, src_pos, mcs, key->texture_data_type);
-         }
-      }
+   default:
+      unreachable("Invalid blorp filter");
    }
 
    if (!isl_swizzle_is_identity(key->src_swizzle)) {
@@ -1929,8 +1932,8 @@ try_blorp_blit(struct blorp_batch *batch,
 
    params->num_samples = params->dst.surf.samples;
 
-   if ((wm_prog_key->bilinear_filter ||
-        (wm_prog_key->blend && !wm_prog_key->blit_scaled)) &&
+   if ((wm_prog_key->filter == BLORP_FILTER_AVERAGE ||
+        wm_prog_key->filter == BLORP_FILTER_BILINEAR) &&
        batch->blorp->isl_dev->info->gen <= 6) {
       /* Gen4-5 don't support non-normalized texture coordinates */
       wm_prog_key->src_coords_normalized = true;
@@ -2241,7 +2244,7 @@ blorp_blit(struct blorp_batch *batch,
    };
 
    /* Scaled blitting or not. */
-   wm_prog_key.blit_scaled =
+   const bool blit_scaled =
       ((dst_x1 - dst_x0) == (src_x1 - src_x0) &&
        (dst_y1 - dst_y0) == (src_y1 - src_y0)) ? false : true;
 
@@ -2254,25 +2257,37 @@ 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;
 
-   if (filter == GL_LINEAR &&
-       params.src.surf.samples <= 1 && params.dst.surf.samples <= 1) {
-      wm_prog_key.bilinear_filter = true;
-   }
+   const bool bilinear_filter = filter == GL_LINEAR &&
+                                params.src.surf.samples <= 1 &&
+                                params.dst.surf.samples <= 1;
 
-   if ((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) {
-      /* 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.
-       */
-      wm_prog_key.blend = true;
+   /* If we are downsampling a non-integer color buffer, 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 =
@@ -2510,6 +2525,7 @@ blorp_copy(struct blorp_batch *batch,
 
    struct brw_blorp_blit_prog_key wm_prog_key = {
       .shader_type = BLORP_SHADER_TYPE_BLIT,
+      .filter = BLORP_FILTER_NONE,
       .need_src_offset = src_surf->tile_x_sa || src_surf->tile_y_sa,
       .need_dst_offset = dst_surf->tile_x_sa || dst_surf->tile_y_sa,
    };
index 40f8c09bbad5ce94df789c3f3d48dcf76e23dbbc..a6aa2aa415135ead32b94de5119c39b002ac13dd 100644 (file)
@@ -307,11 +307,7 @@ struct brw_blorp_blit_prog_key
     */
    bool dst_rgb;
 
-   /* True if all source samples should be blended together to produce each
-    * destination pixel.  If true, src_tiled_w must be false, tex_samples must
-    * equal src_samples, and tex_samples must be nonzero.
-    */
-   bool blend;
+   enum blorp_filter filter;
 
    /* True if the rectangle being sent through the rendering pipeline might be
     * larger than the destination rectangle, so the WM program should kill any
@@ -325,9 +321,6 @@ struct brw_blorp_blit_prog_key
     */
    bool persample_msaa_dispatch;
 
-   /* True for scaled blitting. */
-   bool blit_scaled;
-
    /* True if this blit operation may involve intratile offsets on the source.
     * In this case, we need to add the offset before texturing.
     */
@@ -343,9 +336,6 @@ struct brw_blorp_blit_prog_key
     */
    float x_scale;
    float y_scale;
-
-   /* True for blits with filter = GL_LINEAR. */
-   bool bilinear_filter;
 };
 
 /**