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

Ben Widawsky ben at bwidawsk.net
Thu Feb 5 18:49:07 PST 2015


On Wed, Jan 14, 2015 at 10:42:01AM -0800, Jason Ekstrand wrote:
> 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
> 

I don't understand your y2 vs. y1 comment, can you elaborate a bit?
You're right that the check can go. Personally, I liked the clarity for the
common case, it's just offset, whereas when you remove the if it's like - where
did all this adjustment come from. Not sure how strongly you feel about it, I'm
willing to change it if you do feel strongly.

> 
> > +      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
> >

-- 
Ben Widawsky, Intel Open Source Technology Center


More information about the mesa-dev mailing list