[Mesa-dev] [PATCH 3/6] intel/blorp_blit: Adjust blorp surface parameters for split blits

Jason Ekstrand jason at jlekstrand.net
Tue Nov 29 16:29:25 UTC 2016


On Tue, Nov 22, 2016 at 7:04 PM, Jordan Justen <jordan.l.justen at intel.com>
wrote:

> If try_blorp_blit() previously returned that a blit was too large,
> shrink_surface_params() will be used to update the surface parameters
> for the smaller blit so the blit operation can proceed.
>
> Signed-off-by: Jordan Justen <jordan.l.justen at intel.com>
> ---
>  src/intel/blorp/blorp_blit.c | 124 ++++++++++++++++++++++++++++++
> +++++++++++--
>  1 file changed, 121 insertions(+), 3 deletions(-)
>
> diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c
> index caa3e33..383b64e 100644
> --- a/src/intel/blorp/blorp_blit.c
> +++ b/src/intel/blorp/blorp_blit.c
> @@ -1521,6 +1521,12 @@ dump_blorp_surf(const struct blorp_context *blorp,
>        blorp->unmap(blorp, &surf->aux_addr);
>  }
>
> +static bool
> +can_shrink_surfaces(const struct blorp_params *params)
> +{
> +   return false;
> +}
> +
>  struct blt_axis {
>     float src0, src1, dst0, dst1;
>     bool mirror;
> @@ -1767,12 +1773,114 @@ adjust_split_coords(const struct blt_axis *orig,
>     split_coords->src1 = orig->src1 + (scale >= 0.0 ? delta1 : delta0);
>  }
>
> +static const struct isl_extent2d
> +get_px_size_sa(const struct isl_surf *surf)
> +{
> +   static const struct isl_extent2d one_to_one = { .w = 1, .h = 1 };
> +
> +   if (surf->msaa_layout != ISL_MSAA_LAYOUT_INTERLEAVED)
> +      return one_to_one;
> +   else
> +      return isl_get_interleaved_msaa_px_size_sa(surf->samples);
> +}
> +
> +static void
> +shrink_surface_params(const struct isl_device *dev,
> +                      struct brw_blorp_surface_info *info,
> +                      int rgb_offset,
> +                      float *x0, float *x1, float *y0, float *y1)
> +{
> +   uint32_t byte_offset, x_offset_sa, y_offset_sa, size;
> +   struct isl_extent2d px_size_sa;
> +   int adjust;
> +
> +   uint32_t rgb_adjust = MAX2(rgb_offset, 0);
> +
> +   surf_convert_to_single_slice(dev, info);
> +
> +   px_size_sa = get_px_size_sa(&info->surf);
> +
> +   x_offset_sa =
> +      (uint32_t)*x0 * px_size_sa.w + info->tile_x_sa - rgb_adjust;
> +   y_offset_sa = (uint32_t)*y0 * px_size_sa.h + info->tile_y_sa;
> +   isl_tiling_get_intratile_offset_sa(dev, info->surf.tiling,
> +                                      info->surf.format,
> info->surf.row_pitch,
> +                                      x_offset_sa, y_offset_sa,
> +                                      &byte_offset,
> +                                      &info->tile_x_sa, &info->tile_y_sa);
> +
> +   info->addr.offset += byte_offset;
> +
> +   adjust = (int)info->tile_x_sa / px_size_sa.w - (int)*x0;
> +   uint32_t rgb_x_tile_offset =
> +      rgb_offset >= 0 ? (((int)*x0 + adjust) % 3) : 0u;
> +   adjust += (int)rgb_adjust - rgb_x_tile_offset;
> +   *x0 += adjust;
> +   assert(rgb_offset < 0 || (uint32_t)*x0 % 3 == rgb_adjust);
> +   *x1 += adjust;
> +   info->tile_x_sa = rgb_x_tile_offset;
> +
> +   adjust = (int)info->tile_y_sa / px_size_sa.h - (int)*y0;
> +   *y0 += adjust;
> +   *y1 += adjust;
> +   info->tile_y_sa = 0;
>

Ugh... These calculations are painful.  (Not a comment on your coding
ability; just a comment on the calculations.)

I think a lot of the pain is coming from the fact that you're doing it
before try_blorp_blit rather than at the end of try_blorp_blit.  This means
that you have to deal with partially lowered things (RGB in particular) but
can't actually take advantage of the offset parameters we pass to the
shader (because they aren't calculated yet).  If you did it at the end of
try_blorp_blit, you could probably do something like this (WARNING: This
may not even compile):

shrink_surface_to_fit(const struct isl_dev *isl_dev, struct
*blorp_surface_info *info, struct rect rect)
{
   surf_convert_to_single_slice(dev, info);
   px_size_sa = get_px_size_sa(&info->surf);
   const uint32_t rect_x_sa = (uint32_t)rect.x0 / pix_size_sa.w;
   const uint32_t rect_y_sa = (uint32_t)rect.y0 / pix_size_sa.h;
   const uint32_t rect_w_px = ceilf(rect.x1) - floorf(rect.x0);
   const uint32_t rect_h_px = ceilf(rect.y1) - floorf(rect.y0);

   uint32_t tile_x_sa, tile_y_sa, byte_offsets;
   isl_tiling_get_intratile_offset_sa(dev, info->surf.tiling,
                                      info->surf.format,
info->surf.row_pitch,
                                      rect_x_sa, rect_y_sa,
                                      &byte_offset,
                                      &tile_x_sa, &tile_y_sa);
   assert(tile_x_sa % px_size_sa.w == 0);
   assert(tile_y_sa % px_size_sa.h == 0);

   /* What we actually want here is the offset to the tile, not the
intratile offset */
   const uint32_t tile_pos_x_sa = rect_x_sa - tile_x_sa;
   const uint32_t tile_pos_y_sa = rect_y_sa - tile_y_sa;

   /* Tell the shader that the origin of the surface is actually somewhere
above and to the left of the actual top-left corner. */
   info->tile_x_sa -= tile_pos_x_sa;
   info->tile_y_sa -= tile_pos_y_sa;

   /* Adjust the surface */
   info->addr.offset += byte_offset;
   info->surf.logical_level0_px.w = rect_w_px + (tile_x_sa / px_size_sa.w);
   info->surf.logical_level0_px.h = rect_w_px + (tile_x_sa / px_size_sa.h);
   info->surf.phys_level0_sa.w = rect_w_px * px_size_sa.w + tile_x_sa;
   info->surf.phys_level0_sa.h = rect_h_px * px_size_sa.h + tile_y_sa;
}

Of course, this requires that we have the source rectangle as well as the
destination rectangle, but that shouldn't be too hard to get.   You would
just have to move all of the rectangle adjustment code into the surface
adjustement helper so that it happens on both source and destination.  It
would also require tweaking some of the shader code.  Am I making any
sense?  Am I crazy?


> +
> +   size = ceilf(*x1 + rgb_x_tile_offset);
> +   size = MIN2(size, info->surf.logical_level0_px.width);
> +   float phys_scale =
> +      info->surf.phys_level0_sa.width / info->surf.logical_level0_px.w
> idth;
> +   info->surf.logical_level0_px.width = size;
> +   info->surf.phys_level0_sa.width =
> +      (uint32_t)ceilf(phys_scale * size);
> +
> +   size = ceilf(*y1);
> +   size = MIN2(size, info->surf.logical_level0_px.height);
> +   phys_scale =
> +      info->surf.phys_level0_sa.height / info->surf.logical_level0_px.h
> eight;
> +   info->surf.logical_level0_px.height = (uint32_t)ceilf(size);
> +   info->surf.phys_level0_sa.height =
> +      (uint32_t)ceilf(phys_scale * size);
> +}
> +
> +static void
> +shrink_surfaces(const struct isl_device *dev,
> +                struct blorp_params *params,
> +                struct brw_blorp_blit_prog_key *wm_prog_key,
> +                const struct blt_coords *orig_coords,
> +                struct blt_coords *coords)
> +{
> +   /* Shrink source surface */
> +   shrink_surface_params(dev,
> +                         &params->src,
> +                         -1,
> +                         &coords->x.src0,
> +                         &coords->x.src1,
> +                         &coords->y.src0,
> +                         &coords->y.src1);
> +   wm_prog_key->need_src_offset = false;
> +
> +   /* Shrink destination surface */
> +   int rgb_offset =
> +      wm_prog_key->dst_rgb ?
> +      (uint32_t)(coords->x.dst0 - orig_coords->x.dst0) % 3 : -1;
> +   shrink_surface_params(dev,
> +                         &params->dst,
> +                         rgb_offset,
> +                         &coords->x.dst0,
> +                         &coords->x.dst1,
> +                         &coords->y.dst0,
> +                         &coords->y.dst1);
> +   wm_prog_key->need_dst_offset = wm_prog_key->dst_rgb;
> +}
> +
>  static void
>  do_blorp_blit(struct blorp_batch *batch,
> -              struct blorp_params *params,
> +              const struct blorp_params *orig_params,
>                struct brw_blorp_blit_prog_key *wm_prog_key,
>                const struct blt_coords *orig)
>  {
> +   struct blorp_params params;
> +   struct blt_coords blit_coords;
>     struct blt_coords split_coords = *orig;
>     float w = orig->x.dst1 - orig->x.dst0;
>     float h = orig->y.dst1 - orig->y.dst0;
> @@ -1784,9 +1892,16 @@ do_blorp_blit(struct blorp_batch *batch,
>        y_scale = -y_scale;
>
>     bool x_done, y_done;
> +   bool shrink = false;
>     do {
> +      params = *orig_params;
> +      blit_coords = split_coords;
> +      if (shrink) {
> +         shrink_surfaces(batch->blorp->isl_dev, &params, wm_prog_key,
> orig,
> +                         &blit_coords);
> +      }
>        unsigned result =
> -         try_blorp_blit(batch, params, wm_prog_key, &split_coords);
> +         try_blorp_blit(batch, &params, wm_prog_key, &blit_coords);
>
>        if (result & BLIT_WIDTH_TOO_LARGE) {
>           w /= 2.0;
> @@ -1801,8 +1916,11 @@ do_blorp_blit(struct blorp_batch *batch,
>           adjust_split_coords(&orig->y, &split_coords.y, y_scale);
>        }
>
> -      if (result != 0)
> +      if (result != 0) {
> +         assert(can_shrink_surfaces(orig_params));
> +         shrink = true;
>           continue;
> +      }
>
>        y_done = (orig->y.dst1 - split_coords.y.dst1 < 0.5);
>        x_done = y_done && (orig->x.dst1 - split_coords.x.dst1 < 0.5);
> --
> 2.10.2
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20161129/c3703001/attachment.html>


More information about the mesa-dev mailing list