On Wed, Jun 3, 2015 at 3:25 PM, Ben Widawsky <b...@bwidawsk.net> wrote: > On Tue, Jun 02, 2015 at 04:04:07PM -0700, Anuj Phogat 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(). >> Use XY_FAST prefix for the macros. >> >> Signed-off-by: Anuj Phogat <anuj.pho...@gmail.com> >> Cc: Ben Widawsky <b...@bwidawsk.net> >> --- >> src/mesa/drivers/dri/i965/intel_blit.c | 306 >> +++++++++++++++++++++++---- >> 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 | 36 ++++ >> 4 files changed, 299 insertions(+), 47 deletions(-) >> >> diff --git a/src/mesa/drivers/dri/i965/intel_blit.c >> b/src/mesa/drivers/dri/i965/intel_blit.c >> index cd89f9d..8f0b48b 100644 >> --- a/src/mesa/drivers/dri/i965/intel_blit.c >> +++ b/src/mesa/drivers/dri/i965/intel_blit.c >> @@ -43,6 +43,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 +92,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; >> case 2: >> @@ -86,6 +107,81 @@ 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; >> + 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; >> + >> + if (tr_mode == INTEL_MIPTREE_TRMODE_YF) >> + align = align_2d_yf[i]; >> + else >> + align = align_2d_ys[i]; >> + >> + switch(align) { >> + case 512: >> + return is_src ? XY_FAST_SRC_H_ALIGN_512 : XY_FAST_DST_H_ALIGN_512; >> + case 256: >> + return is_src ? XY_FAST_SRC_H_ALIGN_256 : XY_FAST_DST_H_ALIGN_256; >> + case 128: >> + return is_src ? XY_FAST_SRC_H_ALIGN_128 : XY_FAST_DST_H_ALIGN_128; >> + case 64: >> + return is_src ? XY_FAST_SRC_H_ALIGN_64 : XY_FAST_DST_H_ALIGN_64; >> + case 32: >> + /* XY_FAST_COPY_BLT doesn't support horizontal alignment of 16. */ >> + case 16: >> + return is_src ? XY_FAST_SRC_H_ALIGN_32 : XY_FAST_DST_H_ALIGN_32; >> + default: >> + unreachable("not reached"); >> + } >> +} > > I'd make this smaller, but I think my brain works differently than most. I > don't > see anything wrong with this code though, so it's up to you. > I agree. It'll be nice to make it shorter.
> int shift = is_src ? 17 : 10 > > Then either use your table, or: > /* 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; >> + 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; >> + >> + if (tr_mode == INTEL_MIPTREE_TRMODE_YF) >> + align = align_2d_yf[i]; >> + else >> + align = align_2d_ys[i]; >> + >> + switch(align) { >> + case 256: >> + return is_src ? XY_FAST_SRC_V_ALIGN_256 : XY_FAST_DST_V_ALIGN_256; >> + case 128: >> + return is_src ? XY_FAST_SRC_V_ALIGN_128 : XY_FAST_DST_V_ALIGN_128; >> + case 64: >> + /* XY_FAST_COPY_BLT doesn't support vertical alignments of 16 and 32. */ >> + case 32: >> + case 16: >> + return is_src ? XY_FAST_SRC_V_ALIGN_64 : XY_FAST_DST_V_ALIGN_64; >> + default: >> + unreachable("not reached"); >> + } >> +} >> + >> /** >> * Emits the packet for switching the blitter from X to Y tiled or back. >> * >> @@ -248,9 +344,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, >> @@ -282,6 +380,63 @@ 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, uintptr_t src_offset, uint32_t src_pitch, >> + uint32_t src_tiling, uint32_t src_tr_mode, >> + int16_t dst_x, uintptr_t dst_offset, uint32_t dst_pitch, >> + uint32_t dst_tiling, uint32_t dst_tr_mode, >> + int16_t w, 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; >> + >> + /* Check for an overlap. */ >> + if ((src_x < dst_x && (src_x + w) > dst_x) || >> + (src_x > dst_x && (dst_x + w) > src_x)) >> + return false; > > Can you remind me why Y isn't a factor in determining overlap? > This condition is incomplete :(. I'll fix this in V4 by using existing function regions_overlap() to do the check here. >> + >> + /* 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 >> @@ -291,10 +446,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, >> @@ -306,11 +463,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; >> @@ -342,52 +495,107 @@ 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_offset, src_pitch, >> + src_tiling, src_tr_mode, >> + dst_x, dst_offset, dst_pitch, >> + dst_tiling, dst_tr_mode, >> + w, 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) { >> @@ -545,7 +753,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 */ >> @@ -564,7 +774,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 f563939..4f4bbc5 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..c8ec56b 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,44 @@ >> #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) >> + >> +#define XY_FAST_SRC_H_ALIGN_512 (4 << 17) >> +#define XY_FAST_SRC_H_ALIGN_256 (3 << 17) >> +#define XY_FAST_SRC_H_ALIGN_128 (2 << 17) >> +#define XY_FAST_SRC_H_ALIGN_64 (1 << 17) >> +#define XY_FAST_SRC_H_ALIGN_32 (0 << 17) >> + >> +#define XY_FAST_SRC_V_ALIGN_256 (2 << 15) >> +#define XY_FAST_SRC_V_ALIGN_128 (1 << 15) >> +#define XY_FAST_SRC_V_ALIGN_64 (0 << 15) >> + >> +#define XY_FAST_DST_H_ALIGN_512 (4 << 10) >> +#define XY_FAST_DST_H_ALIGN_256 (3 << 10) >> +#define XY_FAST_DST_H_ALIGN_128 (2 << 10) >> +#define XY_FAST_DST_H_ALIGN_64 (1 << 10) >> +#define XY_FAST_DST_H_ALIGN_32 (0 << 10) >> + >> +#define XY_FAST_DST_V_ALIGN_256 (2 << 8) >> +#define XY_FAST_DST_V_ALIGN_128 (1 << 8) >> +#define XY_FAST_DST_V_ALIGN_64 (0 << 8) >> + >> /* 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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev