mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 02:28:10 +02:00
i965/gen9: Add XY_FAST_COPY_BLT support to intelEmitCopyBlit()
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.
Add check for src_buffer == dst_buffer.
Simplify horizontal and vertical alignment computations.
Signed-off-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
This commit is contained in:
parent
ca21c9ab28
commit
412c8c8e7e
4 changed files with 286 additions and 62 deletions
|
|
@ -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;
|
||||
case 2:
|
||||
|
|
@ -86,6 +108,64 @@ 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 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] :
|
||||
4 * align_2d_yf[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 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] :
|
||||
4 * align_2d_yf[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.
|
||||
*
|
||||
|
|
@ -278,9 +358,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,
|
||||
|
|
@ -313,6 +395,67 @@ alignment_valid(struct brw_context *brw, unsigned offset, uint32_t tiling)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
can_fast_copy_blit(struct brw_context *brw,
|
||||
drm_intel_bo *src_buffer,
|
||||
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,
|
||||
drm_intel_bo *dst_buffer,
|
||||
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 (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))
|
||||
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
|
||||
|
|
@ -322,10 +465,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,
|
||||
|
|
@ -337,18 +482,11 @@ 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;
|
||||
|
||||
assert(!dst_y_tiled || (dst_pitch % 128) == 0);
|
||||
assert(!src_y_tiled || (src_pitch % 128) == 0);
|
||||
|
||||
/* do space check before going any further */
|
||||
do {
|
||||
aper_array[0] = brw->batch.bo;
|
||||
|
|
@ -373,52 +511,114 @@ 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;
|
||||
use_fast_copy_blit = can_fast_copy_blit(brw,
|
||||
src_buffer,
|
||||
src_x, src_y,
|
||||
src_offset, src_pitch,
|
||||
src_tiling, src_tr_mode,
|
||||
dst_buffer,
|
||||
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));
|
||||
|
||||
/* 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 (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.
|
||||
*/
|
||||
brw_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 {
|
||||
assert(!dst_y_tiled || (dst_pitch % 128) == 0);
|
||||
assert(!src_y_tiled || (src_pitch % 128) == 0);
|
||||
|
||||
/* 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) {
|
||||
|
|
@ -576,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 */
|
||||
|
|
@ -595,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 */
|
||||
|
|
|
|||
|
|
@ -32,19 +32,21 @@
|
|||
|
||||
bool
|
||||
intelEmitCopyBlit(struct brw_context *brw,
|
||||
GLuint cpp,
|
||||
GLshort src_pitch,
|
||||
drm_intel_bo *src_buffer,
|
||||
GLuint src_offset,
|
||||
uint32_t src_tiling,
|
||||
GLshort dst_pitch,
|
||||
drm_intel_bo *dst_buffer,
|
||||
GLuint dst_offset,
|
||||
uint32_t dst_tiling,
|
||||
GLshort srcx, GLshort srcy,
|
||||
GLshort dstx, GLshort dsty,
|
||||
GLshort w, GLshort h,
|
||||
GLenum logicop );
|
||||
GLuint cpp,
|
||||
GLshort src_pitch,
|
||||
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,
|
||||
GLenum logicop);
|
||||
|
||||
bool intel_miptree_blit_compatible_formats(mesa_format src, mesa_format dst);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue