[Mesa-dev] [PATCH 3/4] i965: Attempt to blit for larger textures

Jason Ekstrand jason at jlekstrand.net
Wed Jan 14 10:42:01 PST 2015


On Tue, Jan 13, 2015 at 11:37 PM, Ben Widawsky <benjamin.widawsky at intel.com>
wrote:

> The blit engine is limited to 32Kx32K transfer. In cases where we have to
> fall
> back to the blitter, and when trying to blit a slice of a 2d texture
> array, or
> face of a cube map, we don't need to transfer the entire texture.
>
> I doubt this patch will get exercised at this point since we'll always
> allocate
> a linear BO for huge buffers. The next patch changes that.
>
> v2: Fix NDEBUG warning
>
> Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
> ---
>  src/mesa/drivers/dri/i965/intel_blit.c | 107
> ++++++++++++++++++++++++++++++++-
>  1 file changed, 105 insertions(+), 2 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/intel_blit.c
> b/src/mesa/drivers/dri/i965/intel_blit.c
> index 9500bd7..a56e394 100644
> --- a/src/mesa/drivers/dri/i965/intel_blit.c
> +++ b/src/mesa/drivers/dri/i965/intel_blit.c
> @@ -130,6 +130,104 @@ set_blitter_tiling(struct brw_context *brw,
>        ADVANCE_BATCH();                                                  \
>     } while (0)
>
> +
> +/* Returns the height of the tiling format. This would be measured in
> scanlines
> + * (of pitch bytes) */
> +static int
> +tile_height(uint32_t tiling)
> +{
> +   const long PAGE_SIZE = sysconf(_SC_PAGE_SIZE);
> +   switch (tiling) {
> +   case I915_TILING_X:
> +      return PAGE_SIZE / 512;
> +   case I915_TILING_Y:
> +      return PAGE_SIZE / 128;
> +   case I915_TILING_NONE:
> +   default:
> +      unreachable("Helper function is only used for tiled surfaces\n");
> +   }
> +}
> +
> +/* This function returns the offset to be used by the blit operation. It
> may
> + * modify the y if the texture would otherwise fail to be able to perform
> a
> + * blit. The x offset will not need to change based on the computations
> made by
> + * this function.
> + *
> + * By the time we get to this function, the miptree creation code should
> have
> + * already determined it's possible to blit the texture, so there should
> never
> + * be a case where this function fails.
> + */
> +static GLuint
> +intel_miptree_get_adjusted_y_offset(struct intel_mipmap_tree *mt, int
> slice,
> +                                    uint32_t *y)
> +{
> +   GLuint offset = mt->offset;
> +
> +   /* Convert an input number of rows: y into 2 values: an offset (page
> aligned
> +    * in byte units), and the remaining rows of y. The resulting 2 values
> will
> +    * be used as parameters for a blit operation [using the HW blit
> engine].
> +    * They will therefore conform to whatever restrictions are needed.
> +    *
> +    * XXX: This code assumes that LOD0 is always guaranteed to be properly
> +    * aligned for the blit operation. The round down only mutates y if
> the LOD
> +    * being adjusted isn't tile aligned. In other words, if input y is
> pointing
> +    * to LOD0 of a slice, the adjusted y should always be 0. Similarly if
> input
> +    * y is pointing to another LOD, and the offset happens to be tile
> aligned, y
> +    * will again be 0.
> +    *
> +    * The following diagram shows how the blit parameters are modified.
> In the
> +    * example, is is trying to blit with LOD1 from slice[x] as a surface,
> and
> +    * LOD1 is not properly tile aligned.  "TA" means tile aligned. The
> rectangle
> +    * is the BO that contains the mipmaps. There may be an offset from
> the start
> +    * of the BO to the first slice.
> +    *
> +    *                   INPUT                               OUTPUT
> +    *   0    +---------------------------+
> +    *        |                           |
> +---------------------------+
> +    * offset |  slice[0]...slice[x-2]    | offset |  +----------+
>      |
> +    *        |                           |        |  |  lod0    |
> slice[x]    |
> +    *   TA   |  +----------+             |        |  |          |
>      |
> +    *        |  |  lod0    | slice[x-1]  |        |  +----------+
>      |
> +    *        |  |          |             |  y---> |  +---+ +-+
>     |
> +    *        |  +----------+             |        |  |   | +-+
>     |
> +    *        |  +---+ +-+                |        |  +---+ *
>     |
> +    *        |  |   | +-+                |        |
>      |
> +    *        |  +---+ *                  |        |  slice[x+1]...
>     |
> +    *        |                           |
> +---------------------------+
> +    *        |  // qpitch padding        |
> +    *        |                           |
> +    *   TA   |  +----------+             |
> +    *        |  |  lod0    | slice[x]    |
> +    *        |  |          |             |
> +    *        |  +----------+             |
> +    *  y---> |  +---+ +-+                |
> +    *        |  |   | +-+                |
> +    *        |  +---+ *                  |
> +    *        |                           |
> +    *        |  slice[x+1]...            |
> +    *        +---------------------------+
> +    */
> +   if (slice > 0 && *y >= 32768) {
>

Why are we going through all these hoops to avoid the adjustment?  Does
setting an offset cost us something we want to avoid?  Also, I think the
check above needs to check y2 not y1 because y2 is larger and will actually
be the determining factor on whether or not we can blit.
--Jason


> +      const long PAGE_MASK = sysconf(_SC_PAGE_SIZE) - 1;
> +      (void) PAGE_MASK;
> +
> +      /* Since we need to output a page aligned offset, the original
> offset must
> +       * also be page aligned. For tiled buffers, it always should be. */
> +      assert((offset & PAGE_MASK) == 0);
> +
> +      /* Adjust the y value to pick the nearest tile aligned mipmap row */
> +      unsigned tile_aligned_row = ROUND_DOWN_TO(*y,
> tile_height(mt->tiling));
> +      *y -= tile_aligned_row;
> +
> +      /* Convert tiled aligned row to a byte offset for use by the
> blitter */
> +      tile_aligned_row *= mt->pitch;
> +      assert((tile_aligned_row & PAGE_MASK) == 0);
> +      offset += tile_aligned_row;
> +   }
> +
> +   return offset;
> +}
> +
>  /**
>   * Implements a rectangular block transfer (blit) of pixels between two
>   * miptrees.
> @@ -236,6 +334,11 @@ intel_miptree_blit(struct brw_context *brw,
>     dst_x += dst_image_x;
>     dst_y += dst_image_y;
>
> +   GLuint src_offset = intel_miptree_get_adjusted_y_offset(src_mt,
> src_slice,
> +                                                           &src_y);
> +   GLuint dst_offset = intel_miptree_get_adjusted_y_offset(dst_mt,
> dst_slice,
> +                                                           &dst_y);
> +
>     /* The blitter interprets the 16-bit destination x/y as a signed 16-bit
>      * value. The values we're working with are unsigned, so make sure we
> don't
>      * overflow.
> @@ -249,10 +352,10 @@ intel_miptree_blit(struct brw_context *brw,
>     if (!intelEmitCopyBlit(brw,
>                            src_mt->cpp,
>                            src_pitch,
> -                          src_mt->bo, src_mt->offset,
> +                          src_mt->bo, src_offset,
>                            src_mt->tiling,
>                            dst_mt->pitch,
> -                          dst_mt->bo, dst_mt->offset,
> +                          dst_mt->bo, dst_offset,
>                            dst_mt->tiling,
>                            src_x, src_y,
>                            dst_x, dst_y,
> --
> 2.2.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150114/50d2bd24/attachment-0001.html>


More information about the mesa-dev mailing list