All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations
@ 2019-12-01 19:09 Zbigniew Kempczyński
  2019-12-01 19:09 ` [igt-dev] [PATCH i-g-t v2 2/2] tests/gem_render_copy: Add software tiling / detiling support Zbigniew Kempczyński
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Zbigniew Kempczyński @ 2019-12-01 19:09 UTC (permalink / raw)
  To: igt-dev

Different GENs supports different tile surfaces. Older GENs
have HW fences to allow X / Y surface tiling / detiling.
Newer GENs have to tile / detile such surface in software.

To make test developer life easier this code adds buffer
operations (short bufops) to use appropriate functions allowing
copying linear buffer to BO and from BO to linear buffer
regardless GPU generation and tiling within BO. For GENs having
fences support preference is to use them if they are available
(X / Y tiling is probed on bufops initalization).

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Katarzyna Dec <katarzyna.dec@intel.com>
---
 lib/Makefile.sources |   2 +
 lib/intel_bufops.c   | 689 +++++++++++++++++++++++++++++++++++++++++++
 lib/intel_bufops.h   |  24 ++
 lib/meson.build      |   1 +
 4 files changed, 716 insertions(+)
 create mode 100644 lib/intel_bufops.c
 create mode 100644 lib/intel_bufops.h

diff --git a/lib/Makefile.sources b/lib/Makefile.sources
index 9d1a4e06..b808f294 100644
--- a/lib/Makefile.sources
+++ b/lib/Makefile.sources
@@ -65,6 +65,8 @@ lib_source_list =	 	\
 	intel_aub.h		\
 	intel_batchbuffer.c	\
 	intel_batchbuffer.h	\
+	intel_bufops.c		\
+	intel_bufops.h		\
 	intel_chipset.c		\
 	intel_chipset.h		\
 	intel_device_info.c	\
diff --git a/lib/intel_bufops.c b/lib/intel_bufops.c
new file mode 100644
index 00000000..fdb8bdc7
--- /dev/null
+++ b/lib/intel_bufops.c
@@ -0,0 +1,689 @@
+#include <sys/ioctl.h>
+#include "igt.h"
+#include "igt_x86.h"
+#include "intel_bufops.h"
+
+#define TILE_NONE   (1 << I915_TILING_NONE)
+#define TILE_X      (1 << I915_TILING_X)
+#define TILE_Y      (1 << I915_TILING_Y)
+#define TILE_Yf     (1 << I915_TILING_Yf)
+#define TILE_Ys     (1 << I915_TILING_Ys)
+
+typedef void (*bo_copy)(int, struct igt_buf *, uint32_t *);
+
+struct buf_ops {
+	int fd;
+	drm_intel_bufmgr *bufmgr;
+	int gen_start;
+	int gen_end;
+	int intel_gen;
+	uint32_t supported_tiles;
+	uint32_t hw_tiles;
+	bo_copy linear_to;
+	bo_copy linear_to_x;
+	bo_copy linear_to_y;
+	bo_copy linear_to_yf;
+	bo_copy linear_to_ys;
+	bo_copy to_linear;
+	bo_copy x_to_linear;
+	bo_copy y_to_linear;
+	bo_copy yf_to_linear;
+	bo_copy ys_to_linear;
+};
+
+static void *x_ptr(void *ptr,
+		   unsigned int x, unsigned int y,
+		   unsigned int stride, unsigned int cpp)
+{
+	const int tile_width = 512;
+	const int tile_height = 8;
+	const int tile_size = tile_width * tile_height;
+	int tile_x, tile_y;
+	int offset_x, offset_y, pos;
+
+	x *= cpp;
+	tile_x = x / tile_width;
+	tile_y = y / tile_height;
+	offset_x = (tile_x * tile_size);
+	offset_y = (tile_y * stride * tile_height);
+
+	pos = offset_y + offset_x +
+			(y % tile_height * tile_width) + (x % tile_width);
+
+	return ptr + pos;
+}
+
+static void *y_ptr(void *ptr,
+		   unsigned int x, unsigned int y,
+		   unsigned int stride, unsigned int cpp)
+{
+	const int tile_width = 128;
+	const int tile_height = 32;
+	const int owords = 16;
+	const int tile_size = tile_width * tile_height;
+	int tile_x, tile_y;
+	int offset_x, offset_y, pos;
+	int shift_x, shift_y;
+
+	x *= cpp;
+	tile_x = x / tile_width;
+	tile_y = y / tile_height;
+	offset_x = tile_x * tile_size;
+	offset_y = tile_y * stride * tile_height;
+	shift_x = x % owords + (x % tile_width) / owords * tile_width * cpp;
+	shift_y = y % tile_height * owords;
+
+	pos = offset_y + offset_x + shift_x + shift_y;
+
+	return ptr + pos;
+}
+
+static void *yf_ptr(void *ptr,
+		    unsigned int x, unsigned int y,
+		    unsigned int stride, unsigned int cpp)
+{
+	const int tile_size = 4 * 1024;
+	const int tile_width = 128;
+	int row_size = (stride / tile_width) * tile_size;
+
+	x *= cpp; /* convert to Byte offset */
+
+
+	/*
+	 * Within a 4k Yf tile, the byte swizzling pattern is
+	 * msb......lsb
+	 * xyxyxyyyxxxx
+	 * The tiles themselves are laid out in row major order.
+	 */
+	return ptr +
+			((x & 0xf) * 1) + /* 4x1 pixels(32bpp) = 16B */
+			((y & 0x3) * 16) + /* 4x4 pixels = 64B */
+			(((y & 0x4) >> 2) * 64) + /* 1x2 64B blocks */
+			(((x & 0x10) >> 4) * 128) + /* 2x2 64B blocks = 256B block */
+			(((y & 0x8) >> 3) * 256) + /* 2x1 256B blocks */
+			(((x & 0x20) >> 5) * 512) + /* 2x2 256B blocks */
+			(((y & 0x10) >> 4) * 1024) + /* 4x2 256 blocks */
+			(((x & 0x40) >> 6) * 2048) + /* 4x4 256B blocks = 4k tile */
+			(((x & ~0x7f) >> 7) * tile_size) + /* row of tiles */
+			(((y & ~0x1f) >> 5) * row_size);
+}
+
+typedef void *(*fn_ptr)(void *, unsigned int, unsigned int,
+			unsigned int, unsigned int);
+static fn_ptr __get_tile_fn_ptr(int tiling)
+{
+	fn_ptr fn = NULL;
+
+	switch (tiling) {
+	case I915_TILING_X:
+		fn = x_ptr;
+		break;
+	case I915_TILING_Y:
+		fn = y_ptr;
+		break;
+	case I915_TILING_Yf:
+		fn = yf_ptr;
+		break;
+	case I915_TILING_Ys:
+		/* To be implemented */
+		break;
+	}
+
+	igt_assert_f(fn, "Can't find tile function for tiling: %d\n", tiling);
+
+	return fn;
+}
+
+static void __copy_linear_to(int fd, struct igt_buf *buf,
+			     const uint32_t *linear, int tiling)
+{
+	int height = igt_buf_height(buf);
+	int width = igt_buf_width(buf);
+	fn_ptr fn = __get_tile_fn_ptr(tiling);
+	void *map;
+
+	gem_set_domain(fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
+			    buf->bo->size, PROT_READ | PROT_WRITE);
+
+	for (int y = 0; y < height; y++) {
+		for (int x = 0; x < width; x++) {
+			uint32_t *ptr = fn(map, x, y,
+					   buf->stride, buf->bpp / 8);
+
+			*ptr = linear[y * width + x];
+		}
+	}
+
+	munmap(map, buf->bo->size);
+}
+
+static void copy_linear_to_x(int fd, struct igt_buf *buf,
+			     uint32_t *linear)
+{
+	__copy_linear_to(fd, buf, linear, I915_TILING_X);
+}
+
+static void copy_linear_to_y(int fd, struct igt_buf *buf,
+			     uint32_t *linear)
+{
+	__copy_linear_to(fd, buf, linear, I915_TILING_Y);
+}
+
+static void copy_linear_to_yf(int fd, struct igt_buf *buf,
+			      uint32_t *linear)
+{
+	__copy_linear_to(fd, buf, linear, I915_TILING_Yf);
+}
+
+static void __copy_to_linear(int fd, struct igt_buf *buf,
+			     uint32_t *linear, int tiling)
+{
+	int height = igt_buf_height(buf);
+	int width = igt_buf_width(buf);
+	fn_ptr fn = __get_tile_fn_ptr(tiling);
+	void *map;
+
+	gem_set_domain(fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_CPU, 0);
+	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
+			    buf->bo->size, PROT_READ);
+
+	for (int y = 0; y < height; y++) {
+		for (int x = 0; x < width; x++) {
+			uint32_t *ptr = fn(map, x, y,
+					   buf->stride, buf->bpp / 8);
+
+			linear[y * width + x] = *ptr;
+		}
+	}
+
+	munmap(map, buf->bo->size);
+}
+
+static void copy_yf_to_linear(int fd, struct igt_buf *buf,
+			      uint32_t *linear)
+{
+	__copy_to_linear(fd, buf, linear, I915_TILING_Yf);
+}
+
+static void copy_x_to_linear(int fd, struct igt_buf *buf,
+			     uint32_t *linear)
+{
+	__copy_to_linear(fd, buf, linear, I915_TILING_X);
+}
+
+static void copy_y_to_linear(int fd, struct igt_buf *buf,
+			     uint32_t *linear)
+{
+	__copy_to_linear(fd, buf, linear, I915_TILING_Y);
+}
+
+static void copy_linear_to_gtt(int fd, struct igt_buf *buf,
+			       uint32_t *linear)
+{
+	void *map;
+
+	gem_set_domain(fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+
+	map = gem_mmap__gtt(fd, buf->bo->handle,
+			    buf->bo->size, PROT_READ | PROT_WRITE);
+
+	memcpy(map, linear, buf->bo->size);
+
+	munmap(map, buf->bo->size);
+}
+
+static void copy_gtt_to_linear(int fd, struct igt_buf *buf,
+			       uint32_t *linear)
+{
+	void *map;
+
+	gem_set_domain(fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_GTT, 0);
+
+	map = gem_mmap__gtt(fd, buf->bo->handle,
+			    buf->bo->size, PROT_READ);
+
+	igt_memcpy_from_wc(linear, map, buf->bo->size);
+
+	munmap(map, buf->bo->size);
+}
+
+static void copy_linear_to_wc(int fd, struct igt_buf *buf,
+			      uint32_t *linear)
+{
+	void *map;
+
+	gem_set_domain(fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+
+	map = gem_mmap__wc(fd, buf->bo->handle, 0,
+			   buf->bo->size, PROT_READ | PROT_WRITE);
+
+	memcpy(map, linear, buf->bo->size);
+
+	munmap(map, buf->bo->size);
+}
+
+static void copy_wc_to_linear(int fd, struct igt_buf *buf,
+			      uint32_t *linear)
+{
+	void *map;
+
+	gem_set_domain(fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_GTT, 0);
+
+	map = gem_mmap__wc(fd, buf->bo->handle, 0,
+			   buf->bo->size, PROT_READ);
+
+	igt_memcpy_from_wc(linear, map, buf->bo->size);
+
+	munmap(map, buf->bo->size);
+}
+
+static void copy_linear_to_cpu(int fd, struct igt_buf *buf,
+			       uint32_t *linear)
+{
+	void *map;
+
+	gem_set_domain(fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+
+	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
+			    buf->bo->size, PROT_READ | PROT_WRITE);
+
+	memcpy(map, linear, buf->bo->size);
+
+	munmap(map, buf->bo->size);
+}
+
+static void copy_cpu_to_linear(int fd, struct igt_buf *buf,
+			       uint32_t *linear)
+{
+	void *map;
+
+	gem_set_domain(fd, buf->bo->handle,
+		       I915_GEM_DOMAIN_CPU, 0);
+
+	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
+			    buf->bo->size, PROT_READ);
+
+	memcpy(linear, map, buf->bo->size);
+
+	munmap(map, buf->bo->size);
+}
+
+void copy_buf_to_linear(struct buf_ops *bops, struct igt_buf *buf,
+			uint32_t *linear)
+{
+	igt_assert(bops);
+
+	switch (buf->tiling) {
+	case I915_TILING_NONE:
+		igt_assert(bops->to_linear);
+		bops->to_linear(bops->fd, buf, linear);
+		break;
+	case I915_TILING_X:
+		igt_assert(bops->x_to_linear);
+		bops->x_to_linear(bops->fd, buf, linear);
+		break;
+	case I915_TILING_Y:
+		igt_assert(bops->y_to_linear);
+		bops->y_to_linear(bops->fd, buf, linear);
+		break;
+	case I915_TILING_Yf:
+		igt_assert(bops->yf_to_linear);
+		bops->yf_to_linear(bops->fd, buf, linear);
+		break;
+	case I915_TILING_Ys:
+		igt_assert(bops->ys_to_linear);
+		bops->ys_to_linear(bops->fd, buf, linear);
+		break;
+	}
+}
+
+void copy_linear_to_buf(struct buf_ops *bops, struct igt_buf *buf,
+			uint32_t *linear)
+{
+	igt_assert(bops);
+
+	switch (buf->tiling) {
+	case I915_TILING_NONE:
+		igt_assert(bops->linear_to);
+		bops->linear_to(bops->fd, buf, linear);
+		break;
+	case I915_TILING_X:
+		igt_assert(bops->linear_to_x);
+		bops->linear_to_x(bops->fd, buf, linear);
+		break;
+	case I915_TILING_Y:
+		igt_assert(bops->linear_to_y);
+		bops->linear_to_y(bops->fd, buf, linear);
+		break;
+	case I915_TILING_Yf:
+		igt_assert(bops->linear_to_yf);
+		bops->linear_to_yf(bops->fd, buf, linear);
+		break;
+	case I915_TILING_Ys:
+		igt_assert(bops->linear_to_ys);
+		bops->linear_to_ys(bops->fd, buf, linear);
+		break;
+	}
+}
+
+struct buf_ops buf_ops_arr[] = {
+	/* Generations 0 - 8 */
+{
+	.gen_start         = 0,
+	.gen_end           = 8,
+	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y,
+	.hw_tiles          = TILE_X | TILE_Y,
+	.linear_to         = copy_linear_to_cpu,
+	.linear_to_x       = copy_linear_to_gtt,
+	.linear_to_y       = copy_linear_to_gtt,
+	.to_linear         = copy_cpu_to_linear,
+	.x_to_linear       = copy_gtt_to_linear,
+	.y_to_linear       = copy_gtt_to_linear,
+},
+/* Generations 9 - 11 */
+{
+	.gen_start         = 9,
+	.gen_end           = 11,
+	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf,
+	.hw_tiles          = TILE_X | TILE_Y,
+	.linear_to         = copy_linear_to_cpu,
+	.linear_to_x       = copy_linear_to_gtt,
+	.linear_to_y       = copy_linear_to_gtt,
+	.linear_to_yf      = copy_linear_to_yf,
+	.to_linear         = copy_cpu_to_linear,
+	.x_to_linear       = copy_gtt_to_linear,
+	.y_to_linear       = copy_gtt_to_linear,
+	.yf_to_linear      = copy_yf_to_linear,
+},
+/* Generation 12 */
+{
+	.gen_start         = 12,
+	.gen_end           = 12,
+	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf | TILE_Ys,
+	.linear_to         = copy_linear_to_wc,
+	.linear_to_x       = copy_linear_to_x,
+	.linear_to_y       = copy_linear_to_y,
+	.linear_to_yf      = copy_linear_to_yf,
+	.linear_to_ys      = NULL,               /* to be implemented */
+	.to_linear         = copy_wc_to_linear,
+	.x_to_linear       = copy_x_to_linear,
+	.y_to_linear       = copy_y_to_linear,
+	.yf_to_linear      = copy_yf_to_linear,
+	.ys_to_linear      = NULL,               /* to be implemented */
+},
+};
+
+static int __gem_get_tiling(int fd, struct drm_i915_gem_get_tiling *arg)
+{
+	int err;
+
+	err = 0;
+	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, arg))
+		err = -errno;
+	errno = 0;
+
+	return err;
+}
+
+static bool __get_tiling(int fd, uint32_t handle, uint32_t *tiling,
+			 uint32_t *swizzle)
+{
+	struct drm_i915_gem_get_tiling get_tiling;
+
+	memset(&get_tiling, 0, sizeof(get_tiling));
+	get_tiling.handle = handle;
+
+	if (__gem_get_tiling(fd, &get_tiling) != 0)
+		return false;
+
+	*tiling = get_tiling.tiling_mode;
+	*swizzle = get_tiling.swizzle_mode;
+
+	return get_tiling.phys_swizzle_mode == get_tiling.swizzle_mode;
+}
+
+static bool probe_hw_tiling(int fd, uint32_t tiling)
+{
+	struct drm_i915_gem_set_tiling st;
+	uint64_t size = 1024 * 1024;
+	uint32_t handle, buf_tiling, buf_swizzle;
+	uint32_t stride;
+	int ret;
+	bool is_set;
+
+	if (tiling == I915_TILING_X)
+		stride = 512;
+	else if (tiling == I915_TILING_Y)
+		stride = 128;
+	else
+		return false;
+
+	handle = gem_create(fd, size);
+
+	/* Single shot, if no fences are available we fail immediately */
+	st.handle = handle;
+	st.tiling_mode = tiling;
+	st.stride = tiling ? stride : 0;
+	ret = ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &st);
+	if (ret)
+		goto end;
+
+	is_set = __get_tiling(fd, handle, &buf_tiling, &buf_swizzle);
+
+end:
+	gem_close(fd, handle);
+
+	return is_set;
+}
+
+struct buf_ops *buf_ops_get(int fd, drm_intel_bufmgr *bufmgr)
+{
+	struct buf_ops *bops = calloc(1, sizeof(*bops));
+	uint32_t devid;
+	int generation;
+
+	igt_assert(bufmgr);
+	igt_assert(bops);
+
+	devid = intel_get_drm_devid(fd);
+	generation = intel_gen(devid);
+
+	/* Predefined settings */
+	for (int i = 0; i < ARRAY_SIZE(buf_ops_arr); i++) {
+		if (generation >= buf_ops_arr[i].gen_start &&
+				generation <= buf_ops_arr[i].gen_end) {
+			memcpy(bops, &buf_ops_arr[i], sizeof(*bops));
+			bops->fd = fd;
+			bops->bufmgr = bufmgr;
+			bops->intel_gen = generation;
+			igt_debug("generation: %d, supported tiles: 0x%02x\n",
+				  generation, bops->supported_tiles);
+			break;
+		}
+	}
+
+	/* Let's probe X and Y hw tiling support */
+	if (bops->hw_tiles & TILE_X) {
+		bool supported = probe_hw_tiling(fd, I915_TILING_X);
+
+		igt_debug("X fence support: %s\n", supported ? "yes" : "no");
+		if (!supported) {
+			bops->hw_tiles &= ~TILE_X;
+			bops->linear_to_x = copy_linear_to_x;
+			bops->x_to_linear = copy_x_to_linear;
+		}
+	}
+
+	if (bops->hw_tiles & TILE_Y) {
+		bool supported = probe_hw_tiling(fd, I915_TILING_Y);
+
+		igt_debug("Y fence support: %s\n", supported ? "yes" : "no");
+		if (!supported) {
+			bops->hw_tiles &= ~TILE_Y;
+			bops->linear_to_y = copy_linear_to_y;
+			bops->y_to_linear = copy_y_to_linear;
+		}
+	}
+
+	igt_assert(bops->intel_gen);
+
+	return bops;
+}
+
+void buf_ops_switch_to_sofware_tiling(struct buf_ops *bops)
+{
+	igt_debug("Switch to software tiling/detiling of X/Y surfaces\n");
+
+	igt_assert(bops);
+
+	bops->hw_tiles = 0;
+	bops->linear_to_x = copy_linear_to_x;
+	bops->linear_to_y = copy_linear_to_y;
+	bops->x_to_linear = copy_x_to_linear;
+	bops->y_to_linear = copy_y_to_linear;
+}
+
+bool buf_ops_has_hw_fence(struct buf_ops *bops, uint32_t tiling)
+{
+	uint32_t tile_mask = (1 << tiling);
+
+	igt_assert(bops);
+
+	if (tile_mask & bops->hw_tiles)
+		return true;
+
+	return false;
+}
+
+bool buf_ops_has_tiling_support(struct buf_ops *bops, uint32_t tiling)
+{
+	uint32_t tile_mask = (1 << tiling);
+
+	igt_assert(bops);
+
+	if (tile_mask & bops->supported_tiles)
+		return true;
+
+	return false;
+}
+
+static int buf_aux_width(int gen, const struct igt_buf *buf)
+{
+	/*
+	 * GEN12+: The AUX CCS unit size is 64 bytes mapping 4 main surface
+	 * tiles. Thus the width of the CCS unit is 4*32=128 pixels on the
+	 * main surface.
+	 */
+	if (gen >= 12)
+		return DIV_ROUND_UP(igt_buf_width(buf), 128) * 64;
+
+	return DIV_ROUND_UP(igt_buf_width(buf), 1024) * 128;
+}
+
+static int buf_aux_height(int gen, const struct igt_buf *buf)
+{
+	/*
+	 * GEN12+: The AUX CCS unit size is 64 bytes mapping 4 main surface
+	 * tiles. Thus the height of the CCS unit is 32 pixel rows on the main
+	 * surface.
+	 */
+	if (gen >= 12)
+		return DIV_ROUND_UP(igt_buf_height(buf), 32);
+
+	return DIV_ROUND_UP(igt_buf_height(buf), 512) * 32;
+}
+
+void igt_buf_init(struct buf_ops *bops, struct igt_buf *buf,
+		  int width, int height, int bpp,
+		  uint32_t req_tiling, bool ccs)
+{
+	uint32_t tiling = req_tiling;
+	bool supports_hw_fences;
+
+	igt_assert(bops);
+
+	supports_hw_fences = buf_ops_has_hw_fence(bops, req_tiling);
+
+	memset(buf, 0, sizeof(*buf));
+
+	if (ccs) {
+		int aux_width, aux_height;
+		int size;
+
+		igt_require(bops->intel_gen >= 9);
+		igt_assert(req_tiling == I915_TILING_Y ||
+			   req_tiling == I915_TILING_Yf);
+
+		/*
+		 * On GEN12+ we align the main surface to 4 * 4 main surface
+		 * tiles, which is 64kB. These 16 tiles are mapped by 4 AUX
+		 * CCS units, that is 4 * 64 bytes. These 4 CCS units are in
+		 * turn mapped by one L1 AUX page table entry.
+		 */
+		if (bops->intel_gen >= 12)
+			buf->stride = ALIGN(width * (bpp / 8), 128 * 4);
+		else
+			buf->stride = ALIGN(width * (bpp / 8), 128);
+
+		if (bops->intel_gen >= 12)
+			height = ALIGN(height, 4 * 32);
+
+		buf->size = buf->stride * height;
+		buf->tiling = tiling;
+		buf->bpp = bpp;
+
+		aux_width = buf_aux_width(bops->intel_gen, buf);
+		aux_height = buf_aux_height(bops->intel_gen, buf);
+
+		buf->aux.offset = buf->stride * ALIGN(height, 32);
+		buf->aux.stride = aux_width;
+
+		size = buf->aux.offset + aux_width * aux_height;
+
+		buf->bo = drm_intel_bo_alloc(bops->bufmgr, "", size, 4096);
+
+		if (tiling == I915_TILING_Y && supports_hw_fences) {
+			drm_intel_bo_set_tiling(buf->bo, &tiling, buf->stride);
+			igt_assert_eq(tiling, req_tiling);
+		}
+	} else {
+		/* Requested bo must be hw tiled */
+		if (supports_hw_fences) {
+			unsigned long pitch;
+
+			buf->bo = drm_intel_bo_alloc_tiled(bops->bufmgr, "",
+							   width, height,
+							   bpp / 8,
+							   &tiling, &pitch, 0);
+			igt_assert_eq(tiling, req_tiling);
+			igt_assert(buf->bo);
+
+			buf->stride = pitch;
+			buf->tiling = tiling;
+			buf->size = pitch * height;
+			buf->bpp = bpp;
+		} else {
+			/* Use bo alloc and software tiling/detiling */
+			int size;
+
+			buf->stride = ALIGN(width * (bpp / 8), 128);
+			buf->size = buf->stride * height;
+			buf->tiling = tiling;
+			buf->bpp = bpp;
+
+			size = buf->stride * ALIGN(height, 32);
+
+			buf->bo = drm_intel_bo_alloc(bops->bufmgr, "", size,
+						     4096);
+			igt_assert(buf->bo);
+		}
+	}
+}
diff --git a/lib/intel_bufops.h b/lib/intel_bufops.h
new file mode 100644
index 00000000..e53c6ebc
--- /dev/null
+++ b/lib/intel_bufops.h
@@ -0,0 +1,24 @@
+#ifndef __INTEL_BUFOPS_H__
+#define __INTEL_BUFOPS_H__
+
+#include "intel_batchbuffer.h"
+
+struct buf_ops;
+
+struct buf_ops *buf_ops_get(int fd, drm_intel_bufmgr *bufmgr);
+void buf_ops_switch_to_sofware_tiling(struct buf_ops *bops);
+
+void copy_buf_to_linear(struct buf_ops *bops, struct igt_buf *buf,
+			uint32_t *linear);
+
+void copy_linear_to_buf(struct buf_ops *bops, struct igt_buf *buf,
+			uint32_t *linear);
+
+bool buf_ops_has_hw_fence(struct buf_ops *bops, uint32_t tiling);
+bool buf_ops_has_tiling_support(struct buf_ops *bops, uint32_t tiling);
+
+void igt_buf_init(struct buf_ops *bops, struct igt_buf *buf,
+		  int width, int height, int bpp,
+		  uint32_t req_tiling, bool ccs);
+
+#endif
diff --git a/lib/meson.build b/lib/meson.build
index 3f908912..a88c3e89 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -26,6 +26,7 @@ lib_sources = [
 	'igt_x86.c',
 	'instdone.c',
 	'intel_batchbuffer.c',
+	'intel_bufops.c',
 	'intel_chipset.c',
 	'intel_device_info.c',
 	'intel_os.c',
-- 
2.23.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [igt-dev] [PATCH i-g-t v2 2/2] tests/gem_render_copy: Add software tiling / detiling support
  2019-12-01 19:09 [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations Zbigniew Kempczyński
@ 2019-12-01 19:09 ` Zbigniew Kempczyński
  2019-12-01 19:36 ` [igt-dev] ✗ Fi.CI.BAT: failure for series starting with [i-g-t,v2,1/2] lib/intel_bufops: Introduce buffer operations Patchwork
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Zbigniew Kempczyński @ 2019-12-01 19:09 UTC (permalink / raw)
  To: igt-dev

Adopt test code to use buffer operations thus allowing software
tiling / detiling on platforms where HW fences are not supported.

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Katarzyna Dec <katarzyna.dec@intel.com>
---
 tests/i915/gem_render_copy.c | 278 +++++------------------------------
 1 file changed, 39 insertions(+), 239 deletions(-)

diff --git a/tests/i915/gem_render_copy.c b/tests/i915/gem_render_copy.c
index 67be079c..4d46216b 100644
--- a/tests/i915/gem_render_copy.c
+++ b/tests/i915/gem_render_copy.c
@@ -47,6 +47,7 @@
 #include <drm.h>
 
 #include "intel_bufmgr.h"
+#include "intel_bufops.h"
 
 IGT_TEST_DESCRIPTION("Basic test for the render_copy() function.");
 
@@ -59,6 +60,7 @@ typedef struct {
 	drm_intel_bufmgr *bufmgr;
 	struct intel_batchbuffer *batch;
 	igt_render_copyfunc_t render_copy;
+	struct buf_ops *bops;
 } data_t;
 static int opt_dump_png = false;
 static int check_all_pixels = false;
@@ -72,129 +74,13 @@ static const char *make_filename(const char *filename)
 	return buf;
 }
 
-static void *yf_ptr(void *ptr,
-		    unsigned int x, unsigned int y,
-		    unsigned int stride, unsigned int cpp)
+static void *alloc_aligned(uint64_t size)
 {
-	const int tile_size = 4 * 1024;
-	const int tile_width = 128;
-	int row_size = (stride / tile_width) * tile_size;
+	void *p;
 
-	x *= cpp; /* convert to Byte offset */
+	igt_assert_eq(posix_memalign(&p, 16, size), 0);
 
-
-	/*
-	 * Within a 4k Yf tile, the byte swizzling pattern is
-	 * msb......lsb
-	 * xyxyxyyyxxxx
-	 * The tiles themselves are laid out in row major order.
-	 */
-	return ptr +
-		((x & 0xf) * 1) + /* 4x1 pixels(32bpp) = 16B */
-		((y & 0x3) * 16) + /* 4x4 pixels = 64B */
-		(((y & 0x4) >> 2) * 64) + /* 1x2 64B blocks */
-		(((x & 0x10) >> 4) * 128) + /* 2x2 64B blocks = 256B block */
-		(((y & 0x8) >> 3) * 256) + /* 2x1 256B blocks */
-		(((x & 0x20) >> 5) * 512) + /* 2x2 256B blocks */
-		(((y & 0x10) >> 4) * 1024) + /* 4x2 256 blocks */
-		(((x & 0x40) >> 6) * 2048) + /* 4x4 256B blocks = 4k tile */
-		(((x & ~0x7f) >> 7) * tile_size) + /* row of tiles */
-		(((y & ~0x1f) >> 5) * row_size);
-}
-
-static void copy_linear_to_yf(data_t *data, struct igt_buf *buf,
-			      const uint32_t *linear)
-{
-	int height = igt_buf_height(buf);
-	int width = igt_buf_width(buf);
-	void *map;
-
-	gem_set_domain(data->drm_fd, buf->bo->handle,
-		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
-	map = gem_mmap__cpu(data->drm_fd, buf->bo->handle, 0,
-			    buf->bo->size, PROT_READ | PROT_WRITE);
-
-	for (int y = 0; y < height; y++) {
-		for (int x = 0; x < width; x++) {
-			uint32_t *ptr = yf_ptr(map, x, y,
-					       buf->stride, buf->bpp / 8);
-
-			*ptr = linear[y * width + x];
-		}
-	}
-
-	munmap(map, buf->bo->size);
-}
-
-static void copy_yf_to_linear(data_t *data, struct igt_buf *buf,
-			      uint32_t *linear)
-{
-	int height = igt_buf_height(buf);
-	int width = igt_buf_width(buf);
-	void *map;
-
-	gem_set_domain(data->drm_fd, buf->bo->handle,
-		       I915_GEM_DOMAIN_CPU, 0);
-	map = gem_mmap__cpu(data->drm_fd, buf->bo->handle, 0,
-			    buf->bo->size, PROT_READ);
-
-	for (int y = 0; y < height; y++) {
-		for (int x = 0; x < width; x++) {
-			uint32_t *ptr = yf_ptr(map, x, y,
-					       buf->stride, buf->bpp / 8);
-
-			linear[y * width + x] = *ptr;
-		}
-	}
-
-	munmap(map, buf->bo->size);
-}
-
-static void copy_linear_to_gtt(data_t *data, struct igt_buf *buf,
-			       const uint32_t *linear)
-{
-	void *map;
-
-	gem_set_domain(data->drm_fd, buf->bo->handle,
-		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
-
-	map = gem_mmap__gtt(data->drm_fd, buf->bo->handle,
-			    buf->bo->size, PROT_READ | PROT_WRITE);
-
-	memcpy(map, linear, buf->bo->size);
-
-	munmap(map, buf->bo->size);
-}
-
-static void copy_gtt_to_linear(data_t *data, struct igt_buf *buf,
-			       uint32_t *linear)
-{
-	void *map;
-
-	gem_set_domain(data->drm_fd, buf->bo->handle,
-		       I915_GEM_DOMAIN_GTT, 0);
-
-	map = gem_mmap__gtt(data->drm_fd, buf->bo->handle,
-			    buf->bo->size, PROT_READ);
-
-	igt_memcpy_from_wc(linear, map, buf->bo->size);
-
-	munmap(map, buf->bo->size);
-}
-
-static void *linear_copy(data_t *data, struct igt_buf *buf)
-{
-	void *linear;
-
-	/* 16B alignment allows to potentially make use of SSE4 for copying */
-	igt_assert_eq(posix_memalign(&linear, 16, buf->bo->size), 0);
-
-	if (buf->tiling == I915_TILING_Yf)
-		copy_yf_to_linear(data, buf, linear);
-	else
-		copy_gtt_to_linear(data, buf, linear);
-
-	return linear;
+	return p;
 }
 
 static void scratch_buf_write_to_png(data_t *data, struct igt_buf *buf,
@@ -204,7 +90,8 @@ static void scratch_buf_write_to_png(data_t *data, struct igt_buf *buf,
 	cairo_status_t ret;
 	void *linear;
 
-	linear = linear_copy(data, buf);
+	linear = alloc_aligned(buf->bo->size);
+	copy_buf_to_linear(data->bops, buf, linear);
 
 	surface = cairo_image_surface_create_for_data(linear,
 						      CAIRO_FORMAT_RGB24,
@@ -250,12 +137,12 @@ static void *linear_copy_aux(data_t *data, struct igt_buf *buf)
 	int aux_size = scratch_buf_aux_width(data->devid, buf) *
 		scratch_buf_aux_height(data->devid, buf);
 
-	igt_assert_eq(posix_memalign(&linear, 16, aux_size), 0);
+	linear = alloc_aligned(aux_size);
 
 	gem_set_domain(data->drm_fd, buf->bo->handle,
 		       I915_GEM_DOMAIN_GTT, 0);
 
-	map = gem_mmap__gtt(data->drm_fd, buf->bo->handle,
+	map = gem_mmap__wc(data->drm_fd, buf->bo->handle, 0,
 			    buf->bo->size, PROT_READ);
 
 	igt_memcpy_from_wc(linear, map + buf->aux.offset, aux_size);
@@ -297,7 +184,7 @@ static void scratch_buf_draw_pattern(data_t *data, struct igt_buf *buf,
 	cairo_t *cr;
 	void *linear;
 
-	linear = linear_copy(data, buf);
+	linear = alloc_aligned(buf->bo->size);
 
 	surface = cairo_image_surface_create_for_data(linear,
 						      CAIRO_FORMAT_RGB24,
@@ -338,10 +225,7 @@ static void scratch_buf_draw_pattern(data_t *data, struct igt_buf *buf,
 
 	cairo_surface_destroy(surface);
 
-	if (buf->tiling == I915_TILING_Yf)
-		copy_linear_to_yf(data, buf, linear);
-	else
-		copy_linear_to_gtt(data, buf, linear);
+	copy_linear_to_buf(data->bops, buf, linear);
 
 	free(linear);
 }
@@ -354,6 +238,7 @@ scratch_buf_copy(data_t *data,
 	int width = igt_buf_width(dst);
 	int height  = igt_buf_height(dst);
 	uint32_t *linear_dst;
+	uint32_t *linear_src;
 
 	igt_assert_eq(igt_buf_width(dst), igt_buf_width(src));
 	igt_assert_eq(igt_buf_height(dst), igt_buf_height(src));
@@ -366,123 +251,29 @@ scratch_buf_copy(data_t *data,
 	h = min(h, height - sy);
 	h = min(h, height - dy);
 
-	gem_set_domain(data->drm_fd, dst->bo->handle,
-		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
-	linear_dst = gem_mmap__gtt(data->drm_fd, dst->bo->handle,
-				   dst->bo->size, PROT_WRITE);
-
-	if (src->tiling == I915_TILING_Yf) {
-		void *map;
-
-		gem_set_domain(data->drm_fd, src->bo->handle,
-			       I915_GEM_DOMAIN_CPU, 0);
-		map = gem_mmap__cpu(data->drm_fd, src->bo->handle, 0,
-				    src->bo->size, PROT_READ);
-
-		for (int y = 0; y < h; y++) {
-			for (int x = 0; x < w; x++) {
-				const uint32_t *ptr = yf_ptr(map, sx+x, sy+y,
-							     src->stride,
-							     src->bpp / 8);
-
-				linear_dst[(dy+y) * width + dx+x] = *ptr;
-			}
-		}
-
-		munmap(map, src->bo->size);
-	} else {
-		uint32_t *linear_src;
-
-		gem_set_domain(data->drm_fd, src->bo->handle,
-			       I915_GEM_DOMAIN_GTT, 0);
-
-		linear_src = gem_mmap__gtt(data->drm_fd, src->bo->handle,
-					   src->bo->size, PROT_READ);
+	linear_dst = alloc_aligned(dst->bo->size);
+	linear_src = alloc_aligned(src->bo->size);
+	copy_buf_to_linear(data->bops, src, linear_src);
+	copy_buf_to_linear(data->bops, dst, linear_dst);
 
-		for (int y = 0; y < h; y++) {
-			igt_memcpy_from_wc(&linear_dst[(dy+y) * width + dx],
-					   &linear_src[(sy+y) * width + sx],
-					   w * (src->bpp / 8));
-		}
-
-		munmap(linear_src, src->bo->size);
+	for (int y = 0; y < h; y++) {
+		memcpy(&linear_dst[(dy+y) * width + dx],
+				&linear_src[(sy+y) * width + sx],
+				w * (src->bpp / 8));
 	}
+	free(linear_src);
 
-	munmap(linear_dst, dst->bo->size);
+	copy_linear_to_buf(data->bops, dst, linear_dst);
+	free(linear_dst);
 }
 
 static void scratch_buf_init(data_t *data, struct igt_buf *buf,
 			     int width, int height,
 			     uint32_t req_tiling, bool ccs)
 {
-	uint32_t tiling = req_tiling;
-	unsigned long pitch;
 	int bpp = 32;
 
-	memset(buf, 0, sizeof(*buf));
-
-	if (ccs) {
-		int aux_width, aux_height;
-		int size;
-
-		igt_require(intel_gen(data->devid) >= 9);
-		igt_assert(tiling == I915_TILING_Y ||
-			   tiling == I915_TILING_Yf);
-
-		/*
-		 * On GEN12+ we align the main surface to 4 * 4 main surface
-		 * tiles, which is 64kB. These 16 tiles are mapped by 4 AUX
-		 * CCS units, that is 4 * 64 bytes. These 4 CCS units are in
-		 * turn mapped by one L1 AUX page table entry.
-		 */
-		if (intel_gen(data->devid) >= 12)
-			buf->stride = ALIGN(width * (bpp / 8), 128 * 4);
-		else
-			buf->stride = ALIGN(width * (bpp / 8), 128);
-
-		if (intel_gen(data->devid) >= 12)
-			height = ALIGN(height, 4 * 32);
-
-		buf->size = buf->stride * height;
-		buf->tiling = tiling;
-		buf->bpp = bpp;
-
-		aux_width = scratch_buf_aux_width(data->devid, buf);
-		aux_height = scratch_buf_aux_height(data->devid, buf);
-
-		buf->aux.offset = buf->stride * ALIGN(height, 32);
-		buf->aux.stride = aux_width;
-
-		size = buf->aux.offset + aux_width * aux_height;
-
-		buf->bo = drm_intel_bo_alloc(data->bufmgr, "", size, 4096);
-
-		if (tiling == I915_TILING_Y) {
-			drm_intel_bo_set_tiling(buf->bo, &tiling, buf->stride);
-			igt_assert_eq(tiling, req_tiling);
-		}
-	} else if (req_tiling == I915_TILING_Yf) {
-		int size;
-
-		buf->stride = ALIGN(width * (bpp / 8), 128);
-		buf->size = buf->stride * height;
-		buf->tiling = tiling;
-		buf->bpp = bpp;
-
-		size = buf->stride * ALIGN(height, 32);
-
-		buf->bo = drm_intel_bo_alloc(data->bufmgr, "", size, 4096);
-	} else {
-		buf->bo = drm_intel_bo_alloc_tiled(data->bufmgr, "",
-						   width, height, bpp / 8,
-						   &tiling, &pitch, 0);
-		igt_assert_eq(tiling, req_tiling);
-
-		buf->stride = pitch;
-		buf->tiling = tiling;
-		buf->size = pitch * height;
-		buf->bpp = bpp;
-	}
+	igt_buf_init(data->bops, buf, width, height, bpp, req_tiling, ccs);
 
 	igt_assert(igt_buf_width(buf) == width);
 	igt_assert(igt_buf_height(buf) == height);
@@ -507,11 +298,13 @@ scratch_buf_check(data_t *data,
 	igt_assert_eq(igt_buf_height(buf), igt_buf_height(ref));
 	igt_assert_eq(buf->bo->size, ref->bo->size);
 
-	linear = linear_copy(data, buf);
+	linear = alloc_aligned(buf->bo->size);
+	copy_buf_to_linear(data->bops, buf, linear);
 	buf_val = linear[y * width + x];
 	free(linear);
 
-	linear = linear_copy(data, ref);
+	linear = alloc_aligned(ref->bo->size);
+	copy_buf_to_linear(data->bops, buf, linear);
 	ref_val = linear[y * width + x];
 	free(linear);
 
@@ -533,8 +326,10 @@ scratch_buf_check_all(data_t *data,
 	igt_assert_eq(igt_buf_height(buf), igt_buf_height(ref));
 	igt_assert_eq(buf->bo->size, ref->bo->size);
 
-	linear_buf = linear_copy(data, buf);
-	linear_ref = linear_copy(data, ref);
+	linear_buf = alloc_aligned(buf->bo->size);
+	linear_ref = alloc_aligned(ref->bo->size);
+	copy_buf_to_linear(data->bops, buf, linear_buf);
+	copy_buf_to_linear(data->bops, ref, linear_ref);
 
 	for (int y = 0; y < height; y++) {
 		for (int x = 0; x < width; x++) {
@@ -627,6 +422,7 @@ static void test(data_t *data, uint32_t src_tiling, uint32_t dst_tiling,
 
 	for (int i = 0; i < num_src; i++)
 		scratch_buf_init(data, &src[i].buf, WIDTH, HEIGHT, src[i].tiling, false);
+
 	scratch_buf_init(data, &dst, WIDTH, HEIGHT, dst_tiling, false);
 	if (src_compressed)
 		scratch_buf_init(data, &src_ccs, WIDTH, HEIGHT,
@@ -639,7 +435,8 @@ static void test(data_t *data, uint32_t src_tiling, uint32_t dst_tiling,
 	for (int i = 0; i < num_src; i++)
 		scratch_buf_draw_pattern(data, &src[i].buf,
 					 0, 0, WIDTH, HEIGHT,
-					 0, 0, WIDTH, HEIGHT, true);
+					 0, 0, WIDTH, HEIGHT, (i % 2));
+
 	scratch_buf_draw_pattern(data, &dst,
 				 0, 0, WIDTH, HEIGHT,
 				 0, 0, WIDTH, HEIGHT, false);
@@ -826,6 +623,9 @@ igt_main_args("da", NULL, help_str, opt_handler, NULL)
 		data.batch = intel_batchbuffer_alloc(data.bufmgr, data.devid);
 		igt_assert(data.batch);
 
+		data.bops = buf_ops_get(data.drm_fd, data.bufmgr);
+		igt_assert(data.bops);
+
 		igt_fork_hang_detector(data.drm_fd);
 	}
 
-- 
2.23.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [igt-dev] ✗ Fi.CI.BAT: failure for series starting with [i-g-t,v2,1/2] lib/intel_bufops: Introduce buffer operations
  2019-12-01 19:09 [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations Zbigniew Kempczyński
  2019-12-01 19:09 ` [igt-dev] [PATCH i-g-t v2 2/2] tests/gem_render_copy: Add software tiling / detiling support Zbigniew Kempczyński
@ 2019-12-01 19:36 ` Patchwork
  2019-12-03  9:25 ` [igt-dev] [PATCH i-g-t v2 1/2] " Katarzyna Dec
  2019-12-10  0:07 ` Dixit, Ashutosh
  3 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2019-12-01 19:36 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev

== Series Details ==

Series: series starting with [i-g-t,v2,1/2] lib/intel_bufops: Introduce buffer operations
URL   : https://patchwork.freedesktop.org/series/70258/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_7457 -> IGTPW_3789
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_3789 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_3789, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_3789:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_selftest@live_blt:
    - fi-hsw-4770r:       NOTRUN -> [DMESG-FAIL][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/fi-hsw-4770r/igt@i915_selftest@live_blt.html

  * igt@i915_selftest@live_gem_contexts:
    - fi-hsw-peppy:       [PASS][2] -> [INCOMPLETE][3]
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7457/fi-hsw-peppy/igt@i915_selftest@live_gem_contexts.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/fi-hsw-peppy/igt@i915_selftest@live_gem_contexts.html

  
Known issues
------------

  Here are the changes found in IGTPW_3789 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-kbl-7500u:       [PASS][4] -> [FAIL][5] ([fdo#111407])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7457/fi-kbl-7500u/igt@kms_chamelium@hdmi-hpd-fast.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/fi-kbl-7500u/igt@kms_chamelium@hdmi-hpd-fast.html

  
#### Possible fixes ####

  * igt@i915_selftest@live_blt:
    - fi-hsw-4770:        [DMESG-FAIL][6] -> [PASS][7]
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7457/fi-hsw-4770/igt@i915_selftest@live_blt.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/fi-hsw-4770/igt@i915_selftest@live_blt.html

  * igt@i915_selftest@live_mman:
    - fi-bwr-2160:        [DMESG-WARN][8] -> [PASS][9]
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7457/fi-bwr-2160/igt@i915_selftest@live_mman.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/fi-bwr-2160/igt@i915_selftest@live_mman.html

  * igt@kms_chamelium@dp-crc-fast:
    - fi-icl-u2:          [FAIL][10] ([fdo#109635] / [i915#262]) -> [PASS][11]
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7457/fi-icl-u2/igt@kms_chamelium@dp-crc-fast.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/fi-icl-u2/igt@kms_chamelium@dp-crc-fast.html

  
#### Warnings ####

  * igt@i915_pm_rpm@basic-rte:
    - fi-kbl-guc:         [FAIL][12] ([i915#579]) -> [SKIP][13] ([fdo#109271])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7457/fi-kbl-guc/igt@i915_pm_rpm@basic-rte.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/fi-kbl-guc/igt@i915_pm_rpm@basic-rte.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - fi-kbl-x1275:       [DMESG-WARN][14] ([i915#62] / [i915#92] / [i915#95]) -> [DMESG-WARN][15] ([i915#62] / [i915#92]) +7 similar issues
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7457/fi-kbl-x1275/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/fi-kbl-x1275/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_flip@basic-flip-vs-modeset:
    - fi-kbl-x1275:       [DMESG-WARN][16] ([i915#62] / [i915#92]) -> [DMESG-WARN][17] ([i915#62] / [i915#92] / [i915#95]) +3 similar issues
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7457/fi-kbl-x1275/igt@kms_flip@basic-flip-vs-modeset.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/fi-kbl-x1275/igt@kms_flip@basic-flip-vs-modeset.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109635]: https://bugs.freedesktop.org/show_bug.cgi?id=109635
  [fdo#111407]: https://bugs.freedesktop.org/show_bug.cgi?id=111407
  [i915#243]: https://gitlab.freedesktop.org/drm/intel/issues/243
  [i915#262]: https://gitlab.freedesktop.org/drm/intel/issues/262
  [i915#579]: https://gitlab.freedesktop.org/drm/intel/issues/579
  [i915#609]: https://gitlab.freedesktop.org/drm/intel/issues/609
  [i915#62]: https://gitlab.freedesktop.org/drm/intel/issues/62
  [i915#92]: https://gitlab.freedesktop.org/drm/intel/issues/92
  [i915#95]: https://gitlab.freedesktop.org/drm/intel/issues/95


Participating hosts (49 -> 43)
------------------------------

  Additional (1): fi-hsw-4770r 
  Missing    (7): fi-ilk-m540 fi-hsw-4200u fi-bsw-cyan fi-ctg-p8600 fi-kbl-8809g fi-byt-clapper fi-bdw-samus 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_5320 -> IGTPW_3789

  CI-20190529: 20190529
  CI_DRM_7457: a198a06594dd4ac7488e4db1aa6cb228d7afde0f @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_3789: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/index.html
  IGT_5320: 06833ffeaf7621c3fef097166539bbe999a33e9c @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3789/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations
  2019-12-01 19:09 [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations Zbigniew Kempczyński
  2019-12-01 19:09 ` [igt-dev] [PATCH i-g-t v2 2/2] tests/gem_render_copy: Add software tiling / detiling support Zbigniew Kempczyński
  2019-12-01 19:36 ` [igt-dev] ✗ Fi.CI.BAT: failure for series starting with [i-g-t,v2,1/2] lib/intel_bufops: Introduce buffer operations Patchwork
@ 2019-12-03  9:25 ` Katarzyna Dec
  2019-12-03  9:41   ` Katarzyna Dec
  2019-12-03 17:05   ` Zbigniew Kempczyński
  2019-12-10  0:07 ` Dixit, Ashutosh
  3 siblings, 2 replies; 8+ messages in thread
From: Katarzyna Dec @ 2019-12-03  9:25 UTC (permalink / raw)
  To: Zbigniew Kempczyński, igt-dev

On Sun, Dec 01, 2019 at 08:09:41PM +0100, Zbigniew Kempczyński wrote:
> Different GENs supports different tile surfaces. Older GENs
> have HW fences to allow X / Y surface tiling / detiling.
> Newer GENs have to tile / detile such surface in software.
> 
> To make test developer life easier this code adds buffer
> operations (short bufops) to use appropriate functions allowing
> copying linear buffer to BO and from BO to linear buffer
> regardless GPU generation and tiling within BO. For GENs having
> fences support preference is to use them if they are available
> (X / Y tiling is probed on bufops initalization).
> 
> Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Imre Deak <imre.deak@intel.com>
> Cc: Katarzyna Dec <katarzyna.dec@intel.com>
> ---
>  lib/Makefile.sources |   2 +
>  lib/intel_bufops.c   | 689 +++++++++++++++++++++++++++++++++++++++++++
>  lib/intel_bufops.h   |  24 ++
>  lib/meson.build      |   1 +
>  4 files changed, 716 insertions(+)
>  create mode 100644 lib/intel_bufops.c
>  create mode 100644 lib/intel_bufops.h
> 
> diff --git a/lib/Makefile.sources b/lib/Makefile.sources
> index 9d1a4e06..b808f294 100644
> --- a/lib/Makefile.sources
> +++ b/lib/Makefile.sources
> @@ -65,6 +65,8 @@ lib_source_list =	 	\
>  	intel_aub.h		\
>  	intel_batchbuffer.c	\
>  	intel_batchbuffer.h	\
> +	intel_bufops.c		\
> +	intel_bufops.h		\
>  	intel_chipset.c		\
>  	intel_chipset.h		\
>  	intel_device_info.c	\
> diff --git a/lib/intel_bufops.c b/lib/intel_bufops.c
> new file mode 100644
> index 00000000..fdb8bdc7
> --- /dev/null
> +++ b/lib/intel_bufops.c
> @@ -0,0 +1,689 @@
> +#include <sys/ioctl.h>
> +#include "igt.h"
> +#include "igt_x86.h"
> +#include "intel_bufops.h"
> +
> +#define TILE_NONE   (1 << I915_TILING_NONE)
> +#define TILE_X      (1 << I915_TILING_X)
> +#define TILE_Y      (1 << I915_TILING_Y)
> +#define TILE_Yf     (1 << I915_TILING_Yf)
> +#define TILE_Ys     (1 << I915_TILING_Ys)
> +
> +typedef void (*bo_copy)(int, struct igt_buf *, uint32_t *);
> +
> +struct buf_ops {
> +	int fd;
> +	drm_intel_bufmgr *bufmgr;
> +	int gen_start;
> +	int gen_end;
> +	int intel_gen;
> +	uint32_t supported_tiles;
> +	uint32_t hw_tiles;
> +	bo_copy linear_to;
> +	bo_copy linear_to_x;
> +	bo_copy linear_to_y;
> +	bo_copy linear_to_yf;
> +	bo_copy linear_to_ys;
> +	bo_copy to_linear;
> +	bo_copy x_to_linear;
> +	bo_copy y_to_linear;
> +	bo_copy yf_to_linear;
> +	bo_copy ys_to_linear;
> +};
> +
> +static void *x_ptr(void *ptr,
> +		   unsigned int x, unsigned int y,
> +		   unsigned int stride, unsigned int cpp)
> +{
> +	const int tile_width = 512;
> +	const int tile_height = 8;
It can be really silly question - are these ^ values always the same?
> +	const int tile_size = tile_width * tile_height;
> +	int tile_x, tile_y;
> +	int offset_x, offset_y, pos;
> +
> +	x *= cpp;
> +	tile_x = x / tile_width;
> +	tile_y = y / tile_height;
> +	offset_x = (tile_x * tile_size);
> +	offset_y = (tile_y * stride * tile_height);
> +
> +	pos = offset_y + offset_x +
> +			(y % tile_height * tile_width) + (x % tile_width);
> +
> +	return ptr + pos;
> +}
> +
> +static void *y_ptr(void *ptr,
> +		   unsigned int x, unsigned int y,
> +		   unsigned int stride, unsigned int cpp)
> +{
> +	const int tile_width = 128;
> +	const int tile_height = 32;
> +	const int owords = 16;
Similar question. I guess this is something specific either to Intel Gen or to
testcases.
> +	const int tile_size = tile_width * tile_height;
> +	int tile_x, tile_y;
> +	int offset_x, offset_y, pos;
> +	int shift_x, shift_y;
> +
> +	x *= cpp;
> +	tile_x = x / tile_width;
> +	tile_y = y / tile_height;
> +	offset_x = tile_x * tile_size;
> +	offset_y = tile_y * stride * tile_height;
> +	shift_x = x % owords + (x % tile_width) / owords * tile_width * cpp;
> +	shift_y = y % tile_height * owords;
> +
> +	pos = offset_y + offset_x + shift_x + shift_y;
> +
> +	return ptr + pos;
> +}
> +
> +static void *yf_ptr(void *ptr,
> +		    unsigned int x, unsigned int y,
> +		    unsigned int stride, unsigned int cpp)
> +{
> +	const int tile_size = 4 * 1024;
> +	const int tile_width = 128;
> +	int row_size = (stride / tile_width) * tile_size;
> +
> +	x *= cpp; /* convert to Byte offset */
> +
> +
> +	/*
> +	 * Within a 4k Yf tile, the byte swizzling pattern is
> +	 * msb......lsb
> +	 * xyxyxyyyxxxx
> +	 * The tiles themselves are laid out in row major order.
> +	 */
> +	return ptr +
> +			((x & 0xf) * 1) + /* 4x1 pixels(32bpp) = 16B */
> +			((y & 0x3) * 16) + /* 4x4 pixels = 64B */
> +			(((y & 0x4) >> 2) * 64) + /* 1x2 64B blocks */
> +			(((x & 0x10) >> 4) * 128) + /* 2x2 64B blocks = 256B block */
> +			(((y & 0x8) >> 3) * 256) + /* 2x1 256B blocks */
> +			(((x & 0x20) >> 5) * 512) + /* 2x2 256B blocks */
> +			(((y & 0x10) >> 4) * 1024) + /* 4x2 256 blocks */
> +			(((x & 0x40) >> 6) * 2048) + /* 4x4 256B blocks = 4k tile */
> +			(((x & ~0x7f) >> 7) * tile_size) + /* row of tiles */
> +			(((y & ~0x1f) >> 5) * row_size);
> +}
> +
> +typedef void *(*fn_ptr)(void *, unsigned int, unsigned int,
> +			unsigned int, unsigned int);
> +static fn_ptr __get_tile_fn_ptr(int tiling)
> +{
> +	fn_ptr fn = NULL;
> +
> +	switch (tiling) {
> +	case I915_TILING_X:
> +		fn = x_ptr;
> +		break;
> +	case I915_TILING_Y:
> +		fn = y_ptr;
> +		break;
> +	case I915_TILING_Yf:
> +		fn = yf_ptr;
> +		break;
> +	case I915_TILING_Ys:
> +		/* To be implemented */
> +		break;
> +	}
> +
> +	igt_assert_f(fn, "Can't find tile function for tiling: %d\n", tiling);
> +
> +	return fn;
> +}
> +
> +static void __copy_linear_to(int fd, struct igt_buf *buf,
> +			     const uint32_t *linear, int tiling)
> +{
> +	int height = igt_buf_height(buf);
> +	int width = igt_buf_width(buf);
> +	fn_ptr fn = __get_tile_fn_ptr(tiling);
> +	void *map;
> +
> +	gem_set_domain(fd, buf->bo->handle,
> +		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
> +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> +			    buf->bo->size, PROT_READ | PROT_WRITE);
> +
> +	for (int y = 0; y < height; y++) {
> +		for (int x = 0; x < width; x++) {
> +			uint32_t *ptr = fn(map, x, y,
> +					   buf->stride, buf->bpp / 8);
> +
> +			*ptr = linear[y * width + x];
> +		}
> +	}
> +
> +	munmap(map, buf->bo->size);
> +}
> +
> +static void copy_linear_to_x(int fd, struct igt_buf *buf,
> +			     uint32_t *linear)
> +{
> +	__copy_linear_to(fd, buf, linear, I915_TILING_X);
> +}
> +
> +static void copy_linear_to_y(int fd, struct igt_buf *buf,
> +			     uint32_t *linear)
> +{
> +	__copy_linear_to(fd, buf, linear, I915_TILING_Y);
> +}
> +
> +static void copy_linear_to_yf(int fd, struct igt_buf *buf,
> +			      uint32_t *linear)
> +{
> +	__copy_linear_to(fd, buf, linear, I915_TILING_Yf);
> +}
> +
> +static void __copy_to_linear(int fd, struct igt_buf *buf,
> +			     uint32_t *linear, int tiling)
> +{
> +	int height = igt_buf_height(buf);
> +	int width = igt_buf_width(buf);
> +	fn_ptr fn = __get_tile_fn_ptr(tiling);
> +	void *map;
> +
> +	gem_set_domain(fd, buf->bo->handle,
> +		       I915_GEM_DOMAIN_CPU, 0);
> +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> +			    buf->bo->size, PROT_READ);
> +
> +	for (int y = 0; y < height; y++) {
> +		for (int x = 0; x < width; x++) {
> +			uint32_t *ptr = fn(map, x, y,
> +					   buf->stride, buf->bpp / 8);
> +
> +			linear[y * width + x] = *ptr;
> +		}
> +	}
> +
> +	munmap(map, buf->bo->size);
> +}
> +
> +static void copy_yf_to_linear(int fd, struct igt_buf *buf,
> +			      uint32_t *linear)
> +{
> +	__copy_to_linear(fd, buf, linear, I915_TILING_Yf);
> +}
> +
> +static void copy_x_to_linear(int fd, struct igt_buf *buf,
> +			     uint32_t *linear)
> +{
> +	__copy_to_linear(fd, buf, linear, I915_TILING_X);
> +}
> +
> +static void copy_y_to_linear(int fd, struct igt_buf *buf,
> +			     uint32_t *linear)
> +{
> +	__copy_to_linear(fd, buf, linear, I915_TILING_Y);
> +}
> +
> +static void copy_linear_to_gtt(int fd, struct igt_buf *buf,
> +			       uint32_t *linear)
> +{
> +	void *map;
> +
> +	gem_set_domain(fd, buf->bo->handle,
> +		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> +
> +	map = gem_mmap__gtt(fd, buf->bo->handle,
> +			    buf->bo->size, PROT_READ | PROT_WRITE);
> +
> +	memcpy(map, linear, buf->bo->size);
> +
> +	munmap(map, buf->bo->size);
> +}
> +
> +static void copy_gtt_to_linear(int fd, struct igt_buf *buf,
> +			       uint32_t *linear)
> +{
> +	void *map;
> +
> +	gem_set_domain(fd, buf->bo->handle,
> +		       I915_GEM_DOMAIN_GTT, 0);
> +
> +	map = gem_mmap__gtt(fd, buf->bo->handle,
> +			    buf->bo->size, PROT_READ);
> +
> +	igt_memcpy_from_wc(linear, map, buf->bo->size);
> +
> +	munmap(map, buf->bo->size);
> +}
> +
> +static void copy_linear_to_wc(int fd, struct igt_buf *buf,
> +			      uint32_t *linear)
> +{
> +	void *map;
> +
> +	gem_set_domain(fd, buf->bo->handle,
> +		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> +
> +	map = gem_mmap__wc(fd, buf->bo->handle, 0,
> +			   buf->bo->size, PROT_READ | PROT_WRITE);
> +
> +	memcpy(map, linear, buf->bo->size);
> +
> +	munmap(map, buf->bo->size);
> +}
> +
> +static void copy_wc_to_linear(int fd, struct igt_buf *buf,
> +			      uint32_t *linear)
> +{
> +	void *map;
> +
> +	gem_set_domain(fd, buf->bo->handle,
> +		       I915_GEM_DOMAIN_GTT, 0);
> +
> +	map = gem_mmap__wc(fd, buf->bo->handle, 0,
> +			   buf->bo->size, PROT_READ);
> +
> +	igt_memcpy_from_wc(linear, map, buf->bo->size);
> +
> +	munmap(map, buf->bo->size);
> +}
> +
> +static void copy_linear_to_cpu(int fd, struct igt_buf *buf,
> +			       uint32_t *linear)
> +{
> +	void *map;
> +
> +	gem_set_domain(fd, buf->bo->handle,
> +		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
> +
> +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> +			    buf->bo->size, PROT_READ | PROT_WRITE);
> +
> +	memcpy(map, linear, buf->bo->size);
> +
> +	munmap(map, buf->bo->size);
> +}
> +
> +static void copy_cpu_to_linear(int fd, struct igt_buf *buf,
> +			       uint32_t *linear)
> +{
> +	void *map;
> +
> +	gem_set_domain(fd, buf->bo->handle,
> +		       I915_GEM_DOMAIN_CPU, 0);
> +
> +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> +			    buf->bo->size, PROT_READ);
> +
> +	memcpy(linear, map, buf->bo->size);
> +
> +	munmap(map, buf->bo->size);
> +}
> +
> +void copy_buf_to_linear(struct buf_ops *bops, struct igt_buf *buf,
> +			uint32_t *linear)
> +{
> +	igt_assert(bops);
> +
> +	switch (buf->tiling) {
> +	case I915_TILING_NONE:
> +		igt_assert(bops->to_linear);
> +		bops->to_linear(bops->fd, buf, linear);
> +		break;
> +	case I915_TILING_X:
> +		igt_assert(bops->x_to_linear);
> +		bops->x_to_linear(bops->fd, buf, linear);
> +		break;
> +	case I915_TILING_Y:
> +		igt_assert(bops->y_to_linear);
> +		bops->y_to_linear(bops->fd, buf, linear);
> +		break;
> +	case I915_TILING_Yf:
> +		igt_assert(bops->yf_to_linear);
> +		bops->yf_to_linear(bops->fd, buf, linear);
> +		break;
> +	case I915_TILING_Ys:
> +		igt_assert(bops->ys_to_linear);
> +		bops->ys_to_linear(bops->fd, buf, linear);
> +		break;
> +	}
> +}
> +
> +void copy_linear_to_buf(struct buf_ops *bops, struct igt_buf *buf,
> +			uint32_t *linear)
> +{
> +	igt_assert(bops);
> +
> +	switch (buf->tiling) {
> +	case I915_TILING_NONE:
> +		igt_assert(bops->linear_to);
> +		bops->linear_to(bops->fd, buf, linear);
> +		break;
> +	case I915_TILING_X:
> +		igt_assert(bops->linear_to_x);
> +		bops->linear_to_x(bops->fd, buf, linear);
> +		break;
> +	case I915_TILING_Y:
> +		igt_assert(bops->linear_to_y);
> +		bops->linear_to_y(bops->fd, buf, linear);
> +		break;
> +	case I915_TILING_Yf:
> +		igt_assert(bops->linear_to_yf);
> +		bops->linear_to_yf(bops->fd, buf, linear);
> +		break;
> +	case I915_TILING_Ys:
> +		igt_assert(bops->linear_to_ys);
> +		bops->linear_to_ys(bops->fd, buf, linear);
> +		break;
> +	}
> +}
> +
> +struct buf_ops buf_ops_arr[] = {
> +	/* Generations 0 - 8 */
> +{
> +	.gen_start         = 0,
> +	.gen_end           = 8,
> +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y,
> +	.hw_tiles          = TILE_X | TILE_Y,
> +	.linear_to         = copy_linear_to_cpu,
> +	.linear_to_x       = copy_linear_to_gtt,
> +	.linear_to_y       = copy_linear_to_gtt,
> +	.to_linear         = copy_cpu_to_linear,
> +	.x_to_linear       = copy_gtt_to_linear,
> +	.y_to_linear       = copy_gtt_to_linear,
> +},
> +/* Generations 9 - 11 */
> +{
> +	.gen_start         = 9,
> +	.gen_end           = 11,
> +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf,
> +	.hw_tiles          = TILE_X | TILE_Y,
> +	.linear_to         = copy_linear_to_cpu,
> +	.linear_to_x       = copy_linear_to_gtt,
> +	.linear_to_y       = copy_linear_to_gtt,
> +	.linear_to_yf      = copy_linear_to_yf,
> +	.to_linear         = copy_cpu_to_linear,
> +	.x_to_linear       = copy_gtt_to_linear,
> +	.y_to_linear       = copy_gtt_to_linear,
> +	.yf_to_linear      = copy_yf_to_linear,
> +},
> +/* Generation 12 */
> +{
> +	.gen_start         = 12,
> +	.gen_end           = 12,
> +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf | TILE_Ys,
> +	.linear_to         = copy_linear_to_wc,
> +	.linear_to_x       = copy_linear_to_x,
> +	.linear_to_y       = copy_linear_to_y,
> +	.linear_to_yf      = copy_linear_to_yf,
> +	.linear_to_ys      = NULL,               /* to be implemented */
> +	.to_linear         = copy_wc_to_linear,
> +	.x_to_linear       = copy_x_to_linear,
> +	.y_to_linear       = copy_y_to_linear,
> +	.yf_to_linear      = copy_yf_to_linear,
> +	.ys_to_linear      = NULL,               /* to be implemented */
> +},
> +};
> +
> +static int __gem_get_tiling(int fd, struct drm_i915_gem_get_tiling *arg)
> +{
> +	int err;
> +
> +	err = 0;
> +	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, arg))
> +		err = -errno;
> +	errno = 0;
> +
> +	return err;
> +}
> +
> +static bool __get_tiling(int fd, uint32_t handle, uint32_t *tiling,
> +			 uint32_t *swizzle)
> +{
> +	struct drm_i915_gem_get_tiling get_tiling;
> +
> +	memset(&get_tiling, 0, sizeof(get_tiling));
> +	get_tiling.handle = handle;
> +
> +	if (__gem_get_tiling(fd, &get_tiling) != 0)
> +		return false;
> +
> +	*tiling = get_tiling.tiling_mode;
> +	*swizzle = get_tiling.swizzle_mode;
> +
> +	return get_tiling.phys_swizzle_mode == get_tiling.swizzle_mode;
> +}
> +
> +static bool probe_hw_tiling(int fd, uint32_t tiling)
> +{
> +	struct drm_i915_gem_set_tiling st;
> +	uint64_t size = 1024 * 1024;
> +	uint32_t handle, buf_tiling, buf_swizzle;
> +	uint32_t stride;
> +	int ret;
> +	bool is_set;
> +
> +	if (tiling == I915_TILING_X)
> +		stride = 512;
> +	else if (tiling == I915_TILING_Y)
> +		stride = 128;
> +	else
> +		return false;
> +
> +	handle = gem_create(fd, size);
> +
> +	/* Single shot, if no fences are available we fail immediately */
> +	st.handle = handle;
> +	st.tiling_mode = tiling;
> +	st.stride = tiling ? stride : 0;
> +	ret = ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &st);
> +	if (ret)
> +		goto end;
> +
> +	is_set = __get_tiling(fd, handle, &buf_tiling, &buf_swizzle);
> +
> +end:
> +	gem_close(fd, handle);
> +
> +	return is_set;
> +}
> +
> +struct buf_ops *buf_ops_get(int fd, drm_intel_bufmgr *bufmgr)
> +{
> +	struct buf_ops *bops = calloc(1, sizeof(*bops));
> +	uint32_t devid;
> +	int generation;
> +
> +	igt_assert(bufmgr);
> +	igt_assert(bops);
> +
> +	devid = intel_get_drm_devid(fd);
> +	generation = intel_gen(devid);
> +
> +	/* Predefined settings */
> +	for (int i = 0; i < ARRAY_SIZE(buf_ops_arr); i++) {
> +		if (generation >= buf_ops_arr[i].gen_start &&
> +				generation <= buf_ops_arr[i].gen_end) {
> +			memcpy(bops, &buf_ops_arr[i], sizeof(*bops));
> +			bops->fd = fd;
> +			bops->bufmgr = bufmgr;
> +			bops->intel_gen = generation;
> +			igt_debug("generation: %d, supported tiles: 0x%02x\n",
> +				  generation, bops->supported_tiles);
> +			break;
> +		}
> +	}
> +
> +	/* Let's probe X and Y hw tiling support */
> +	if (bops->hw_tiles & TILE_X) {
> +		bool supported = probe_hw_tiling(fd, I915_TILING_X);
> +
> +		igt_debug("X fence support: %s\n", supported ? "yes" : "no");
> +		if (!supported) {
> +			bops->hw_tiles &= ~TILE_X;
> +			bops->linear_to_x = copy_linear_to_x;
> +			bops->x_to_linear = copy_x_to_linear;
> +		}
> +	}
> +
> +	if (bops->hw_tiles & TILE_Y) {
> +		bool supported = probe_hw_tiling(fd, I915_TILING_Y);
> +
> +		igt_debug("Y fence support: %s\n", supported ? "yes" : "no");
> +		if (!supported) {
> +			bops->hw_tiles &= ~TILE_Y;
> +			bops->linear_to_y = copy_linear_to_y;
> +			bops->y_to_linear = copy_y_to_linear;
> +		}
> +	}
> +
> +	igt_assert(bops->intel_gen);
> +
> +	return bops;
> +}
> +
> +void buf_ops_switch_to_sofware_tiling(struct buf_ops *bops)
so far so good :) first typo ^ s/sofware/software/
Check declaration too :)
> +{
> +	igt_debug("Switch to software tiling/detiling of X/Y surfaces\n");
> +
> +	igt_assert(bops);
> +
> +	bops->hw_tiles = 0;
> +	bops->linear_to_x = copy_linear_to_x;
> +	bops->linear_to_y = copy_linear_to_y;
> +	bops->x_to_linear = copy_x_to_linear;
> +	bops->y_to_linear = copy_y_to_linear;
> +}
> +
> +bool buf_ops_has_hw_fence(struct buf_ops *bops, uint32_t tiling)
> +{
> +	uint32_t tile_mask = (1 << tiling);
> +
> +	igt_assert(bops);
> +
> +	if (tile_mask & bops->hw_tiles)
> +		return true;
> +
> +	return false;
> +}
> +
> +bool buf_ops_has_tiling_support(struct buf_ops *bops, uint32_t tiling)
> +{
> +	uint32_t tile_mask = (1 << tiling);
> +
> +	igt_assert(bops);
> +
> +	if (tile_mask & bops->supported_tiles)
> +		return true;
> +
> +	return false;
> +}
> +
> +static int buf_aux_width(int gen, const struct igt_buf *buf)
> +{
> +	/*
> +	 * GEN12+: The AUX CCS unit size is 64 bytes mapping 4 main surface
> +	 * tiles. Thus the width of the CCS unit is 4*32=128 pixels on the
> +	 * main surface.
> +	 */
> +	if (gen >= 12)
> +		return DIV_ROUND_UP(igt_buf_width(buf), 128) * 64;
> +
> +	return DIV_ROUND_UP(igt_buf_width(buf), 1024) * 128;
> +}
> +
> +static int buf_aux_height(int gen, const struct igt_buf *buf)
> +{
> +	/*
> +	 * GEN12+: The AUX CCS unit size is 64 bytes mapping 4 main surface
> +	 * tiles. Thus the height of the CCS unit is 32 pixel rows on the main
> +	 * surface.
> +	 */
> +	if (gen >= 12)
> +		return DIV_ROUND_UP(igt_buf_height(buf), 32);
> +
> +	return DIV_ROUND_UP(igt_buf_height(buf), 512) * 32;
> +}
> +
> +void igt_buf_init(struct buf_ops *bops, struct igt_buf *buf,
> +		  int width, int height, int bpp,
> +		  uint32_t req_tiling, bool ccs)
> +{
> +	uint32_t tiling = req_tiling;
> +	bool supports_hw_fences;
> +
> +	igt_assert(bops);
> +
> +	supports_hw_fences = buf_ops_has_hw_fence(bops, req_tiling);
> +
> +	memset(buf, 0, sizeof(*buf));
> +
> +	if (ccs) {
> +		int aux_width, aux_height;
> +		int size;
> +
> +		igt_require(bops->intel_gen >= 9);
> +		igt_assert(req_tiling == I915_TILING_Y ||
> +			   req_tiling == I915_TILING_Yf);
> +
> +		/*
> +		 * On GEN12+ we align the main surface to 4 * 4 main surface
> +		 * tiles, which is 64kB. These 16 tiles are mapped by 4 AUX
> +		 * CCS units, that is 4 * 64 bytes. These 4 CCS units are in
> +		 * turn mapped by one L1 AUX page table entry.
> +		 */
> +		if (bops->intel_gen >= 12)
> +			buf->stride = ALIGN(width * (bpp / 8), 128 * 4);
> +		else
> +			buf->stride = ALIGN(width * (bpp / 8), 128);
> +
> +		if (bops->intel_gen >= 12)
> +			height = ALIGN(height, 4 * 32);
> +
> +		buf->size = buf->stride * height;
> +		buf->tiling = tiling;
> +		buf->bpp = bpp;
> +
> +		aux_width = buf_aux_width(bops->intel_gen, buf);
> +		aux_height = buf_aux_height(bops->intel_gen, buf);
> +
> +		buf->aux.offset = buf->stride * ALIGN(height, 32);
> +		buf->aux.stride = aux_width;
> +
> +		size = buf->aux.offset + aux_width * aux_height;
> +
> +		buf->bo = drm_intel_bo_alloc(bops->bufmgr, "", size, 4096);
> +
> +		if (tiling == I915_TILING_Y && supports_hw_fences) {
> +			drm_intel_bo_set_tiling(buf->bo, &tiling, buf->stride);
> +			igt_assert_eq(tiling, req_tiling);
> +		}
> +	} else {
> +		/* Requested bo must be hw tiled */
> +		if (supports_hw_fences) {
> +			unsigned long pitch;
> +
> +			buf->bo = drm_intel_bo_alloc_tiled(bops->bufmgr, "",
> +							   width, height,
> +							   bpp / 8,
> +							   &tiling, &pitch, 0);
> +			igt_assert_eq(tiling, req_tiling);
> +			igt_assert(buf->bo);
> +
> +			buf->stride = pitch;
> +			buf->tiling = tiling;
> +			buf->size = pitch * height;
> +			buf->bpp = bpp;
> +		} else {
> +			/* Use bo alloc and software tiling/detiling */
> +			int size;
> +
> +			buf->stride = ALIGN(width * (bpp / 8), 128);
> +			buf->size = buf->stride * height;
> +			buf->tiling = tiling;
> +			buf->bpp = bpp;
> +
> +			size = buf->stride * ALIGN(height, 32);
> +
> +			buf->bo = drm_intel_bo_alloc(bops->bufmgr, "", size,
> +						     4096);
> +			igt_assert(buf->bo);
> +		}
> +	}
> +}
> diff --git a/lib/intel_bufops.h b/lib/intel_bufops.h
> new file mode 100644
> index 00000000..e53c6ebc
> --- /dev/null
> +++ b/lib/intel_bufops.h
> @@ -0,0 +1,24 @@
> +#ifndef __INTEL_BUFOPS_H__
> +#define __INTEL_BUFOPS_H__
> +
> +#include "intel_batchbuffer.h"
> +
> +struct buf_ops;
> +
> +struct buf_ops *buf_ops_get(int fd, drm_intel_bufmgr *bufmgr);
> +void buf_ops_switch_to_sofware_tiling(struct buf_ops *bops);
> +
> +void copy_buf_to_linear(struct buf_ops *bops, struct igt_buf *buf,
> +			uint32_t *linear);
> +
> +void copy_linear_to_buf(struct buf_ops *bops, struct igt_buf *buf,
> +			uint32_t *linear);
> +
> +bool buf_ops_has_hw_fence(struct buf_ops *bops, uint32_t tiling);
> +bool buf_ops_has_tiling_support(struct buf_ops *bops, uint32_t tiling);
> +
> +void igt_buf_init(struct buf_ops *bops, struct igt_buf *buf,
> +		  int width, int height, int bpp,
> +		  uint32_t req_tiling, bool ccs);
> +
> +#endif
> diff --git a/lib/meson.build b/lib/meson.build
> index 3f908912..a88c3e89 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -26,6 +26,7 @@ lib_sources = [
>  	'igt_x86.c',
>  	'instdone.c',
>  	'intel_batchbuffer.c',
> +	'intel_bufops.c',
>  	'intel_chipset.c',
>  	'intel_device_info.c',
>  	'intel_os.c',
> -- 
> 2.23.0
>
Huge and quite important functions introduced!
Kasia
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations
  2019-12-03  9:25 ` [igt-dev] [PATCH i-g-t v2 1/2] " Katarzyna Dec
@ 2019-12-03  9:41   ` Katarzyna Dec
  2019-12-03 17:05   ` Zbigniew Kempczyński
  1 sibling, 0 replies; 8+ messages in thread
From: Katarzyna Dec @ 2019-12-03  9:41 UTC (permalink / raw)
  To: Zbigniew Kempczyński, igt-dev

On Tue, Dec 03, 2019 at 10:25:29AM +0100, Katarzyna Dec wrote:
> On Sun, Dec 01, 2019 at 08:09:41PM +0100, Zbigniew Kempczyński wrote:
> > Different GENs supports different tile surfaces. Older GENs
> > have HW fences to allow X / Y surface tiling / detiling.
> > Newer GENs have to tile / detile such surface in software.
> > 
> > To make test developer life easier this code adds buffer
> > operations (short bufops) to use appropriate functions allowing
> > copying linear buffer to BO and from BO to linear buffer
> > regardless GPU generation and tiling within BO. For GENs having
> > fences support preference is to use them if they are available
> > (X / Y tiling is probed on bufops initalization).
> > 
> > Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
> > Cc: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Imre Deak <imre.deak@intel.com>
> > Cc: Katarzyna Dec <katarzyna.dec@intel.com>
> > ---
> >  lib/Makefile.sources |   2 +
> >  lib/intel_bufops.c   | 689 +++++++++++++++++++++++++++++++++++++++++++
> >  lib/intel_bufops.h   |  24 ++
> >  lib/meson.build      |   1 +
> >  4 files changed, 716 insertions(+)
> >  create mode 100644 lib/intel_bufops.c
> >  create mode 100644 lib/intel_bufops.h
> > 
> > diff --git a/lib/Makefile.sources b/lib/Makefile.sources
> > index 9d1a4e06..b808f294 100644
> > --- a/lib/Makefile.sources
> > +++ b/lib/Makefile.sources
> > @@ -65,6 +65,8 @@ lib_source_list =	 	\
> >  	intel_aub.h		\
> >  	intel_batchbuffer.c	\
> >  	intel_batchbuffer.h	\
> > +	intel_bufops.c		\
> > +	intel_bufops.h		\
> >  	intel_chipset.c		\
> >  	intel_chipset.h		\
> >  	intel_device_info.c	\
> > diff --git a/lib/intel_bufops.c b/lib/intel_bufops.c
> > new file mode 100644
> > index 00000000..fdb8bdc7
> > --- /dev/null
> > +++ b/lib/intel_bufops.c
> > @@ -0,0 +1,689 @@
> > +#include <sys/ioctl.h>
> > +#include "igt.h"
> > +#include "igt_x86.h"
> > +#include "intel_bufops.h"
> > +
> > +#define TILE_NONE   (1 << I915_TILING_NONE)
> > +#define TILE_X      (1 << I915_TILING_X)
> > +#define TILE_Y      (1 << I915_TILING_Y)
> > +#define TILE_Yf     (1 << I915_TILING_Yf)
> > +#define TILE_Ys     (1 << I915_TILING_Ys)
> > +
> > +typedef void (*bo_copy)(int, struct igt_buf *, uint32_t *);
> > +
> > +struct buf_ops {
> > +	int fd;
> > +	drm_intel_bufmgr *bufmgr;
> > +	int gen_start;
> > +	int gen_end;
> > +	int intel_gen;
> > +	uint32_t supported_tiles;
> > +	uint32_t hw_tiles;
> > +	bo_copy linear_to;
> > +	bo_copy linear_to_x;
> > +	bo_copy linear_to_y;
> > +	bo_copy linear_to_yf;
> > +	bo_copy linear_to_ys;
> > +	bo_copy to_linear;
> > +	bo_copy x_to_linear;
> > +	bo_copy y_to_linear;
> > +	bo_copy yf_to_linear;
> > +	bo_copy ys_to_linear;
> > +};
> > +
> > +static void *x_ptr(void *ptr,
> > +		   unsigned int x, unsigned int y,
> > +		   unsigned int stride, unsigned int cpp)
> > +{
> > +	const int tile_width = 512;
> > +	const int tile_height = 8;
> It can be really silly question - are these ^ values always the same?
> > +	const int tile_size = tile_width * tile_height;
> > +	int tile_x, tile_y;
> > +	int offset_x, offset_y, pos;
> > +
> > +	x *= cpp;
> > +	tile_x = x / tile_width;
> > +	tile_y = y / tile_height;
> > +	offset_x = (tile_x * tile_size);
> > +	offset_y = (tile_y * stride * tile_height);
> > +
> > +	pos = offset_y + offset_x +
> > +			(y % tile_height * tile_width) + (x % tile_width);
> > +
> > +	return ptr + pos;
> > +}
> > +
> > +static void *y_ptr(void *ptr,
> > +		   unsigned int x, unsigned int y,
> > +		   unsigned int stride, unsigned int cpp)
> > +{
> > +	const int tile_width = 128;
> > +	const int tile_height = 32;
> > +	const int owords = 16;
> Similar question. I guess this is something specific either to Intel Gen or to
> testcases.
> > +	const int tile_size = tile_width * tile_height;
> > +	int tile_x, tile_y;
> > +	int offset_x, offset_y, pos;
> > +	int shift_x, shift_y;
> > +
> > +	x *= cpp;
> > +	tile_x = x / tile_width;
> > +	tile_y = y / tile_height;
> > +	offset_x = tile_x * tile_size;
> > +	offset_y = tile_y * stride * tile_height;
> > +	shift_x = x % owords + (x % tile_width) / owords * tile_width * cpp;
> > +	shift_y = y % tile_height * owords;
> > +
> > +	pos = offset_y + offset_x + shift_x + shift_y;
> > +
> > +	return ptr + pos;
> > +}
> > +
> > +static void *yf_ptr(void *ptr,
> > +		    unsigned int x, unsigned int y,
> > +		    unsigned int stride, unsigned int cpp)
> > +{
> > +	const int tile_size = 4 * 1024;
> > +	const int tile_width = 128;
> > +	int row_size = (stride / tile_width) * tile_size;
> > +
> > +	x *= cpp; /* convert to Byte offset */
> > +
> > +
> > +	/*
> > +	 * Within a 4k Yf tile, the byte swizzling pattern is
> > +	 * msb......lsb
> > +	 * xyxyxyyyxxxx
> > +	 * The tiles themselves are laid out in row major order.
> > +	 */
> > +	return ptr +
> > +			((x & 0xf) * 1) + /* 4x1 pixels(32bpp) = 16B */
> > +			((y & 0x3) * 16) + /* 4x4 pixels = 64B */
> > +			(((y & 0x4) >> 2) * 64) + /* 1x2 64B blocks */
> > +			(((x & 0x10) >> 4) * 128) + /* 2x2 64B blocks = 256B block */
> > +			(((y & 0x8) >> 3) * 256) + /* 2x1 256B blocks */
> > +			(((x & 0x20) >> 5) * 512) + /* 2x2 256B blocks */
> > +			(((y & 0x10) >> 4) * 1024) + /* 4x2 256 blocks */
> > +			(((x & 0x40) >> 6) * 2048) + /* 4x4 256B blocks = 4k tile */
> > +			(((x & ~0x7f) >> 7) * tile_size) + /* row of tiles */
> > +			(((y & ~0x1f) >> 5) * row_size);
> > +}
> > +
> > +typedef void *(*fn_ptr)(void *, unsigned int, unsigned int,
> > +			unsigned int, unsigned int);
> > +static fn_ptr __get_tile_fn_ptr(int tiling)
> > +{
> > +	fn_ptr fn = NULL;
> > +
> > +	switch (tiling) {
> > +	case I915_TILING_X:
> > +		fn = x_ptr;
> > +		break;
> > +	case I915_TILING_Y:
> > +		fn = y_ptr;
> > +		break;
> > +	case I915_TILING_Yf:
> > +		fn = yf_ptr;
> > +		break;
> > +	case I915_TILING_Ys:
> > +		/* To be implemented */
> > +		break;
> > +	}
> > +
> > +	igt_assert_f(fn, "Can't find tile function for tiling: %d\n", tiling);
> > +
> > +	return fn;
> > +}
> > +
> > +static void __copy_linear_to(int fd, struct igt_buf *buf,
> > +			     const uint32_t *linear, int tiling)
> > +{
> > +	int height = igt_buf_height(buf);
> > +	int width = igt_buf_width(buf);
> > +	fn_ptr fn = __get_tile_fn_ptr(tiling);
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
> > +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> > +			    buf->bo->size, PROT_READ | PROT_WRITE);
> > +
> > +	for (int y = 0; y < height; y++) {
> > +		for (int x = 0; x < width; x++) {
> > +			uint32_t *ptr = fn(map, x, y,
> > +					   buf->stride, buf->bpp / 8);
> > +
> > +			*ptr = linear[y * width + x];
> > +		}
> > +	}
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_linear_to_x(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear)
> > +{
> > +	__copy_linear_to(fd, buf, linear, I915_TILING_X);
> > +}
> > +
> > +static void copy_linear_to_y(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear)
> > +{
> > +	__copy_linear_to(fd, buf, linear, I915_TILING_Y);
> > +}
> > +
> > +static void copy_linear_to_yf(int fd, struct igt_buf *buf,
> > +			      uint32_t *linear)
> > +{
> > +	__copy_linear_to(fd, buf, linear, I915_TILING_Yf);
> > +}
> > +
> > +static void __copy_to_linear(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear, int tiling)
> > +{
> > +	int height = igt_buf_height(buf);
> > +	int width = igt_buf_width(buf);
> > +	fn_ptr fn = __get_tile_fn_ptr(tiling);
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_CPU, 0);
> > +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> > +			    buf->bo->size, PROT_READ);
> > +
> > +	for (int y = 0; y < height; y++) {
> > +		for (int x = 0; x < width; x++) {
> > +			uint32_t *ptr = fn(map, x, y,
> > +					   buf->stride, buf->bpp / 8);
> > +
> > +			linear[y * width + x] = *ptr;
> > +		}
> > +	}
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_yf_to_linear(int fd, struct igt_buf *buf,
> > +			      uint32_t *linear)
> > +{
> > +	__copy_to_linear(fd, buf, linear, I915_TILING_Yf);
> > +}
> > +
> > +static void copy_x_to_linear(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear)
> > +{
> > +	__copy_to_linear(fd, buf, linear, I915_TILING_X);
> > +}
> > +
> > +static void copy_y_to_linear(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear)
> > +{
> > +	__copy_to_linear(fd, buf, linear, I915_TILING_Y);
> > +}
> > +
> > +static void copy_linear_to_gtt(int fd, struct igt_buf *buf,
> > +			       uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> > +
> > +	map = gem_mmap__gtt(fd, buf->bo->handle,
> > +			    buf->bo->size, PROT_READ | PROT_WRITE);
> > +
> > +	memcpy(map, linear, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_gtt_to_linear(int fd, struct igt_buf *buf,
> > +			       uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_GTT, 0);
> > +
> > +	map = gem_mmap__gtt(fd, buf->bo->handle,
> > +			    buf->bo->size, PROT_READ);
> > +
> > +	igt_memcpy_from_wc(linear, map, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_linear_to_wc(int fd, struct igt_buf *buf,
> > +			      uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> > +
> > +	map = gem_mmap__wc(fd, buf->bo->handle, 0,
> > +			   buf->bo->size, PROT_READ | PROT_WRITE);
> > +
> > +	memcpy(map, linear, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_wc_to_linear(int fd, struct igt_buf *buf,
> > +			      uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_GTT, 0);
> > +
> > +	map = gem_mmap__wc(fd, buf->bo->handle, 0,
> > +			   buf->bo->size, PROT_READ);
> > +
> > +	igt_memcpy_from_wc(linear, map, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_linear_to_cpu(int fd, struct igt_buf *buf,
> > +			       uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
> > +
> > +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> > +			    buf->bo->size, PROT_READ | PROT_WRITE);
> > +
> > +	memcpy(map, linear, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_cpu_to_linear(int fd, struct igt_buf *buf,
> > +			       uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_CPU, 0);
> > +
> > +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> > +			    buf->bo->size, PROT_READ);
> > +
> > +	memcpy(linear, map, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +void copy_buf_to_linear(struct buf_ops *bops, struct igt_buf *buf,
> > +			uint32_t *linear)
> > +{
> > +	igt_assert(bops);
> > +
> > +	switch (buf->tiling) {
> > +	case I915_TILING_NONE:
> > +		igt_assert(bops->to_linear);
> > +		bops->to_linear(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_X:
> > +		igt_assert(bops->x_to_linear);
> > +		bops->x_to_linear(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Y:
> > +		igt_assert(bops->y_to_linear);
> > +		bops->y_to_linear(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Yf:
> > +		igt_assert(bops->yf_to_linear);
> > +		bops->yf_to_linear(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Ys:
> > +		igt_assert(bops->ys_to_linear);
> > +		bops->ys_to_linear(bops->fd, buf, linear);
> > +		break;
> > +	}
> > +}
> > +
> > +void copy_linear_to_buf(struct buf_ops *bops, struct igt_buf *buf,
> > +			uint32_t *linear)
> > +{
> > +	igt_assert(bops);
> > +
> > +	switch (buf->tiling) {
> > +	case I915_TILING_NONE:
> > +		igt_assert(bops->linear_to);
> > +		bops->linear_to(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_X:
> > +		igt_assert(bops->linear_to_x);
> > +		bops->linear_to_x(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Y:
> > +		igt_assert(bops->linear_to_y);
> > +		bops->linear_to_y(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Yf:
> > +		igt_assert(bops->linear_to_yf);
> > +		bops->linear_to_yf(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Ys:
> > +		igt_assert(bops->linear_to_ys);
> > +		bops->linear_to_ys(bops->fd, buf, linear);
> > +		break;
> > +	}
> > +}
> > +
> > +struct buf_ops buf_ops_arr[] = {
> > +	/* Generations 0 - 8 */
> > +{
> > +	.gen_start         = 0,
> > +	.gen_end           = 8,
> > +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y,
> > +	.hw_tiles          = TILE_X | TILE_Y,
> > +	.linear_to         = copy_linear_to_cpu,
> > +	.linear_to_x       = copy_linear_to_gtt,
> > +	.linear_to_y       = copy_linear_to_gtt,
> > +	.to_linear         = copy_cpu_to_linear,
> > +	.x_to_linear       = copy_gtt_to_linear,
> > +	.y_to_linear       = copy_gtt_to_linear,
> > +},
> > +/* Generations 9 - 11 */
> > +{
> > +	.gen_start         = 9,
> > +	.gen_end           = 11,
> > +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf,
> > +	.hw_tiles          = TILE_X | TILE_Y,
> > +	.linear_to         = copy_linear_to_cpu,
> > +	.linear_to_x       = copy_linear_to_gtt,
> > +	.linear_to_y       = copy_linear_to_gtt,
> > +	.linear_to_yf      = copy_linear_to_yf,
> > +	.to_linear         = copy_cpu_to_linear,
> > +	.x_to_linear       = copy_gtt_to_linear,
> > +	.y_to_linear       = copy_gtt_to_linear,
> > +	.yf_to_linear      = copy_yf_to_linear,
> > +},
> > +/* Generation 12 */
> > +{
> > +	.gen_start         = 12,
> > +	.gen_end           = 12,
> > +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf | TILE_Ys,
> > +	.linear_to         = copy_linear_to_wc,
> > +	.linear_to_x       = copy_linear_to_x,
> > +	.linear_to_y       = copy_linear_to_y,
> > +	.linear_to_yf      = copy_linear_to_yf,
> > +	.linear_to_ys      = NULL,               /* to be implemented */
> > +	.to_linear         = copy_wc_to_linear,
> > +	.x_to_linear       = copy_x_to_linear,
> > +	.y_to_linear       = copy_y_to_linear,
> > +	.yf_to_linear      = copy_yf_to_linear,
> > +	.ys_to_linear      = NULL,               /* to be implemented */
> > +},
> > +};
> > +
> > +static int __gem_get_tiling(int fd, struct drm_i915_gem_get_tiling *arg)
> > +{
> > +	int err;
> > +
> > +	err = 0;
> > +	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, arg))
> > +		err = -errno;
> > +	errno = 0;
> > +
> > +	return err;
> > +}
> > +
> > +static bool __get_tiling(int fd, uint32_t handle, uint32_t *tiling,
> > +			 uint32_t *swizzle)
> > +{
> > +	struct drm_i915_gem_get_tiling get_tiling;
> > +
> > +	memset(&get_tiling, 0, sizeof(get_tiling));
> > +	get_tiling.handle = handle;
> > +
> > +	if (__gem_get_tiling(fd, &get_tiling) != 0)
> > +		return false;
> > +
> > +	*tiling = get_tiling.tiling_mode;
> > +	*swizzle = get_tiling.swizzle_mode;
> > +
> > +	return get_tiling.phys_swizzle_mode == get_tiling.swizzle_mode;
> > +}
> > +
> > +static bool probe_hw_tiling(int fd, uint32_t tiling)
> > +{
> > +	struct drm_i915_gem_set_tiling st;
> > +	uint64_t size = 1024 * 1024;
> > +	uint32_t handle, buf_tiling, buf_swizzle;
> > +	uint32_t stride;
> > +	int ret;
> > +	bool is_set;
> > +
> > +	if (tiling == I915_TILING_X)
> > +		stride = 512;
> > +	else if (tiling == I915_TILING_Y)
> > +		stride = 128;
> > +	else
> > +		return false;
> > +
> > +	handle = gem_create(fd, size);
> > +
> > +	/* Single shot, if no fences are available we fail immediately */
> > +	st.handle = handle;
> > +	st.tiling_mode = tiling;
> > +	st.stride = tiling ? stride : 0;
> > +	ret = ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &st);
> > +	if (ret)
> > +		goto end;
> > +
> > +	is_set = __get_tiling(fd, handle, &buf_tiling, &buf_swizzle);
> > +
> > +end:
> > +	gem_close(fd, handle);
> > +
> > +	return is_set;
> > +}
> > +
> > +struct buf_ops *buf_ops_get(int fd, drm_intel_bufmgr *bufmgr)
> > +{
> > +	struct buf_ops *bops = calloc(1, sizeof(*bops));
> > +	uint32_t devid;
> > +	int generation;
> > +
> > +	igt_assert(bufmgr);
> > +	igt_assert(bops);
> > +
> > +	devid = intel_get_drm_devid(fd);
> > +	generation = intel_gen(devid);
> > +
> > +	/* Predefined settings */
> > +	for (int i = 0; i < ARRAY_SIZE(buf_ops_arr); i++) {
> > +		if (generation >= buf_ops_arr[i].gen_start &&
> > +				generation <= buf_ops_arr[i].gen_end) {
> > +			memcpy(bops, &buf_ops_arr[i], sizeof(*bops));
> > +			bops->fd = fd;
> > +			bops->bufmgr = bufmgr;
> > +			bops->intel_gen = generation;
> > +			igt_debug("generation: %d, supported tiles: 0x%02x\n",
> > +				  generation, bops->supported_tiles);
> > +			break;
> > +		}
> > +	}
> > +
> > +	/* Let's probe X and Y hw tiling support */
> > +	if (bops->hw_tiles & TILE_X) {
> > +		bool supported = probe_hw_tiling(fd, I915_TILING_X);
> > +
> > +		igt_debug("X fence support: %s\n", supported ? "yes" : "no");
> > +		if (!supported) {
> > +			bops->hw_tiles &= ~TILE_X;
> > +			bops->linear_to_x = copy_linear_to_x;
> > +			bops->x_to_linear = copy_x_to_linear;
> > +		}
> > +	}
> > +
> > +	if (bops->hw_tiles & TILE_Y) {
> > +		bool supported = probe_hw_tiling(fd, I915_TILING_Y);
> > +
> > +		igt_debug("Y fence support: %s\n", supported ? "yes" : "no");
> > +		if (!supported) {
> > +			bops->hw_tiles &= ~TILE_Y;
> > +			bops->linear_to_y = copy_linear_to_y;
> > +			bops->y_to_linear = copy_y_to_linear;
> > +		}
> > +	}
> > +
> > +	igt_assert(bops->intel_gen);
> > +
> > +	return bops;
> > +}
> > +
> > +void buf_ops_switch_to_sofware_tiling(struct buf_ops *bops)
> so far so good :) first typo ^ s/sofware/software/
> Check declaration too :)
> > +{
> > +	igt_debug("Switch to software tiling/detiling of X/Y surfaces\n");
> > +
> > +	igt_assert(bops);
> > +
> > +	bops->hw_tiles = 0;
> > +	bops->linear_to_x = copy_linear_to_x;
> > +	bops->linear_to_y = copy_linear_to_y;
> > +	bops->x_to_linear = copy_x_to_linear;
> > +	bops->y_to_linear = copy_y_to_linear;
> > +}
> > +
> > +bool buf_ops_has_hw_fence(struct buf_ops *bops, uint32_t tiling)
> > +{
> > +	uint32_t tile_mask = (1 << tiling);
> > +
> > +	igt_assert(bops);
> > +
> > +	if (tile_mask & bops->hw_tiles)
> > +		return true;
> > +
> > +	return false;
> > +}
> > +
> > +bool buf_ops_has_tiling_support(struct buf_ops *bops, uint32_t tiling)
> > +{
> > +	uint32_t tile_mask = (1 << tiling);
> > +
> > +	igt_assert(bops);
> > +
> > +	if (tile_mask & bops->supported_tiles)
> > +		return true;
> > +
> > +	return false;
> > +}
> > +
> > +static int buf_aux_width(int gen, const struct igt_buf *buf)
Similar fuctions (buf_aux_height) as well are still in
tests/i915/gem_render_copy . Is it by purpose?
And it looks like these 2 ^ v are only used in lib while could be used in test
functions. 

BTW - finally we have someone who wants to make life easier with rendercopy.
Kasia :)
> > +{
> > +	/*
> > +	 * GEN12+: The AUX CCS unit size is 64 bytes mapping 4 main surface
> > +	 * tiles. Thus the width of the CCS unit is 4*32=128 pixels on the
> > +	 * main surface.
> > +	 */
> > +	if (gen >= 12)
> > +		return DIV_ROUND_UP(igt_buf_width(buf), 128) * 64;
> > +
> > +	return DIV_ROUND_UP(igt_buf_width(buf), 1024) * 128;
> > +}
> > +
> > +static int buf_aux_height(int gen, const struct igt_buf *buf)
> > +{
> > +	/*
> > +	 * GEN12+: The AUX CCS unit size is 64 bytes mapping 4 main surface
> > +	 * tiles. Thus the height of the CCS unit is 32 pixel rows on the main
> > +	 * surface.
> > +	 */
> > +	if (gen >= 12)
> > +		return DIV_ROUND_UP(igt_buf_height(buf), 32);
> > +
> > +	return DIV_ROUND_UP(igt_buf_height(buf), 512) * 32;
> > +}
> > +
> > +void igt_buf_init(struct buf_ops *bops, struct igt_buf *buf,
> > +		  int width, int height, int bpp,
> > +		  uint32_t req_tiling, bool ccs)
> > +{
> > +	uint32_t tiling = req_tiling;
> > +	bool supports_hw_fences;
> > +
> > +	igt_assert(bops);
> > +
> > +	supports_hw_fences = buf_ops_has_hw_fence(bops, req_tiling);
> > +
> > +	memset(buf, 0, sizeof(*buf));
> > +
> > +	if (ccs) {
> > +		int aux_width, aux_height;
> > +		int size;
> > +
> > +		igt_require(bops->intel_gen >= 9);
> > +		igt_assert(req_tiling == I915_TILING_Y ||
> > +			   req_tiling == I915_TILING_Yf);
> > +
> > +		/*
> > +		 * On GEN12+ we align the main surface to 4 * 4 main surface
> > +		 * tiles, which is 64kB. These 16 tiles are mapped by 4 AUX
> > +		 * CCS units, that is 4 * 64 bytes. These 4 CCS units are in
> > +		 * turn mapped by one L1 AUX page table entry.
> > +		 */
> > +		if (bops->intel_gen >= 12)
> > +			buf->stride = ALIGN(width * (bpp / 8), 128 * 4);
> > +		else
> > +			buf->stride = ALIGN(width * (bpp / 8), 128);
> > +
> > +		if (bops->intel_gen >= 12)
> > +			height = ALIGN(height, 4 * 32);
> > +
> > +		buf->size = buf->stride * height;
> > +		buf->tiling = tiling;
> > +		buf->bpp = bpp;
> > +
> > +		aux_width = buf_aux_width(bops->intel_gen, buf);
> > +		aux_height = buf_aux_height(bops->intel_gen, buf);
> > +
> > +		buf->aux.offset = buf->stride * ALIGN(height, 32);
> > +		buf->aux.stride = aux_width;
> > +
> > +		size = buf->aux.offset + aux_width * aux_height;
> > +
> > +		buf->bo = drm_intel_bo_alloc(bops->bufmgr, "", size, 4096);
> > +
> > +		if (tiling == I915_TILING_Y && supports_hw_fences) {
> > +			drm_intel_bo_set_tiling(buf->bo, &tiling, buf->stride);
> > +			igt_assert_eq(tiling, req_tiling);
> > +		}
> > +	} else {
> > +		/* Requested bo must be hw tiled */
> > +		if (supports_hw_fences) {
> > +			unsigned long pitch;
> > +
> > +			buf->bo = drm_intel_bo_alloc_tiled(bops->bufmgr, "",
> > +							   width, height,
> > +							   bpp / 8,
> > +							   &tiling, &pitch, 0);
> > +			igt_assert_eq(tiling, req_tiling);
> > +			igt_assert(buf->bo);
> > +
> > +			buf->stride = pitch;
> > +			buf->tiling = tiling;
> > +			buf->size = pitch * height;
> > +			buf->bpp = bpp;
> > +		} else {
> > +			/* Use bo alloc and software tiling/detiling */
> > +			int size;
> > +
> > +			buf->stride = ALIGN(width * (bpp / 8), 128);
> > +			buf->size = buf->stride * height;
> > +			buf->tiling = tiling;
> > +			buf->bpp = bpp;
> > +
> > +			size = buf->stride * ALIGN(height, 32);
> > +
> > +			buf->bo = drm_intel_bo_alloc(bops->bufmgr, "", size,
> > +						     4096);
> > +			igt_assert(buf->bo);
> > +		}
> > +	}
> > +}
> > diff --git a/lib/intel_bufops.h b/lib/intel_bufops.h
> > new file mode 100644
> > index 00000000..e53c6ebc
> > --- /dev/null
> > +++ b/lib/intel_bufops.h
> > @@ -0,0 +1,24 @@
> > +#ifndef __INTEL_BUFOPS_H__
> > +#define __INTEL_BUFOPS_H__
> > +
> > +#include "intel_batchbuffer.h"
> > +
> > +struct buf_ops;
> > +
> > +struct buf_ops *buf_ops_get(int fd, drm_intel_bufmgr *bufmgr);
> > +void buf_ops_switch_to_sofware_tiling(struct buf_ops *bops);
> > +
> > +void copy_buf_to_linear(struct buf_ops *bops, struct igt_buf *buf,
> > +			uint32_t *linear);
> > +
> > +void copy_linear_to_buf(struct buf_ops *bops, struct igt_buf *buf,
> > +			uint32_t *linear);
> > +
> > +bool buf_ops_has_hw_fence(struct buf_ops *bops, uint32_t tiling);
> > +bool buf_ops_has_tiling_support(struct buf_ops *bops, uint32_t tiling);
> > +
> > +void igt_buf_init(struct buf_ops *bops, struct igt_buf *buf,
> > +		  int width, int height, int bpp,
> > +		  uint32_t req_tiling, bool ccs);
> > +
> > +#endif
> > diff --git a/lib/meson.build b/lib/meson.build
> > index 3f908912..a88c3e89 100644
> > --- a/lib/meson.build
> > +++ b/lib/meson.build
> > @@ -26,6 +26,7 @@ lib_sources = [
> >  	'igt_x86.c',
> >  	'instdone.c',
> >  	'intel_batchbuffer.c',
> > +	'intel_bufops.c',
> >  	'intel_chipset.c',
> >  	'intel_device_info.c',
> >  	'intel_os.c',
> > -- 
> > 2.23.0
> >
> Huge and quite important functions introduced!
> Kasia
> _______________________________________________
> igt-dev mailing list
> igt-dev@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/igt-dev
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations
  2019-12-03  9:25 ` [igt-dev] [PATCH i-g-t v2 1/2] " Katarzyna Dec
  2019-12-03  9:41   ` Katarzyna Dec
@ 2019-12-03 17:05   ` Zbigniew Kempczyński
  2019-12-03 17:46     ` Ville Syrjälä
  1 sibling, 1 reply; 8+ messages in thread
From: Zbigniew Kempczyński @ 2019-12-03 17:05 UTC (permalink / raw)
  To: Katarzyna Dec; +Cc: igt-dev

On Tue, Dec 03, 2019 at 10:25:29AM +0100, Katarzyna Dec wrote:

<cut>
> > +static void *x_ptr(void *ptr,
> > +		   unsigned int x, unsigned int y,
> > +		   unsigned int stride, unsigned int cpp)
> > +{
> > +	const int tile_width = 512;
> > +	const int tile_height = 8;
> It can be really silly question - are these ^ values always the same?

Yes.

> > +	const int tile_size = tile_width * tile_height;
> > +	int tile_x, tile_y;
> > +	int offset_x, offset_y, pos;
> > +
> > +	x *= cpp;
> > +	tile_x = x / tile_width;
> > +	tile_y = y / tile_height;
> > +	offset_x = (tile_x * tile_size);
> > +	offset_y = (tile_y * stride * tile_height);
> > +
> > +	pos = offset_y + offset_x +
> > +			(y % tile_height * tile_width) + (x % tile_width);
> > +
> > +	return ptr + pos;
> > +}
> > +
> > +static void *y_ptr(void *ptr,
> > +		   unsigned int x, unsigned int y,
> > +		   unsigned int stride, unsigned int cpp)
> > +{
> > +	const int tile_width = 128;
> > +	const int tile_height = 32;
> > +	const int owords = 16;
> Similar question. I guess this is something specific either to Intel Gen or to
> testcases.

Tile-n where n is X/Y/Yf/Ys/... describe data placement algorithms
to be CPU/GPU cache-friendly. 

> > +	const int tile_size = tile_width * tile_height;
> > +	int tile_x, tile_y;
> > +	int offset_x, offset_y, pos;
> > +	int shift_x, shift_y;
> > +
> > +	x *= cpp;
> > +	tile_x = x / tile_width;
> > +	tile_y = y / tile_height;
> > +	offset_x = tile_x * tile_size;
> > +	offset_y = tile_y * stride * tile_height;
> > +	shift_x = x % owords + (x % tile_width) / owords * tile_width * cpp;
> > +	shift_y = y % tile_height * owords;
> > +
> > +	pos = offset_y + offset_x + shift_x + shift_y;
> > +
> > +	return ptr + pos;
> > +}
> > +
> > +static void *yf_ptr(void *ptr,
> > +		    unsigned int x, unsigned int y,
> > +		    unsigned int stride, unsigned int cpp)
> > +{
> > +	const int tile_size = 4 * 1024;
> > +	const int tile_width = 128;
> > +	int row_size = (stride / tile_width) * tile_size;
> > +
> > +	x *= cpp; /* convert to Byte offset */
> > +
> > +
> > +	/*
> > +	 * Within a 4k Yf tile, the byte swizzling pattern is
> > +	 * msb......lsb
> > +	 * xyxyxyyyxxxx
> > +	 * The tiles themselves are laid out in row major order.
> > +	 */
> > +	return ptr +
> > +			((x & 0xf) * 1) + /* 4x1 pixels(32bpp) = 16B */
> > +			((y & 0x3) * 16) + /* 4x4 pixels = 64B */
> > +			(((y & 0x4) >> 2) * 64) + /* 1x2 64B blocks */
> > +			(((x & 0x10) >> 4) * 128) + /* 2x2 64B blocks = 256B block */
> > +			(((y & 0x8) >> 3) * 256) + /* 2x1 256B blocks */
> > +			(((x & 0x20) >> 5) * 512) + /* 2x2 256B blocks */
> > +			(((y & 0x10) >> 4) * 1024) + /* 4x2 256 blocks */
> > +			(((x & 0x40) >> 6) * 2048) + /* 4x4 256B blocks = 4k tile */
> > +			(((x & ~0x7f) >> 7) * tile_size) + /* row of tiles */
> > +			(((y & ~0x1f) >> 5) * row_size);
> > +}
> > +
> > +typedef void *(*fn_ptr)(void *, unsigned int, unsigned int,
> > +			unsigned int, unsigned int);
> > +static fn_ptr __get_tile_fn_ptr(int tiling)
> > +{
> > +	fn_ptr fn = NULL;
> > +
> > +	switch (tiling) {
> > +	case I915_TILING_X:
> > +		fn = x_ptr;
> > +		break;
> > +	case I915_TILING_Y:
> > +		fn = y_ptr;
> > +		break;
> > +	case I915_TILING_Yf:
> > +		fn = yf_ptr;
> > +		break;
> > +	case I915_TILING_Ys:
> > +		/* To be implemented */
> > +		break;
> > +	}
> > +
> > +	igt_assert_f(fn, "Can't find tile function for tiling: %d\n", tiling);
> > +
> > +	return fn;
> > +}
> > +
> > +static void __copy_linear_to(int fd, struct igt_buf *buf,
> > +			     const uint32_t *linear, int tiling)
> > +{
> > +	int height = igt_buf_height(buf);
> > +	int width = igt_buf_width(buf);
> > +	fn_ptr fn = __get_tile_fn_ptr(tiling);
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
> > +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> > +			    buf->bo->size, PROT_READ | PROT_WRITE);
> > +
> > +	for (int y = 0; y < height; y++) {
> > +		for (int x = 0; x < width; x++) {
> > +			uint32_t *ptr = fn(map, x, y,
> > +					   buf->stride, buf->bpp / 8);
> > +
> > +			*ptr = linear[y * width + x];
> > +		}
> > +	}
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_linear_to_x(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear)
> > +{
> > +	__copy_linear_to(fd, buf, linear, I915_TILING_X);
> > +}
> > +
> > +static void copy_linear_to_y(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear)
> > +{
> > +	__copy_linear_to(fd, buf, linear, I915_TILING_Y);
> > +}
> > +
> > +static void copy_linear_to_yf(int fd, struct igt_buf *buf,
> > +			      uint32_t *linear)
> > +{
> > +	__copy_linear_to(fd, buf, linear, I915_TILING_Yf);
> > +}
> > +
> > +static void __copy_to_linear(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear, int tiling)
> > +{
> > +	int height = igt_buf_height(buf);
> > +	int width = igt_buf_width(buf);
> > +	fn_ptr fn = __get_tile_fn_ptr(tiling);
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_CPU, 0);
> > +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> > +			    buf->bo->size, PROT_READ);
> > +
> > +	for (int y = 0; y < height; y++) {
> > +		for (int x = 0; x < width; x++) {
> > +			uint32_t *ptr = fn(map, x, y,
> > +					   buf->stride, buf->bpp / 8);
> > +
> > +			linear[y * width + x] = *ptr;
> > +		}
> > +	}
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_yf_to_linear(int fd, struct igt_buf *buf,
> > +			      uint32_t *linear)
> > +{
> > +	__copy_to_linear(fd, buf, linear, I915_TILING_Yf);
> > +}
> > +
> > +static void copy_x_to_linear(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear)
> > +{
> > +	__copy_to_linear(fd, buf, linear, I915_TILING_X);
> > +}
> > +
> > +static void copy_y_to_linear(int fd, struct igt_buf *buf,
> > +			     uint32_t *linear)
> > +{
> > +	__copy_to_linear(fd, buf, linear, I915_TILING_Y);
> > +}
> > +
> > +static void copy_linear_to_gtt(int fd, struct igt_buf *buf,
> > +			       uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> > +
> > +	map = gem_mmap__gtt(fd, buf->bo->handle,
> > +			    buf->bo->size, PROT_READ | PROT_WRITE);
> > +
> > +	memcpy(map, linear, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_gtt_to_linear(int fd, struct igt_buf *buf,
> > +			       uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_GTT, 0);
> > +
> > +	map = gem_mmap__gtt(fd, buf->bo->handle,
> > +			    buf->bo->size, PROT_READ);
> > +
> > +	igt_memcpy_from_wc(linear, map, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_linear_to_wc(int fd, struct igt_buf *buf,
> > +			      uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> > +
> > +	map = gem_mmap__wc(fd, buf->bo->handle, 0,
> > +			   buf->bo->size, PROT_READ | PROT_WRITE);
> > +
> > +	memcpy(map, linear, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_wc_to_linear(int fd, struct igt_buf *buf,
> > +			      uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_GTT, 0);
> > +
> > +	map = gem_mmap__wc(fd, buf->bo->handle, 0,
> > +			   buf->bo->size, PROT_READ);
> > +
> > +	igt_memcpy_from_wc(linear, map, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_linear_to_cpu(int fd, struct igt_buf *buf,
> > +			       uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
> > +
> > +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> > +			    buf->bo->size, PROT_READ | PROT_WRITE);
> > +
> > +	memcpy(map, linear, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +static void copy_cpu_to_linear(int fd, struct igt_buf *buf,
> > +			       uint32_t *linear)
> > +{
> > +	void *map;
> > +
> > +	gem_set_domain(fd, buf->bo->handle,
> > +		       I915_GEM_DOMAIN_CPU, 0);
> > +
> > +	map = gem_mmap__cpu(fd, buf->bo->handle, 0,
> > +			    buf->bo->size, PROT_READ);
> > +
> > +	memcpy(linear, map, buf->bo->size);
> > +
> > +	munmap(map, buf->bo->size);
> > +}
> > +
> > +void copy_buf_to_linear(struct buf_ops *bops, struct igt_buf *buf,
> > +			uint32_t *linear)
> > +{
> > +	igt_assert(bops);
> > +
> > +	switch (buf->tiling) {
> > +	case I915_TILING_NONE:
> > +		igt_assert(bops->to_linear);
> > +		bops->to_linear(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_X:
> > +		igt_assert(bops->x_to_linear);
> > +		bops->x_to_linear(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Y:
> > +		igt_assert(bops->y_to_linear);
> > +		bops->y_to_linear(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Yf:
> > +		igt_assert(bops->yf_to_linear);
> > +		bops->yf_to_linear(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Ys:
> > +		igt_assert(bops->ys_to_linear);
> > +		bops->ys_to_linear(bops->fd, buf, linear);
> > +		break;
> > +	}
> > +}
> > +
> > +void copy_linear_to_buf(struct buf_ops *bops, struct igt_buf *buf,
> > +			uint32_t *linear)
> > +{
> > +	igt_assert(bops);
> > +
> > +	switch (buf->tiling) {
> > +	case I915_TILING_NONE:
> > +		igt_assert(bops->linear_to);
> > +		bops->linear_to(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_X:
> > +		igt_assert(bops->linear_to_x);
> > +		bops->linear_to_x(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Y:
> > +		igt_assert(bops->linear_to_y);
> > +		bops->linear_to_y(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Yf:
> > +		igt_assert(bops->linear_to_yf);
> > +		bops->linear_to_yf(bops->fd, buf, linear);
> > +		break;
> > +	case I915_TILING_Ys:
> > +		igt_assert(bops->linear_to_ys);
> > +		bops->linear_to_ys(bops->fd, buf, linear);
> > +		break;
> > +	}
> > +}
> > +
> > +struct buf_ops buf_ops_arr[] = {
> > +	/* Generations 0 - 8 */
> > +{
> > +	.gen_start         = 0,
> > +	.gen_end           = 8,
> > +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y,
> > +	.hw_tiles          = TILE_X | TILE_Y,
> > +	.linear_to         = copy_linear_to_cpu,
> > +	.linear_to_x       = copy_linear_to_gtt,
> > +	.linear_to_y       = copy_linear_to_gtt,
> > +	.to_linear         = copy_cpu_to_linear,
> > +	.x_to_linear       = copy_gtt_to_linear,
> > +	.y_to_linear       = copy_gtt_to_linear,
> > +},
> > +/* Generations 9 - 11 */
> > +{
> > +	.gen_start         = 9,
> > +	.gen_end           = 11,
> > +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf,
> > +	.hw_tiles          = TILE_X | TILE_Y,
> > +	.linear_to         = copy_linear_to_cpu,
> > +	.linear_to_x       = copy_linear_to_gtt,
> > +	.linear_to_y       = copy_linear_to_gtt,
> > +	.linear_to_yf      = copy_linear_to_yf,
> > +	.to_linear         = copy_cpu_to_linear,
> > +	.x_to_linear       = copy_gtt_to_linear,
> > +	.y_to_linear       = copy_gtt_to_linear,
> > +	.yf_to_linear      = copy_yf_to_linear,
> > +},
> > +/* Generation 12 */
> > +{
> > +	.gen_start         = 12,
> > +	.gen_end           = 12,
> > +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf | TILE_Ys,
> > +	.linear_to         = copy_linear_to_wc,
> > +	.linear_to_x       = copy_linear_to_x,
> > +	.linear_to_y       = copy_linear_to_y,
> > +	.linear_to_yf      = copy_linear_to_yf,
> > +	.linear_to_ys      = NULL,               /* to be implemented */
> > +	.to_linear         = copy_wc_to_linear,
> > +	.x_to_linear       = copy_x_to_linear,
> > +	.y_to_linear       = copy_y_to_linear,
> > +	.yf_to_linear      = copy_yf_to_linear,
> > +	.ys_to_linear      = NULL,               /* to be implemented */
> > +},
> > +};
> > +
> > +static int __gem_get_tiling(int fd, struct drm_i915_gem_get_tiling *arg)
> > +{
> > +	int err;
> > +
> > +	err = 0;
> > +	if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, arg))
> > +		err = -errno;
> > +	errno = 0;
> > +
> > +	return err;
> > +}
> > +
> > +static bool __get_tiling(int fd, uint32_t handle, uint32_t *tiling,
> > +			 uint32_t *swizzle)
> > +{
> > +	struct drm_i915_gem_get_tiling get_tiling;
> > +
> > +	memset(&get_tiling, 0, sizeof(get_tiling));
> > +	get_tiling.handle = handle;
> > +
> > +	if (__gem_get_tiling(fd, &get_tiling) != 0)
> > +		return false;
> > +
> > +	*tiling = get_tiling.tiling_mode;
> > +	*swizzle = get_tiling.swizzle_mode;
> > +
> > +	return get_tiling.phys_swizzle_mode == get_tiling.swizzle_mode;
> > +}
> > +
> > +static bool probe_hw_tiling(int fd, uint32_t tiling)
> > +{
> > +	struct drm_i915_gem_set_tiling st;
> > +	uint64_t size = 1024 * 1024;
> > +	uint32_t handle, buf_tiling, buf_swizzle;
> > +	uint32_t stride;
> > +	int ret;
> > +	bool is_set;
> > +
> > +	if (tiling == I915_TILING_X)
> > +		stride = 512;
> > +	else if (tiling == I915_TILING_Y)
> > +		stride = 128;
> > +	else
> > +		return false;
> > +
> > +	handle = gem_create(fd, size);
> > +
> > +	/* Single shot, if no fences are available we fail immediately */
> > +	st.handle = handle;
> > +	st.tiling_mode = tiling;
> > +	st.stride = tiling ? stride : 0;
> > +	ret = ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &st);
> > +	if (ret)
> > +		goto end;
> > +
> > +	is_set = __get_tiling(fd, handle, &buf_tiling, &buf_swizzle);
> > +
> > +end:
> > +	gem_close(fd, handle);
> > +
> > +	return is_set;
> > +}
> > +
> > +struct buf_ops *buf_ops_get(int fd, drm_intel_bufmgr *bufmgr)
> > +{
> > +	struct buf_ops *bops = calloc(1, sizeof(*bops));
> > +	uint32_t devid;
> > +	int generation;
> > +
> > +	igt_assert(bufmgr);
> > +	igt_assert(bops);
> > +
> > +	devid = intel_get_drm_devid(fd);
> > +	generation = intel_gen(devid);
> > +
> > +	/* Predefined settings */
> > +	for (int i = 0; i < ARRAY_SIZE(buf_ops_arr); i++) {
> > +		if (generation >= buf_ops_arr[i].gen_start &&
> > +				generation <= buf_ops_arr[i].gen_end) {
> > +			memcpy(bops, &buf_ops_arr[i], sizeof(*bops));
> > +			bops->fd = fd;
> > +			bops->bufmgr = bufmgr;
> > +			bops->intel_gen = generation;
> > +			igt_debug("generation: %d, supported tiles: 0x%02x\n",
> > +				  generation, bops->supported_tiles);
> > +			break;
> > +		}
> > +	}
> > +
> > +	/* Let's probe X and Y hw tiling support */
> > +	if (bops->hw_tiles & TILE_X) {
> > +		bool supported = probe_hw_tiling(fd, I915_TILING_X);
> > +
> > +		igt_debug("X fence support: %s\n", supported ? "yes" : "no");
> > +		if (!supported) {
> > +			bops->hw_tiles &= ~TILE_X;
> > +			bops->linear_to_x = copy_linear_to_x;
> > +			bops->x_to_linear = copy_x_to_linear;
> > +		}
> > +	}
> > +
> > +	if (bops->hw_tiles & TILE_Y) {
> > +		bool supported = probe_hw_tiling(fd, I915_TILING_Y);
> > +
> > +		igt_debug("Y fence support: %s\n", supported ? "yes" : "no");
> > +		if (!supported) {
> > +			bops->hw_tiles &= ~TILE_Y;
> > +			bops->linear_to_y = copy_linear_to_y;
> > +			bops->y_to_linear = copy_y_to_linear;
> > +		}
> > +	}
> > +
> > +	igt_assert(bops->intel_gen);
> > +
> > +	return bops;
> > +}
> > +
> > +void buf_ops_switch_to_sofware_tiling(struct buf_ops *bops)
> so far so good :) first typo ^ s/sofware/software/
> Check declaration too :)

Sure, I'll fix this.

> > +{
> > +	igt_debug("Switch to software tiling/detiling of X/Y surfaces\n");
> > +
> > +	igt_assert(bops);
> > +
> > +	bops->hw_tiles = 0;
> > +	bops->linear_to_x = copy_linear_to_x;
> > +	bops->linear_to_y = copy_linear_to_y;
> > +	bops->x_to_linear = copy_x_to_linear;
> > +	bops->y_to_linear = copy_y_to_linear;
> > +}
> > +
> > +bool buf_ops_has_hw_fence(struct buf_ops *bops, uint32_t tiling)
> > +{
> > +	uint32_t tile_mask = (1 << tiling);
> > +
> > +	igt_assert(bops);
> > +
> > +	if (tile_mask & bops->hw_tiles)
> > +		return true;
> > +
> > +	return false;
> > +}
> > +
> > +bool buf_ops_has_tiling_support(struct buf_ops *bops, uint32_t tiling)
> > +{
> > +	uint32_t tile_mask = (1 << tiling);
> > +
> > +	igt_assert(bops);
> > +
> > +	if (tile_mask & bops->supported_tiles)
> > +		return true;
> > +
> > +	return false;
> > +}
> > +
> > +static int buf_aux_width(int gen, const struct igt_buf *buf)
> > +{
> > +	/*
> > +	 * GEN12+: The AUX CCS unit size is 64 bytes mapping 4 main surface
> > +	 * tiles. Thus the width of the CCS unit is 4*32=128 pixels on the
> > +	 * main surface.
> > +	 */
> > +	if (gen >= 12)
> > +		return DIV_ROUND_UP(igt_buf_width(buf), 128) * 64;
> > +
> > +	return DIV_ROUND_UP(igt_buf_width(buf), 1024) * 128;
> > +}
> > +
> > +static int buf_aux_height(int gen, const struct igt_buf *buf)
> > +{
> > +	/*
> > +	 * GEN12+: The AUX CCS unit size is 64 bytes mapping 4 main surface
> > +	 * tiles. Thus the height of the CCS unit is 32 pixel rows on the main
> > +	 * surface.
> > +	 */
> > +	if (gen >= 12)
> > +		return DIV_ROUND_UP(igt_buf_height(buf), 32);
> > +
> > +	return DIV_ROUND_UP(igt_buf_height(buf), 512) * 32;
> > +}
> > +
> > +void igt_buf_init(struct buf_ops *bops, struct igt_buf *buf,
> > +		  int width, int height, int bpp,
> > +		  uint32_t req_tiling, bool ccs)
> > +{
> > +	uint32_t tiling = req_tiling;
> > +	bool supports_hw_fences;
> > +
> > +	igt_assert(bops);
> > +
> > +	supports_hw_fences = buf_ops_has_hw_fence(bops, req_tiling);
> > +
> > +	memset(buf, 0, sizeof(*buf));
> > +
> > +	if (ccs) {
> > +		int aux_width, aux_height;
> > +		int size;
> > +
> > +		igt_require(bops->intel_gen >= 9);
> > +		igt_assert(req_tiling == I915_TILING_Y ||
> > +			   req_tiling == I915_TILING_Yf);
> > +
> > +		/*
> > +		 * On GEN12+ we align the main surface to 4 * 4 main surface
> > +		 * tiles, which is 64kB. These 16 tiles are mapped by 4 AUX
> > +		 * CCS units, that is 4 * 64 bytes. These 4 CCS units are in
> > +		 * turn mapped by one L1 AUX page table entry.
> > +		 */
> > +		if (bops->intel_gen >= 12)
> > +			buf->stride = ALIGN(width * (bpp / 8), 128 * 4);
> > +		else
> > +			buf->stride = ALIGN(width * (bpp / 8), 128);
> > +
> > +		if (bops->intel_gen >= 12)
> > +			height = ALIGN(height, 4 * 32);
> > +
> > +		buf->size = buf->stride * height;
> > +		buf->tiling = tiling;
> > +		buf->bpp = bpp;
> > +
> > +		aux_width = buf_aux_width(bops->intel_gen, buf);
> > +		aux_height = buf_aux_height(bops->intel_gen, buf);
> > +
> > +		buf->aux.offset = buf->stride * ALIGN(height, 32);
> > +		buf->aux.stride = aux_width;
> > +
> > +		size = buf->aux.offset + aux_width * aux_height;
> > +
> > +		buf->bo = drm_intel_bo_alloc(bops->bufmgr, "", size, 4096);
> > +
> > +		if (tiling == I915_TILING_Y && supports_hw_fences) {
> > +			drm_intel_bo_set_tiling(buf->bo, &tiling, buf->stride);
> > +			igt_assert_eq(tiling, req_tiling);
> > +		}
> > +	} else {
> > +		/* Requested bo must be hw tiled */
> > +		if (supports_hw_fences) {
> > +			unsigned long pitch;
> > +
> > +			buf->bo = drm_intel_bo_alloc_tiled(bops->bufmgr, "",
> > +							   width, height,
> > +							   bpp / 8,
> > +							   &tiling, &pitch, 0);
> > +			igt_assert_eq(tiling, req_tiling);
> > +			igt_assert(buf->bo);
> > +
> > +			buf->stride = pitch;
> > +			buf->tiling = tiling;
> > +			buf->size = pitch * height;
> > +			buf->bpp = bpp;
> > +		} else {
> > +			/* Use bo alloc and software tiling/detiling */
> > +			int size;
> > +
> > +			buf->stride = ALIGN(width * (bpp / 8), 128);
> > +			buf->size = buf->stride * height;
> > +			buf->tiling = tiling;
> > +			buf->bpp = bpp;
> > +
> > +			size = buf->stride * ALIGN(height, 32);
> > +
> > +			buf->bo = drm_intel_bo_alloc(bops->bufmgr, "", size,
> > +						     4096);
> > +			igt_assert(buf->bo);
> > +		}
> > +	}
> > +}
> > diff --git a/lib/intel_bufops.h b/lib/intel_bufops.h
> > new file mode 100644
> > index 00000000..e53c6ebc
> > --- /dev/null
> > +++ b/lib/intel_bufops.h
> > @@ -0,0 +1,24 @@
> > +#ifndef __INTEL_BUFOPS_H__
> > +#define __INTEL_BUFOPS_H__
> > +
> > +#include "intel_batchbuffer.h"
> > +
> > +struct buf_ops;
> > +
> > +struct buf_ops *buf_ops_get(int fd, drm_intel_bufmgr *bufmgr);
> > +void buf_ops_switch_to_sofware_tiling(struct buf_ops *bops);
> > +
> > +void copy_buf_to_linear(struct buf_ops *bops, struct igt_buf *buf,
> > +			uint32_t *linear);
> > +
> > +void copy_linear_to_buf(struct buf_ops *bops, struct igt_buf *buf,
> > +			uint32_t *linear);
> > +
> > +bool buf_ops_has_hw_fence(struct buf_ops *bops, uint32_t tiling);
> > +bool buf_ops_has_tiling_support(struct buf_ops *bops, uint32_t tiling);
> > +
> > +void igt_buf_init(struct buf_ops *bops, struct igt_buf *buf,
> > +		  int width, int height, int bpp,
> > +		  uint32_t req_tiling, bool ccs);
> > +
> > +#endif
> > diff --git a/lib/meson.build b/lib/meson.build
> > index 3f908912..a88c3e89 100644
> > --- a/lib/meson.build
> > +++ b/lib/meson.build
> > @@ -26,6 +26,7 @@ lib_sources = [
> >  	'igt_x86.c',
> >  	'instdone.c',
> >  	'intel_batchbuffer.c',
> > +	'intel_bufops.c',
> >  	'intel_chipset.c',
> >  	'intel_device_info.c',
> >  	'intel_os.c',
> > -- 
> > 2.23.0
> >
> Huge and quite important functions introduced!
> Kasia

If I good understand Chris intention I should also provide function
to get tiled buffer for kms.

Zbigniew
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations
  2019-12-03 17:05   ` Zbigniew Kempczyński
@ 2019-12-03 17:46     ` Ville Syrjälä
  0 siblings, 0 replies; 8+ messages in thread
From: Ville Syrjälä @ 2019-12-03 17:46 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev

On Tue, Dec 03, 2019 at 06:05:58PM +0100, Zbigniew Kempczyński wrote:
> On Tue, Dec 03, 2019 at 10:25:29AM +0100, Katarzyna Dec wrote:
> 
> <cut>
> > > +static void *x_ptr(void *ptr,
> > > +		   unsigned int x, unsigned int y,
> > > +		   unsigned int stride, unsigned int cpp)
> > > +{
> > > +	const int tile_width = 512;
> > > +	const int tile_height = 8;
> > It can be really silly question - are these ^ values always the same?
> 
> Yes.

If you ignore gen2.

> 
> > > +	const int tile_size = tile_width * tile_height;
> > > +	int tile_x, tile_y;
> > > +	int offset_x, offset_y, pos;
> > > +
> > > +	x *= cpp;
> > > +	tile_x = x / tile_width;
> > > +	tile_y = y / tile_height;
> > > +	offset_x = (tile_x * tile_size);
> > > +	offset_y = (tile_y * stride * tile_height);
> > > +
> > > +	pos = offset_y + offset_x +
> > > +			(y % tile_height * tile_width) + (x % tile_width);
> > > +
> > > +	return ptr + pos;
> > > +}
> > > +
> > > +static void *y_ptr(void *ptr,
> > > +		   unsigned int x, unsigned int y,
> > > +		   unsigned int stride, unsigned int cpp)
> > > +{
> > > +	const int tile_width = 128;
> > > +	const int tile_height = 32;
> > > +	const int owords = 16;
> > Similar question. I guess this is something specific either to Intel Gen or to
> > testcases.
> 
> Tile-n where n is X/Y/Yf/Ys/... describe data placement algorithms
> to be CPU/GPU cache-friendly. 

These numbers also only work for i945+.

-- 
Ville Syrjälä
Intel
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations
  2019-12-01 19:09 [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations Zbigniew Kempczyński
                   ` (2 preceding siblings ...)
  2019-12-03  9:25 ` [igt-dev] [PATCH i-g-t v2 1/2] " Katarzyna Dec
@ 2019-12-10  0:07 ` Dixit, Ashutosh
  3 siblings, 0 replies; 8+ messages in thread
From: Dixit, Ashutosh @ 2019-12-10  0:07 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev

On Sun, 01 Dec 2019 11:09:41 -0800, Zbigniew Kempczyński wrote:
>
> Different GENs supports different tile surfaces. Older GENs
> have HW fences to allow X / Y surface tiling / detiling.
> Newer GENs have to tile / detile such surface in software.
>
> To make test developer life easier this code adds buffer
> operations (short bufops) to use appropriate functions allowing
> copying linear buffer to BO and from BO to linear buffer
> regardless GPU generation and tiling within BO. For GENs having
> fences support preference is to use them if they are available
> (X / Y tiling is probed on bufops initalization).
>
> Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Imre Deak <imre.deak@intel.com>
> Cc: Katarzyna Dec <katarzyna.dec@intel.com>

[snip]

> +/* Generations 9 - 11 */
> +{
> +	.gen_start         = 9,
> +	.gen_end           = 11,
> +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf,
> +	.hw_tiles          = TILE_X | TILE_Y,
> +	.linear_to         = copy_linear_to_cpu,
> +	.linear_to_x       = copy_linear_to_gtt,
> +	.linear_to_y       = copy_linear_to_gtt,
> +	.linear_to_yf      = copy_linear_to_yf,
> +	.to_linear         = copy_cpu_to_linear,
> +	.x_to_linear       = copy_gtt_to_linear,
> +	.y_to_linear       = copy_gtt_to_linear,
> +	.yf_to_linear      = copy_yf_to_linear,
> +},
> +/* Generation 12 */
> +{
> +	.gen_start         = 12,
> +	.gen_end           = 12,
> +	.supported_tiles   = TILE_NONE | TILE_X | TILE_Y | TILE_Yf | TILE_Ys,
> +	.linear_to         = copy_linear_to_wc,
> +	.linear_to_x       = copy_linear_to_x,
> +	.linear_to_y       = copy_linear_to_y,
> +	.linear_to_yf      = copy_linear_to_yf,
> +	.linear_to_ys      = NULL,               /* to be implemented */
> +	.to_linear         = copy_wc_to_linear,
> +	.x_to_linear       = copy_x_to_linear,
> +	.y_to_linear       = copy_y_to_linear,

Isn't it true that TGL which is Gen12 does support HW fences in ggtt?
Maybe it is ok to leave the default functions as these but perhaps we
should set the ggtt versions of the functions (same ag Gen11 above) if HW
tiling support is detected in buf_ops_get()?
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-12-10  0:16 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-01 19:09 [igt-dev] [PATCH i-g-t v2 1/2] lib/intel_bufops: Introduce buffer operations Zbigniew Kempczyński
2019-12-01 19:09 ` [igt-dev] [PATCH i-g-t v2 2/2] tests/gem_render_copy: Add software tiling / detiling support Zbigniew Kempczyński
2019-12-01 19:36 ` [igt-dev] ✗ Fi.CI.BAT: failure for series starting with [i-g-t,v2,1/2] lib/intel_bufops: Introduce buffer operations Patchwork
2019-12-03  9:25 ` [igt-dev] [PATCH i-g-t v2 1/2] " Katarzyna Dec
2019-12-03  9:41   ` Katarzyna Dec
2019-12-03 17:05   ` Zbigniew Kempczyński
2019-12-03 17:46     ` Ville Syrjälä
2019-12-10  0:07 ` Dixit, Ashutosh

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.