[Intel-gfx] [PATCH] tests/gem_userptr_blits: add test to check blit aligns

Mika Kuoppala mika.kuoppala at linux.intel.com
Fri Dec 5 05:32:30 PST 2014


Copy a block into a destination object with varying base offset
into the destination and source. Put guard area before and after
the blit target to see that it didn't touch memory out of
blit boundaries.

References: https://bugs.freedesktop.org/show_bug.cgi?id=79053
Cc: Chris Wilson <chris at chris-wilson.co.uk>
Signed-off-by: Mika Kuoppala <mika.kuoppala at intel.com>
---
 tests/gem_userptr_blits.c | 275 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 268 insertions(+), 7 deletions(-)

diff --git a/tests/gem_userptr_blits.c b/tests/gem_userptr_blits.c
index d641c12..b945b48 100644
--- a/tests/gem_userptr_blits.c
+++ b/tests/gem_userptr_blits.c
@@ -81,6 +81,7 @@ static uint32_t userptr_flags = LOCAL_I915_USERPTR_UNSYNCHRONIZED;
 #define HEIGHT 512
 
 static uint32_t linear[WIDTH*HEIGHT];
+static uint32_t gen;
 
 static void gem_userptr_test_unsynchronized(void)
 {
@@ -136,7 +137,7 @@ copy(int fd, uint32_t dst, uint32_t src, unsigned int error)
 	batch[i++] = XY_SRC_COPY_BLT_CMD |
 		  XY_SRC_COPY_BLT_WRITE_ALPHA |
 		  XY_SRC_COPY_BLT_WRITE_RGB;
-	if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+	if (gen >= 8)
 		batch[i - 1] |= 8;
 	else
 		batch[i - 1] |= 6;
@@ -147,12 +148,12 @@ copy(int fd, uint32_t dst, uint32_t src, unsigned int error)
 	batch[i++] = 0; /* dst x1,y1 */
 	batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */
 	batch[i++] = 0; /* dst reloc */
-	if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+	if (gen >= 8)
 		batch[i++] = 0;
 	batch[i++] = 0; /* src x1,y1 */
 	batch[i++] = WIDTH*4;
 	batch[i++] = 0; /* src reloc */
-	if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+	if (gen >= 8)
 		batch[i++] = 0;
 	batch[i++] = MI_BATCH_BUFFER_END;
 	batch[i++] = MI_NOOP;
@@ -170,7 +171,7 @@ copy(int fd, uint32_t dst, uint32_t src, unsigned int error)
 	reloc[1].target_handle = src;
 	reloc[1].delta = 0;
 	reloc[1].offset = 7 * sizeof(batch[0]);
-	if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+	if (gen >= 8)
 		reloc[1].offset += sizeof(batch[0]);
 	reloc[1].presumed_offset = 0;
 	reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
@@ -221,7 +222,7 @@ blit(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo)
 	batch[i++] = XY_SRC_COPY_BLT_CMD |
 		  XY_SRC_COPY_BLT_WRITE_ALPHA |
 		  XY_SRC_COPY_BLT_WRITE_RGB;
-	if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+	if (gen >= 8)
 		batch[i - 1] |= 8;
 	else
 		batch[i - 1] |= 6;
@@ -231,7 +232,7 @@ blit(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo)
 	batch[i++] = 0; /* dst x1,y1 */
 	batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */
 	batch[i++] = 0; /* dst reloc */
-	if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+	if (gen >= 8)
 		batch[i++] = 0;
 	batch[i++] = 0; /* src x1,y1 */
 	batch[i++] = WIDTH*4;
@@ -254,7 +255,7 @@ blit(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo)
 	reloc[1].target_handle = src;
 	reloc[1].delta = 0;
 	reloc[1].offset = 7 * sizeof(batch[0]);
-	if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+	if (gen >= 8)
 		reloc[1].offset += sizeof(batch[0]);
 	reloc[1].presumed_offset = 0;
 	reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
@@ -972,6 +973,258 @@ static int test_coherency(int fd, int count)
 	return 0;
 }
 
+static uint32_t lb[12];
+
+static void
+copy_align(int fd,
+	   uint32_t dst, uint32_t dst_offset,
+	   uint32_t src, uint32_t src_offset,
+	   uint32_t w, uint32_t h)
+{
+	uint32_t batch[12];
+	struct drm_i915_gem_relocation_entry reloc[2];
+	struct drm_i915_gem_exec_object2 obj[3];
+	struct drm_i915_gem_execbuffer2 exec;
+	uint32_t handle;
+	int i=0;
+
+	batch[i++] = XY_SRC_COPY_BLT_CMD |
+		XY_SRC_COPY_BLT_WRITE_ALPHA |
+		XY_SRC_COPY_BLT_WRITE_RGB;
+	if (gen >= 8)
+		batch[i - 1] |= 8;
+	else
+		batch[i - 1] |= 6;
+
+	batch[i++] = (3 << 24) | /* 32 bits */
+		(0xcc << 16) | /* copy ROP */
+		w * 4;
+
+	batch[i++] = 0; /* dst, x1,y2 */
+	batch[i++] = ((h) << 16) | (w); /* dst x2,y2 */
+	batch[i++] = dst_offset * 4; /* dst reloc */
+	if (gen >= 8)
+		batch[i++] = 0;
+	batch[i++] = 0; /* src x1,y1 */
+	batch[i++] = w * 4;
+
+	if ((w * 4) % 8)
+		igt_warn("src pitch NOT aligned to quad\n");
+
+	batch[i++] = src_offset * 4; /* src reloc */
+	if (gen >= 8)
+		batch[i++] = 0;
+	batch[i++] = MI_BATCH_BUFFER_END;
+	batch[i++] = MI_NOOP;
+
+	handle = gem_create(fd, 4096);
+	gem_write(fd, handle, 0, batch, sizeof(batch));
+
+	reloc[0].target_handle = dst;
+	reloc[0].delta = dst_offset * 4;
+	reloc[0].offset = 4 * sizeof(batch[0]);
+	reloc[0].presumed_offset = 0;
+	reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
+	reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
+
+	reloc[1].target_handle = src;
+	reloc[1].delta = src_offset * 4;
+	reloc[1].offset = 7 * sizeof(batch[0]);
+	if (gen >= 8)
+		reloc[1].offset += sizeof(batch[0]);
+	reloc[1].presumed_offset = 0;
+	reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
+	reloc[1].write_domain = 0;
+
+	memset(obj, 0, sizeof(obj));
+	exec.buffer_count = 0;
+	obj[exec.buffer_count++].handle = dst;
+	if (src != dst)
+		obj[exec.buffer_count++].handle = src;
+	obj[exec.buffer_count].handle = handle;
+	obj[exec.buffer_count].relocation_count = 2;
+	obj[exec.buffer_count].relocs_ptr = (uintptr_t)reloc;
+	exec.buffer_count++;
+	exec.buffers_ptr = (uintptr_t)obj;
+
+	exec.batch_start_offset = 0;
+	exec.batch_len = i * 4;
+	exec.DR1 = exec.DR4 = 0;
+	exec.num_cliprects = 0;
+	exec.cliprects_ptr = 0;
+	exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0;
+	i915_execbuffer2_set_context_id(exec, 0);
+	exec.rsvd2 = 0;
+
+	gem_execbuf(fd, &exec);
+
+	memcpy(lb, batch, sizeof(batch));
+
+	gem_sync(fd, handle);
+	gem_close(fd, handle);
+}
+
+static unsigned long verify_guard_area(uint32_t *p,
+				       const int size,
+				       const uint32_t sval)
+{
+	int i;
+	unsigned long count = 0;
+
+	for (i = 0; i < size; i++) {
+		if (p[i] != i + sval) {
+			igt_warn("guard at index %d is 0x%08x, should be 0x%08x\n",
+				 i, p[i], i + sval);
+			count++;
+		}
+	}
+
+	return count;
+}
+
+static unsigned long verify_destination_area(uint32_t *p, const int size, const int sval)
+{
+	int i;
+	unsigned long count = 0;
+
+	for (i = 0; i < size; i++) {
+		if (p[i] != i + sval) {
+			igt_warn("dest data at index %d 0x%08x, should be 0x%08x\n",
+				 i, p[i], i + sval);
+			count++;
+		}
+	}
+
+	return count;
+}
+
+static int
+_test_destination_align(int fd, const uint32_t dst_align,
+			const uint32_t src_align,
+			const uint32_t w,
+			const uint32_t h,
+			const bool userptr)
+{
+	const uint32_t size = sizeof(linear) / 4;
+	const uint32_t guard_val = 0xdeadf00d;
+	uint32_t *p;
+	uint32_t h_dst;
+	uint32_t h_src;
+	int i, ret;
+	bool failed = false;
+	const int dwords = w*h;
+
+	igt_assert(dwords < size);
+
+	if (userptr) {
+		ret = posix_memalign((void **)&p, PAGE_SIZE, size * 4);
+		igt_assert(ret == 0 && p);
+
+		ret = gem_userptr(fd, p, size * 4, 0, &h_dst);
+		igt_assert(ret == 0);
+	} else {
+		h_dst = gem_create(fd, size * 4);
+		p = linear;
+	}
+
+	igt_assert(h_dst != 0);
+
+	h_src = create_bo(fd, 0);
+	check_gpu(fd, h_src, 0);
+
+	for (i = 0; i < size; i++)
+		p[i] = guard_val + i;
+
+	if (!userptr) {
+		gem_write(fd, h_dst, 0, p, size * 4);
+		gem_read(fd, h_dst, 0, p, size * 4);
+	}
+
+	igt_assert(verify_guard_area(p, size, guard_val) == 0);
+
+	copy_align(fd, h_dst, dst_align, h_src, src_align, w, h);
+
+	if (!userptr)
+		gem_read(fd, h_dst, 0, p, size * 4);
+
+	if (verify_guard_area(p, dst_align, guard_val)) {
+		failed = true;
+		igt_warn("corrupted before blit target, align (%d:%d) dwords\n",
+			 dst_align, src_align);
+	}
+
+	if (verify_destination_area(p + dst_align, dwords, src_align)) {
+		failed = true;
+		igt_warn("blit src not copied correctly, align (%d:%d) dwords\n",
+			 dst_align, src_align);
+	}
+
+	if (verify_guard_area(p + dwords + dst_align,
+			      size - dwords - dst_align,
+			      guard_val + dwords + dst_align)) {
+		failed = true;
+		igt_warn("corrupted after blit target, align (%d:%d) dwords\n",
+			 dst_align, src_align);
+	}
+
+	gem_close(fd, h_src);
+	gem_close(fd, h_dst);
+
+	if (userptr)
+		free(p);
+
+	if (failed) {
+		igt_warn("failed batch:\n");
+		for(i = 0; i < 12; i++)
+			igt_warn("0x%04x: 0x%08x\n", i, lb[i]);
+	}
+
+	return failed ? 1 : 0;
+}
+
+static bool assumed_fail(int dst_align, int w, int h)
+{
+	if (h == 1 || gen < 8)
+		return false;
+
+	if ((w % 8) == 2 && h != 2)
+		return ((dst_align % 8) + (w % 8)) >= 4;
+
+	return (dst_align % 8) + (w % 8) >= 8;
+}
+
+static void test_destination_align(int fd, bool userptr, int dst_align, int src_align, int max_w,
+				   int max_h)
+{
+	int i, j, w, h;
+	bool failed = false;
+	int res;
+
+	for (i = 0; i <= src_align; i++) {
+		for (j = 0; j <= dst_align; j++) {
+			for (h = 2; h <= max_h; h += 2) {
+				for (w = 2; w <= max_w; w += 2) {
+					res = _test_destination_align(fd, j, i, w, h, userptr);
+					if (res)
+						igt_warn("BLT %s: from 0x%08x to 0x%08x %d:%d (%d) dwords\n",
+							 res ? "FAIL" : "OK",
+							 i * 4, j * 4, w, h, w * h);
+
+					if (assumed_fail(j, w, h) != res) {
+						igt_warn("not expected dst blt result %s, %d:%d to 0x%08x, pitch 0x%08x\n",
+							 res ? "FAIL" : "OK", w, h, j * 4, w * 4);
+					}
+
+					if (res)
+						failed = true;
+				}
+			}
+		}
+	}
+
+	igt_assert(failed == false);
+}
+
 static struct igt_eviction_test_ops fault_ops = {
 	.create = create_userptr_bo,
 	.flink = flink_userptr_bo,
@@ -1248,6 +1501,8 @@ int main(int argc, char **argv)
 		fd = drm_open_any();
 		igt_assert(fd >= 0);
 
+		gen = intel_gen(intel_get_drm_devid(fd));
+
 		ret = has_userptr(fd);
 		igt_skip_on_f(ret == 0, "No userptr support - %s (%d)\n",
 			      strerror(errno), ret);
@@ -1457,5 +1712,11 @@ int main(int argc, char **argv)
 	igt_subtest("access-control")
 		test_access_control(fd);
 
+	igt_subtest("destination-bo-align")
+		test_destination_align(fd, false, 16, 0, 16, 16);
+
+	igt_subtest("destination-userptr-align")
+		test_destination_align(fd, true, 16, 0, 16, 16);
+
 	igt_exit();
 }
-- 
1.9.1




More information about the Intel-gfx mailing list