On Wed, Jun 10, 2015 at 3:34 PM, Anuj Phogat <anuj.pho...@gmail.com> wrote: > This patch enables using XY_FAST_COPY_BLT only for Yf/Ys tiled buffers. > It can be later turned on for other tiling patterns (X,Y) too. > > V3: Flush in between sequential fast copy blits. > Fix src/dst alignment requirements. > Make can_fast_copy_blit() helper. > Use ffs(), is_power_of_two() > Move overlap computation inside intel_miptree_blit(). > > V4: Use _mesa_regions_overlap() function. > Simplify horizontal and vertical alignment computations. > > Signed-off-by: Anuj Phogat <anuj.pho...@gmail.com> > Cc: Ben Widawsky <b...@bwidawsk.net> > --- > src/mesa/drivers/dri/i965/intel_blit.c | 295 > ++++++++++++++++++++++----- > src/mesa/drivers/dri/i965/intel_blit.h | 2 + > src/mesa/drivers/dri/i965/intel_copy_image.c | 2 + > src/mesa/drivers/dri/i965/intel_reg.h | 16 ++ > 4 files changed, 268 insertions(+), 47 deletions(-) > > diff --git a/src/mesa/drivers/dri/i965/intel_blit.c > b/src/mesa/drivers/dri/i965/intel_blit.c > index 5afc771..800ed7e 100644 > --- a/src/mesa/drivers/dri/i965/intel_blit.c > +++ b/src/mesa/drivers/dri/i965/intel_blit.c > @@ -27,6 +27,7 @@ > > > #include "main/mtypes.h" > +#include "main/blit.h" > #include "main/context.h" > #include "main/enums.h" > #include "main/colormac.h" > @@ -43,6 +44,23 @@ > > #define FILE_DEBUG_FLAG DEBUG_BLIT > > +#define SET_TILING_XY_FAST_COPY_BLT(tiling, tr_mode, type) \ > +({ \ > + switch (tiling) { \ > + case I915_TILING_X: \ > + CMD |= type ## _TILED_X; \ > + break; \ > + case I915_TILING_Y: \ > + if (tr_mode == INTEL_MIPTREE_TRMODE_YS) \ > + CMD |= type ## _TILED_64K; \ > + else \ > + CMD |= type ## _TILED_Y; \ > + break; \ > + default: \ > + unreachable("not reached"); \ > + } \ > +}) > + > static void > intel_miptree_set_alpha_to_one(struct brw_context *brw, > struct intel_mipmap_tree *mt, > @@ -75,6 +93,10 @@ static uint32_t > br13_for_cpp(int cpp) > { > switch (cpp) { > + case 16: > + return BR13_32323232; > + case 8: > + return BR13_16161616; > case 4: > return BR13_8888; > break; > @@ -89,6 +111,66 @@ br13_for_cpp(int cpp) > } > } > > +static uint32_t > +get_tr_horizontal_align(uint32_t tr_mode, uint32_t cpp, bool is_src) { > + /* Alignment tables for YF/YS tiled surfaces. */ > + const uint32_t align_2d_yf[] = {64, 64, 32, 32, 16}; > + const uint32_t align_2d_ys[] = {256, 256, 128, 128, 64}; > + const uint32_t bpp = cpp * 8; > + const uint32_t shift = is_src ? 17 : 10; > + uint32_t align; > + int i = 0; > + > + if (tr_mode == INTEL_MIPTREE_TRMODE_NONE) > + return 0; > + > + /* Compute array index. */ > + assert (bpp >= 8 && bpp <= 128 && is_power_of_two(bpp)); > + i = ffs(bpp / 8) - 1; > + > + align = tr_mode == INTEL_MIPTREE_TRMODE_YF ? > + align_2d_yf[i] : > + align_2d_ys[i]; > + > + assert(is_power_of_two(align)); > + > + /* XY_FAST_COPY_BLT doesn't support horizontal alignment of 16. */ > + if (align == 16) > + align = 32; > + > + return (ffs(align) - 6) << shift; > +} > + > +static uint32_t > +get_tr_vertical_align(uint32_t tr_mode, uint32_t cpp, bool is_src) { > + /* Vertical alignment tables for YF/YS tiled surfaces. */ > + const unsigned align_2d_yf[] = {64, 32, 32, 16, 16}; > + const unsigned align_2d_ys[] = {256, 128, 128, 64, 64}; > + const uint32_t bpp = cpp * 8; > + const uint32_t shift = is_src ? 15 : 8; > + uint32_t align; > + int i = 0; > + > + if (tr_mode == INTEL_MIPTREE_TRMODE_NONE) > + return 0; > + > + /* Compute array index. */ > + assert (bpp >= 8 && bpp <= 128 && is_power_of_two(bpp)); > + i = ffs(bpp / 8) - 1; > + > + align = tr_mode == INTEL_MIPTREE_TRMODE_YF ? > + align_2d_yf[i] : > + align_2d_ys[i]; > + > + assert(is_power_of_two(align)); > + > + /* XY_FAST_COPY_BLT doesn't support vertical alignments of 16 and 32. */ > + if (align == 16 || align == 32) > + align = 64; > + > + return (ffs(align) - 7) << shift; > +} > + > /** > * Emits the packet for switching the blitter from X to Y tiled or back. > * > @@ -281,9 +363,11 @@ intel_miptree_blit(struct brw_context *brw, > src_pitch, > src_mt->bo, src_mt->offset, > src_mt->tiling, > + src_mt->tr_mode, > dst_mt->pitch, > dst_mt->bo, dst_mt->offset, > dst_mt->tiling, > + dst_mt->tr_mode, > src_x, src_y, > dst_x, dst_y, > width, height, > @@ -316,6 +400,64 @@ alignment_valid(struct brw_context *brw, unsigned > offset, uint32_t tiling) > return true; > } > > +static bool > +can_fast_copy_blit(struct brw_context *brw, > + int16_t src_x, int16_t src_y, > + uintptr_t src_offset, uint32_t src_pitch,\ > + uint32_t src_tiling, uint32_t src_tr_mode, > + int16_t dst_x, int16_t dst_y, > + uintptr_t dst_offset, uint32_t dst_pitch, > + uint32_t dst_tiling, uint32_t dst_tr_mode, > + int16_t w, int16_t h, uint32_t cpp) > +{ > + const bool dst_tiling_none = dst_tiling == I915_TILING_NONE; > + const bool src_tiling_none = src_tiling == I915_TILING_NONE; > + > + if (brw->gen < 9) > + return false; > + > + if (_mesa_regions_overlap(src_x, src_y, src_x + w, src_y + h, > + dst_x, dst_y, dst_x + w, dst_y + h)) Changed the condition to: if (src_buffer->handle == dst_buffer->handle && _mesa_regions_overlap(src_x, src_y, src_x + w, src_y + h, dst_x, dst_y, dst_x + w, dst_y + h))
See my review branch for the updated patch. > + return false; > + > + /* Enable fast copy blit only if the surfaces are Yf/Ys tiled. > + * FIXME: Based on performance data, remove this condition later to > + * enable for all types of surfaces. > + */ > + if (src_tr_mode == INTEL_MIPTREE_TRMODE_NONE && > + dst_tr_mode == INTEL_MIPTREE_TRMODE_NONE) > + return false; > + > + /* For all surface types buffers must be cacheline-aligned. */ > + if ((dst_offset | src_offset) & 63) > + return false; > + > + /* Color depth greater than 128 bits not supported. */ > + if (cpp > 16) > + return false; > + > + /* For Fast Copy Blits the pitch cannot be a negative number. So, bit 15 > + * of the destination pitch must be zero. > + */ > + if ((src_pitch >> 15 & 1) != 0 || (dst_pitch >> 15 & 1) != 0) > + return false; > + > + /* For Linear surfaces, the pitch has to be an OWord (16byte) multiple. */ > + if ((src_tiling_none && src_pitch % 16 != 0) || > + (dst_tiling_none && dst_pitch % 16 != 0)) > + return false; > + > + /* For Tiled surfaces, the pitch has to be a multiple of the Tile width > + * (X direction width of the Tile). This means the pitch value will > + * always be Cache Line aligned (64byte multiple). > + */ > + if ((!dst_tiling_none && dst_pitch % 64 != 0) || > + (!src_tiling_none && src_pitch % 64 != 0)) > + return false; > + > + return true; > +} > + > /* Copy BitBlt > */ > bool > @@ -325,10 +467,12 @@ intelEmitCopyBlit(struct brw_context *brw, > drm_intel_bo *src_buffer, > GLuint src_offset, > uint32_t src_tiling, > + uint32_t src_tr_mode, > GLshort dst_pitch, > drm_intel_bo *dst_buffer, > GLuint dst_offset, > uint32_t dst_tiling, > + uint32_t dst_tr_mode, > GLshort src_x, GLshort src_y, > GLshort dst_x, GLshort dst_y, > GLshort w, GLshort h, > @@ -340,11 +484,7 @@ intelEmitCopyBlit(struct brw_context *brw, > drm_intel_bo *aper_array[3]; > bool dst_y_tiled = dst_tiling == I915_TILING_Y; > bool src_y_tiled = src_tiling == I915_TILING_Y; > - > - if (!alignment_valid(brw, dst_offset, dst_tiling)) > - return false; > - if (!alignment_valid(brw, src_offset, src_tiling)) > - return false; > + bool use_fast_copy_blit = false; > > if ((dst_y_tiled || src_y_tiled) && brw->gen < 6) > return false; > @@ -376,52 +516,109 @@ intelEmitCopyBlit(struct brw_context *brw, > src_buffer, src_pitch, src_offset, src_x, src_y, > dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h); > > - /* Blit pitch must be dword-aligned. Otherwise, the hardware appears to > drop > - * the low bits. Offsets must be naturally aligned. > - */ > - if (src_pitch % 4 != 0 || src_offset % cpp != 0 || > - dst_pitch % 4 != 0 || dst_offset % cpp != 0) > - return false; > - > - /* For big formats (such as floating point), do the copy using 16 or 32bpp > - * and multiply the coordinates. > - */ > - if (cpp > 4) { > - if (cpp % 4 == 2) { > - dst_x *= cpp / 2; > - dst_x2 *= cpp / 2; > - src_x *= cpp / 2; > - cpp = 2; > - } else { > - assert(cpp % 4 == 0); > - dst_x *= cpp / 4; > - dst_x2 *= cpp / 4; > - src_x *= cpp / 4; > - cpp = 4; > + use_fast_copy_blit = can_fast_copy_blit(brw, > + src_x, src_y, > + src_offset, src_pitch, > + src_tiling, src_tr_mode, > + dst_x, dst_y, > + dst_offset, dst_pitch, > + dst_tiling, dst_tr_mode, > + w, h, cpp); > + assert(use_fast_copy_blit || > + (src_tr_mode == INTEL_MIPTREE_TRMODE_NONE && > + dst_tr_mode == INTEL_MIPTREE_TRMODE_NONE)); > + > + if (use_fast_copy_blit) { > + /* When two sequential fast copy blits have different source surfaces, > + * but their destinations refer to the same destination surfaces and > + * therefore destinations overlap it is imperative that a flush be > + * inserted between the two blits. > + * > + * FIXME: Figure out a way to avoid flushing when not required. > + */ > + intel_batchbuffer_emit_mi_flush(brw); > + > + assert(cpp <= 16); > + BR13 = br13_for_cpp(cpp); > + > + if (src_tr_mode == INTEL_MIPTREE_TRMODE_YF) > + BR13 |= XY_FAST_SRC_TRMODE_YF; > + > + if (dst_tr_mode == INTEL_MIPTREE_TRMODE_YF) > + BR13 |= XY_FAST_DST_TRMODE_YF; > + > + CMD = XY_FAST_COPY_BLT_CMD; > + > + if (dst_tiling != I915_TILING_NONE) { > + SET_TILING_XY_FAST_COPY_BLT(dst_tiling, dst_tr_mode, XY_FAST_DST); > + /* Pitch value should be specified as a number of Dwords. */ > + dst_pitch /= 4; > + } > + if (src_tiling != I915_TILING_NONE) { > + SET_TILING_XY_FAST_COPY_BLT(src_tiling, src_tr_mode, XY_FAST_SRC); > + /* Pitch value should be specified as a number of Dwords. */ > + src_pitch /= 4; > } > - } > > - BR13 = br13_for_cpp(cpp) | translate_raster_op(logic_op) << 16; > + CMD |= get_tr_horizontal_align(src_tr_mode, cpp, true /* is_src */); > + CMD |= get_tr_vertical_align(src_tr_mode, cpp, true /* is_src */); > > - switch (cpp) { > - case 1: > - case 2: > - CMD = XY_SRC_COPY_BLT_CMD; > - break; > - case 4: > - CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; > - break; > - default: > - return false; > - } > + CMD |= get_tr_horizontal_align(dst_tr_mode, cpp, false /* is_src */); > + CMD |= get_tr_vertical_align(dst_tr_mode, cpp, false /* is_src */); > > - if (dst_tiling != I915_TILING_NONE) { > - CMD |= XY_DST_TILED; > - dst_pitch /= 4; > - } > - if (src_tiling != I915_TILING_NONE) { > - CMD |= XY_SRC_TILED; > - src_pitch /= 4; > + } else { > + /* For big formats (such as floating point), do the copy using 16 or > + * 32bpp and multiply the coordinates. > + */ > + if (cpp > 4) { > + if (cpp % 4 == 2) { > + dst_x *= cpp / 2; > + dst_x2 *= cpp / 2; > + src_x *= cpp / 2; > + cpp = 2; > + } else { > + assert(cpp % 4 == 0); > + dst_x *= cpp / 4; > + dst_x2 *= cpp / 4; > + src_x *= cpp / 4; > + cpp = 4; > + } > + } > + > + if (!alignment_valid(brw, dst_offset, dst_tiling)) > + return false; > + if (!alignment_valid(brw, src_offset, src_tiling)) > + return false; > + > + /* Blit pitch must be dword-aligned. Otherwise, the hardware appears > to drop > + * the low bits. Offsets must be naturally aligned. > + */ > + if (src_pitch % 4 != 0 || src_offset % cpp != 0 || > + dst_pitch % 4 != 0 || dst_offset % cpp != 0) > + return false; > + > + assert(cpp <= 4); > + BR13 = br13_for_cpp(cpp) | translate_raster_op(logic_op) << 16; > + switch (cpp) { > + case 1: > + case 2: > + CMD = XY_SRC_COPY_BLT_CMD; > + break; > + case 4: > + CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; > + break; > + default: > + return false; > + } > + > + if (dst_tiling != I915_TILING_NONE) { > + CMD |= XY_DST_TILED; > + dst_pitch /= 4; > + } > + if (src_tiling != I915_TILING_NONE) { > + CMD |= XY_SRC_TILED; > + src_pitch /= 4; > + } > } > > if (dst_y2 <= dst_y || dst_x2 <= dst_x) { > @@ -579,7 +776,9 @@ intel_emit_linear_blit(struct brw_context *brw, > dst_x = dst_offset % 64; > ok = intelEmitCopyBlit(brw, 1, > pitch, src_bo, src_offset - src_x, I915_TILING_NONE, > + INTEL_MIPTREE_TRMODE_NONE, > pitch, dst_bo, dst_offset - dst_x, I915_TILING_NONE, > + INTEL_MIPTREE_TRMODE_NONE, > src_x, 0, /* src x/y */ > dst_x, 0, /* dst x/y */ > pitch, height, /* w, h */ > @@ -598,7 +797,9 @@ intel_emit_linear_blit(struct brw_context *brw, > if (size != 0) { > ok = intelEmitCopyBlit(brw, 1, > pitch, src_bo, src_offset - src_x, > I915_TILING_NONE, > + INTEL_MIPTREE_TRMODE_NONE, > pitch, dst_bo, dst_offset - dst_x, > I915_TILING_NONE, > + INTEL_MIPTREE_TRMODE_NONE, > src_x, 0, /* src x/y */ > dst_x, 0, /* dst x/y */ > size, 1, /* w, h */ > diff --git a/src/mesa/drivers/dri/i965/intel_blit.h > b/src/mesa/drivers/dri/i965/intel_blit.h > index 2287c37..823488b 100644 > --- a/src/mesa/drivers/dri/i965/intel_blit.h > +++ b/src/mesa/drivers/dri/i965/intel_blit.h > @@ -37,10 +37,12 @@ intelEmitCopyBlit(struct brw_context *brw, > drm_intel_bo *src_buffer, > GLuint src_offset, > uint32_t src_tiling, > + uint32_t src_tr_mode, > GLshort dst_pitch, > drm_intel_bo *dst_buffer, > GLuint dst_offset, > uint32_t dst_tiling, > + uint32_t dst_tr_mode, > GLshort srcx, GLshort srcy, > GLshort dstx, GLshort dsty, > GLshort w, GLshort h, > diff --git a/src/mesa/drivers/dri/i965/intel_copy_image.c > b/src/mesa/drivers/dri/i965/intel_copy_image.c > index f4c7eff..3706704 100644 > --- a/src/mesa/drivers/dri/i965/intel_copy_image.c > +++ b/src/mesa/drivers/dri/i965/intel_copy_image.c > @@ -126,9 +126,11 @@ copy_image_with_blitter(struct brw_context *brw, > src_mt->pitch, > src_mt->bo, src_mt->offset, > src_mt->tiling, > + src_mt->tr_mode, > dst_mt->pitch, > dst_mt->bo, dst_mt->offset, > dst_mt->tiling, > + dst_mt->tr_mode, > src_x, src_y, > dst_x, dst_y, > src_width, src_height, > diff --git a/src/mesa/drivers/dri/i965/intel_reg.h > b/src/mesa/drivers/dri/i965/intel_reg.h > index bd14e18..4223e11 100644 > --- a/src/mesa/drivers/dri/i965/intel_reg.h > +++ b/src/mesa/drivers/dri/i965/intel_reg.h > @@ -102,6 +102,8 @@ > > #define XY_SRC_COPY_BLT_CMD (CMD_2D | (0x53 << 22)) > > +#define XY_FAST_COPY_BLT_CMD (CMD_2D | (0x42 << 22)) > + > #define XY_TEXT_IMMEDIATE_BLIT_CMD (CMD_2D | (0x31 << 22)) > # define XY_TEXT_BYTE_PACKED (1 << 16) > > @@ -111,10 +113,24 @@ > #define XY_SRC_TILED (1 << 15) > #define XY_DST_TILED (1 << 11) > > +/* BR00 */ > +#define XY_FAST_SRC_TILED_64K (3 << 20) > +#define XY_FAST_SRC_TILED_Y (2 << 20) > +#define XY_FAST_SRC_TILED_X (1 << 20) > + > +#define XY_FAST_DST_TILED_64K (3 << 13) > +#define XY_FAST_DST_TILED_Y (2 << 13) > +#define XY_FAST_DST_TILED_X (1 << 13) > + > /* BR13 */ > #define BR13_8 (0x0 << 24) > #define BR13_565 (0x1 << 24) > #define BR13_8888 (0x3 << 24) > +#define BR13_16161616 (0x4 << 24) > +#define BR13_32323232 (0x5 << 24) > + > +#define XY_FAST_SRC_TRMODE_YF (1 << 31) > +#define XY_FAST_DST_TRMODE_YF (1 << 30) > > /* Pipeline Statistics Counter Registers */ > #define IA_VERTICES_COUNT 0x2310 > -- > 1.9.3 > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev