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.widaw...@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 <b...@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@lists.freedesktop.org > > http://lists.freedesktop.org/mailman/listinfo/mesa-dev > > -- Ben Widawsky, Intel Open Source Technology Center _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev