[Mesa-dev] [PATCH 19/23] i965/gen9: Add XY_FAST_COPY_BLT support to intelEmitCopyBlit()
Anuj Phogat
anuj.phogat at gmail.com
Mon Mar 30 14:04:50 PDT 2015
Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
---
src/mesa/drivers/dri/i965/intel_blit.c | 293 +++++++++++++++++++++++----
src/mesa/drivers/dri/i965/intel_blit.h | 3 +
src/mesa/drivers/dri/i965/intel_copy_image.c | 3 +
src/mesa/drivers/dri/i965/intel_reg.h | 33 +++
4 files changed, 292 insertions(+), 40 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/intel_blit.c b/src/mesa/drivers/dri/i965/intel_blit.c
index 9500bd7..bdf85ae 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_YS: \
+ CMD |= type ## _TILED_64K; \
+ case I915_TILING_Y: \
+ case I915_TILING_YF: \
+ 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,12 @@ static uint32_t
br13_for_cpp(int cpp)
{
switch (cpp) {
+ case 16:
+ return BR13_32323232;
+ break;
+ case 8:
+ return BR13_16161616;
+ break;
case 4:
return BR13_8888;
break;
@@ -89,6 +112,134 @@ 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 && (bpp & (bpp - 1)) == 0);
+ while (bpp >> (i + 4))
+ i++;
+
+ 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_SRC_H_ALIGN_512 : XY_DST_H_ALIGN_512;
+ case 256:
+ return is_src ? XY_SRC_H_ALIGN_256 : XY_DST_H_ALIGN_256;
+ case 128:
+ return is_src ? XY_SRC_H_ALIGN_128 : XY_DST_H_ALIGN_128;
+ case 64:
+ return is_src ? XY_SRC_H_ALIGN_64 : XY_DST_H_ALIGN_64;
+ case 32:
+ return is_src ? XY_SRC_H_ALIGN_32 : XY_DST_H_ALIGN_32;
+ case 16:
+ /* XY_FAST_COPY_BLT doesn't support horizontal alignment of 16. */
+ return is_src ? XY_SRC_H_ALIGN_32 : XY_DST_H_ALIGN_32;
+ default:
+ unreachable("not reached");
+ }
+}
+
+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 && (bpp & (bpp - 1)) == 0);
+ while (bpp >> (i + 4))
+ i++;
+
+ 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_SRC_V_ALIGN_256 : XY_DST_V_ALIGN_256;
+ case 128:
+ return is_src ? XY_SRC_V_ALIGN_128 : XY_DST_V_ALIGN_128;
+ case 64:
+ return is_src ? XY_SRC_V_ALIGN_64 : XY_DST_V_ALIGN_64;
+ case 32:
+ case 16:
+ /* XY_FAST_COPY_BLT doesn't support vertical alignments of 16 and 32. */
+ return is_src ? XY_SRC_V_ALIGN_64 : XY_DST_V_ALIGN_64;
+ default:
+ unreachable("not reached");
+ }
+}
+
+static bool
+fast_copy_blit_error_check(uintptr_t src_addr, uint32_t src_pitch,
+ uint32_t src_tiling, uintptr_t dst_addr,
+ uint32_t dst_pitch, uint32_t dst_tiling,
+ uint32_t cpp)
+{
+ const bool dst_tiling_none = dst_tiling == I915_TILING_NONE;
+ const bool src_tiling_none = src_tiling == I915_TILING_NONE;
+
+ /* When destination tiling is enabled, this address is 64Byte aligned. */
+ if (!dst_tiling_none) {
+ if (dst_addr & 63)
+ return false;
+ }
+
+ /* When source tiling is enabled, this address should be 4 KB aligned. */
+ if (!src_tiling_none) {
+ if (src_addr & 4095)
+ return false;
+ }
+
+ /* When either source or destination tiling is enabled, this address is
+ * 16-byte aligned.
+ */
+ if (!src_tiling_none || !dst_tiling_none) {
+ if (src_addr & 15)
+ return false;
+ }
+
+ assert(cpp <= 16);
+ /* For Fast Copy Blits the pitch cannot be a negative number. */
+ assert(dst_pitch >= 0);
+
+ /* 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;
+}
+
/**
* Emits the packet for switching the blitter from X to Y tiled or back.
*
@@ -156,6 +307,7 @@ intel_miptree_blit(struct brw_context *brw,
uint32_t width, uint32_t height,
GLenum logicop)
{
+ bool overlap = false;
/* The blitter doesn't understand multisampling at all. */
if (src_mt->num_samples > 0 || dst_mt->num_samples > 0)
return false;
@@ -216,6 +368,12 @@ intel_miptree_blit(struct brw_context *brw,
intel_miptree_resolve_color(brw, src_mt);
intel_miptree_resolve_color(brw, dst_mt);
+ /* Check for an overlap for SKL+ platforms. */
+ if (brw->gen >= 9 &&
+ ((src_x < dst_x && (src_x + width) > dst_x) ||
+ (src_x > dst_x && (dst_x + width) > src_x)))
+ overlap = true;
+
if (src_flip)
src_y = minify(src_mt->physical_height0, src_level - src_mt->first_level) - src_y - height;
@@ -251,12 +409,15 @@ 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,
+ overlap,
logicop)) {
return false;
}
@@ -280,36 +441,40 @@ 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,
+ bool overlap,
GLenum logic_op)
{
GLuint CMD, BR13, pass = 0;
int dst_y2 = dst_y + h;
int dst_x2 = dst_x + w;
drm_intel_bo *aper_array[3];
- bool dst_y_tiled = dst_tiling == I915_TILING_Y;
- bool src_y_tiled = src_tiling == I915_TILING_Y;
+ bool dst_tr_mode_none = dst_tr_mode == INTEL_MIPTREE_TRMODE_NONE;
+ bool src_tr_mode_none = src_tr_mode == INTEL_MIPTREE_TRMODE_NONE;
+
+ bool dst_y_tiled = dst_tiling == I915_TILING_Y || !dst_tr_mode_none;
+ bool src_y_tiled = src_tiling == I915_TILING_Y || !src_tr_mode_none;
+ bool use_fast_copy_blit = brw->gen >= 9 && !overlap;
- if (dst_tiling != I915_TILING_NONE) {
- if (dst_offset & 4095)
- return false;
- }
- if (src_tiling != I915_TILING_NONE) {
- if (src_offset & 4095)
- return false;
- }
if ((dst_y_tiled || src_y_tiled) && brw->gen < 6)
return false;
assert(!dst_y_tiled || (dst_pitch % 128) == 0);
assert(!src_y_tiled || (src_pitch % 128) == 0);
+ if (use_fast_copy_blit == false &&
+ (src_tr_mode != INTEL_MIPTREE_TRMODE_NONE ||
+ dst_tr_mode != INTEL_MIPTREE_TRMODE_NONE))
+ return false;
+
/* do space check before going any further */
do {
aper_array[0] = brw->batch.bo;
@@ -334,13 +499,6 @@ 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.
*/
@@ -359,27 +517,76 @@ intelEmitCopyBlit(struct brw_context *brw,
}
}
- BR13 = br13_for_cpp(cpp) | translate_raster_op(logic_op) << 16;
+ if (use_fast_copy_blit &&
+ fast_copy_blit_error_check(src_offset, src_pitch, src_tiling,
+ dst_offset, dst_pitch, dst_tiling, cpp)) {
+ BR13 = br13_for_cpp(cpp);
- 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 (src_tr_mode == INTEL_MIPTREE_TRMODE_YF)
+ BR13 |= XY_SRC_TRMODE_YF;
- 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_tr_mode == INTEL_MIPTREE_TRMODE_YF)
+ BR13 |= XY_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_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_SRC);
+ /* Pitch value should be specified as a number of Dwords. */
+ src_pitch /= 4;
+ }
+
+ CMD |= get_tr_horizontal_align(src_tr_mode, cpp, true /* is_src */);
+ CMD |= get_tr_vertical_align(src_tr_mode, cpp, true /* is_src */);
+
+ CMD |= get_tr_horizontal_align(dst_tr_mode, cpp, false /* is_src */);
+ CMD |= get_tr_vertical_align(dst_tr_mode, cpp, false /* is_src */);
+
+ } else {
+ /* Source and destination base addresses should be 4 KB aligned. */
+ if (dst_tiling != I915_TILING_NONE) {
+ if (dst_offset & 4095)
+ return false;
+ }
+ if (src_tiling != I915_TILING_NONE) {
+ if (src_offset & 4095)
+ 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) {
@@ -533,11 +740,14 @@ intel_emit_linear_blit(struct brw_context *brw,
pitch = ROUND_DOWN_TO(MIN2(size, (1 << 15) - 1), 4);
height = (pitch == 0) ? 1 : size / pitch;
ok = intelEmitCopyBlit(brw, 1,
- pitch, src_bo, src_offset, I915_TILING_NONE,
- pitch, dst_bo, dst_offset, I915_TILING_NONE,
+ pitch, src_bo, src_offset,
+ I915_TILING_NONE, INTEL_MIPTREE_TRMODE_NONE,
+ pitch, dst_bo, dst_offset,
+ I915_TILING_NONE, INTEL_MIPTREE_TRMODE_NONE,
0, 0, /* src x/y */
0, 0, /* dst x/y */
pitch, height, /* w, h */
+ false, /* overlap */
GL_COPY);
if (!ok)
_mesa_problem(ctx, "Failed to linear blit %dx%d\n", pitch, height);
@@ -549,11 +759,14 @@ intel_emit_linear_blit(struct brw_context *brw,
pitch = ALIGN(size, 4);
if (size != 0) {
ok = intelEmitCopyBlit(brw, 1,
- pitch, src_bo, src_offset, I915_TILING_NONE,
- pitch, dst_bo, dst_offset, I915_TILING_NONE,
+ pitch, src_bo, src_offset,
+ I915_TILING_NONE, INTEL_MIPTREE_TRMODE_NONE,
+ pitch, dst_bo, dst_offset,
+ I915_TILING_NONE, INTEL_MIPTREE_TRMODE_NONE,
0, 0, /* src x/y */
0, 0, /* dst x/y */
size, 1, /* w, h */
+ false, /* overlap */
GL_COPY);
if (!ok)
_mesa_problem(ctx, "Failed to linear blit %dx%d\n", size, 1);
diff --git a/src/mesa/drivers/dri/i965/intel_blit.h b/src/mesa/drivers/dri/i965/intel_blit.h
index f563939..29c9ead 100644
--- a/src/mesa/drivers/dri/i965/intel_blit.h
+++ b/src/mesa/drivers/dri/i965/intel_blit.h
@@ -37,13 +37,16 @@ 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,
+ bool overlap,
GLenum logicop );
bool intel_miptree_blit(struct brw_context *brw,
diff --git a/src/mesa/drivers/dri/i965/intel_copy_image.c b/src/mesa/drivers/dri/i965/intel_copy_image.c
index f4c7eff..1e4a1e2 100644
--- a/src/mesa/drivers/dri/i965/intel_copy_image.c
+++ b/src/mesa/drivers/dri/i965/intel_copy_image.c
@@ -126,12 +126,15 @@ 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,
+ false /* overlap */,
GL_COPY);
}
diff --git a/src/mesa/drivers/dri/i965/intel_reg.h b/src/mesa/drivers/dri/i965/intel_reg.h
index e5730e2..0ccf4a5 100644
--- a/src/mesa/drivers/dri/i965/intel_reg.h
+++ b/src/mesa/drivers/dri/i965/intel_reg.h
@@ -87,6 +87,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)
@@ -95,11 +97,42 @@
#define XY_BLT_WRITE_RGB (1 << 20)
#define XY_SRC_TILED (1 << 15)
#define XY_DST_TILED (1 << 11)
+#define XY_SRC_TILED_X (1 << 20)
+#define XY_SRC_TILED_Y (2 << 20)
+#define XY_SRC_TILED_64K (3 << 20)
+#define XY_DST_TILED_X (1 << 13)
+#define XY_DST_TILED_Y (2 << 13)
+#define XY_DST_TILED_64K (3 << 13)
+
+#define XY_SRC_H_ALIGN_32 (0 << 17)
+#define XY_SRC_H_ALIGN_64 (1 << 17)
+#define XY_SRC_H_ALIGN_128 (2 << 17)
+#define XY_SRC_H_ALIGN_256 (3 << 17)
+#define XY_SRC_H_ALIGN_512 (4 << 17)
+
+#define XY_SRC_V_ALIGN_64 (0 << 15)
+#define XY_SRC_V_ALIGN_128 (1 << 15)
+#define XY_SRC_V_ALIGN_256 (2 << 15)
+
+#define XY_DST_H_ALIGN_32 (0 << 10)
+#define XY_DST_H_ALIGN_64 (1 << 10)
+#define XY_DST_H_ALIGN_128 (2 << 10)
+#define XY_DST_H_ALIGN_256 (3 << 10)
+#define XY_DST_H_ALIGN_512 (4 << 10)
+
+#define XY_DST_V_ALIGN_64 (0 << 8)
+#define XY_DST_V_ALIGN_128 (1 << 8)
+#define XY_DST_V_ALIGN_256 (2 << 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_SRC_TRMODE_YF (1 << 31)
+#define XY_DST_TRMODE_YF (1 << 30)
/* Pipeline Statistics Counter Registers */
#define IA_VERTICES_COUNT 0x2310
--
2.3.4
More information about the mesa-dev
mailing list