[PATCH i-g-t 1/3] lib: Introduce blitter verifier

Karolina Stolarek karolina.stolarek at intel.com
Fri Mar 31 13:41:04 UTC 2023


Add an initial version of intel_blt_verifier, a library that checks if
the blit operation used the expected tiling format.

Signed-off-by: Karolina Stolarek <karolina.stolarek at intel.com>
---
 lib/intel_blt_verifier.c | 265 +++++++++++++++++++++++++++++++++++++++
 lib/intel_blt_verifier.h |  33 +++++
 lib/meson.build          |   1 +
 3 files changed, 299 insertions(+)
 create mode 100644 lib/intel_blt_verifier.c
 create mode 100644 lib/intel_blt_verifier.h

diff --git a/lib/intel_blt_verifier.c b/lib/intel_blt_verifier.c
new file mode 100644
index 00000000..b9116433
--- /dev/null
+++ b/lib/intel_blt_verifier.c
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#include "intel_blt_verifier.h"
+
+/*
+ *  As for now, only a subsection of tiling formats is supported by intel_bufops
+ *  operations. Verifier checks if it can copy to a requested format before
+ *  trying to verify intel_cmds_info entry.
+ */
+#define SUPPORTED_TILING_FORMATS (BIT(T_LINEAR) | BIT(T_XMAJOR) | BIT(T_YMAJOR) | BIT(T_YFMAJOR))
+
+static void generate_reference(struct intel_blt_verifier *verifier)
+{
+	cairo_surface_t *surface;
+	cairo_pattern_t *pat;
+	cairo_t *cr;
+
+	struct intel_buf *buf;
+	void *linear;
+	int width = 512, height = 512;
+	int bpp = 32;
+
+	buf = verifier->ref;
+
+	intel_buf_init(verifier->bops, buf, width, height, bpp, 0,
+		       I915_TILING_NONE, I915_COMPRESSION_NONE);
+
+	width = intel_buf_width(buf);
+	height = intel_buf_height(buf);
+
+	linear = gem_mmap__device_coherent(verifier->fd, buf->handle, 0,
+					   buf->surface[0].size,
+					   PROT_READ | PROT_WRITE);
+
+	surface = cairo_image_surface_create_for_data(linear,
+						      CAIRO_FORMAT_RGB24,
+						      width, height,
+						      buf->surface[0].stride);
+	cr = cairo_create(surface);
+
+	cairo_rectangle(cr, 0, 0, width, height);
+	cairo_clip(cr);
+
+	pat = cairo_pattern_create_mesh();
+	cairo_mesh_pattern_begin_patch(pat);
+	cairo_mesh_pattern_move_to(pat, 0, 0);
+	cairo_mesh_pattern_line_to(pat, width, 0);
+	cairo_mesh_pattern_line_to(pat, width, height);
+	cairo_mesh_pattern_line_to(pat, 0, height);
+	cairo_mesh_pattern_set_corner_color_rgb(pat, 0, 1.0, 0.0, 0.0);
+	cairo_mesh_pattern_set_corner_color_rgb(pat, 1, 0.0, 1.0, 0.0);
+	cairo_mesh_pattern_set_corner_color_rgb(pat, 2, 0.0, 0.0, 1.0);
+	cairo_mesh_pattern_set_corner_color_rgb(pat, 3, 1.0, 1.0, 1.0);
+	cairo_mesh_pattern_end_patch(pat);
+
+	cairo_rectangle(cr, 0, 0, width, height);
+	cairo_set_source(cr, pat);
+	cairo_fill(cr);
+	cairo_pattern_destroy(pat);
+
+	cairo_destroy(cr);
+
+	cairo_surface_destroy(surface);
+
+	linear_to_intel_buf(verifier->bops, buf, linear);
+
+	munmap(linear, buf->surface[0].size);
+}
+
+static void software_blit(struct intel_blt_verifier *verifier,
+			  enum blt_tiling_type tiling)
+{
+	struct intel_buf *ref, *dst;
+	int width, height;
+	void *linear;
+	int bpp = 32;
+
+	ref = verifier->ref;
+	dst = verifier->software_dst;
+
+	width = intel_buf_width(ref);
+	height = intel_buf_height(ref);
+
+	intel_buf_init(verifier->bops, dst, width, height, bpp, 0,
+		       tiling, I915_COMPRESSION_NONE);
+
+	gem_set_domain(verifier->fd, ref->handle, I915_GEM_DOMAIN_CPU, 0);
+	linear = gem_mmap__device_coherent(verifier->fd, ref->handle, 0,
+					   ref->size, PROT_READ);
+	if (!ref->ptr)
+		intel_buf_cpu_map(ref, false);
+
+	linear_to_intel_buf(verifier->bops, dst, linear);
+
+	munmap(linear, ref->size);
+}
+
+static void copy_from_ref(int fd, struct intel_buf *ref,
+			  struct blt_copy_object *src)
+{
+	void *map = src->ptr;
+
+	map = gem_mmap__device_coherent(fd, src->handle, 0,
+					src->size, PROT_READ | PROT_WRITE);
+
+	memcpy(map, ref->ptr, ref->surface[0].size);
+	munmap(map, ref->surface[0].size);
+}
+
+static void blit(struct intel_blt_verifier *verifier,
+		 enum blt_cmd_type command,
+		 enum blt_tiling_type tiling)
+{
+	struct blt_copy_data blt = {};
+	struct blt_block_copy_data_ext ext = {}, *pext = &ext;
+	struct blt_copy_object *src, *dst;
+	struct intel_execution_engine2 *e;
+	const uint32_t bpp = 32;
+	uint64_t bb_size = 4096;
+	int fd = verifier->fd;
+
+	uint64_t ahnd = intel_allocator_open_full(fd, verifier->ctx->id, 0, 0,
+						  INTEL_ALLOCATOR_SIMPLE,
+						  ALLOC_STRATEGY_LOW_TO_HIGH, 0);
+	uint32_t bb;
+	int width, height;
+
+	igt_assert(__gem_create_in_memory_regions(fd, &bb, &bb_size, I915_SYSTEM_MEMORY) == 0);
+
+	width = intel_buf_width(verifier->ref);
+	height = intel_buf_height(verifier->ref);
+
+	src = blt_create_object(fd, I915_SYSTEM_MEMORY, width, height, bpp, 0,
+				T_LINEAR, COMPRESSION_DISABLED, 0, true);
+	dst = blt_create_object(fd, I915_SYSTEM_MEMORY, width, height, bpp, 0,
+				tiling, COMPRESSION_DISABLED, 0, true);
+	igt_assert(src->size == dst->size);
+
+	copy_from_ref(fd, verifier->ref, src);
+
+	for_each_ctx_engine(fd, verifier->ctx, e) {
+		if (e->class == I915_ENGINE_CLASS_COPY)
+			break;
+	}
+
+	memset(&blt, 0, sizeof(blt));
+	blt.color_depth = CD_32bit;
+	blt_set_batch(&blt.bb, bb, bb_size, I915_SYSTEM_MEMORY);
+	blt_set_copy_object(&blt.src, src);
+	blt_set_copy_object(&blt.dst, dst);
+
+	/* block-copy doesn't have a bit to set Yf-Major, test all but this format */
+	if (command == XY_BLOCK_COPY && tiling != T_YFMAJOR) {
+		if (!blt_uses_extended_block_copy(fd))
+			pext = NULL;
+
+		/* block-copy requires additional setup */
+		blt_set_object_ext(&ext.src, 0, width, height, SURFACE_TYPE_2D);
+		blt_set_object_ext(&ext.dst, 0, width, height, SURFACE_TYPE_2D);
+
+		blt_block_copy(fd, verifier->ctx, e, ahnd, &blt, pext);
+	} else if (command == XY_FAST_COPY) {
+		blt_fast_copy(fd, verifier->ctx, e, ahnd, &blt);
+	}
+
+	gem_sync(fd, blt.dst.handle);
+	verifier->blitter_dst = dst;
+
+	blt_destroy_object(fd, src);
+	gem_close(fd, bb);
+	put_ahnd(ahnd);
+	munmap(&bb, bb_size);
+}
+
+struct intel_blt_verifier *blt_verifier_init(int fd)
+{
+	struct intel_blt_verifier *verifier;
+	int devid = intel_get_drm_devid(fd);
+
+	verifier = calloc(1, sizeof(*verifier));
+	igt_assert(verifier);
+
+	verifier->fd = fd;
+	verifier->cmds_info = intel_get_cmds_info(devid);
+	verifier->bops = buf_ops_create(fd);
+	verifier->ctx = intel_ctx_create_all_physical(fd);
+
+	verifier->ref = calloc(1, sizeof(struct intel_buf *));
+	verifier->software_dst = calloc(1, sizeof(struct intel_buf *));
+
+	generate_reference(verifier);
+
+	return verifier;
+}
+
+bool verifier_supports_blt_tiling(enum blt_tiling_type tiling)
+{
+	return SUPPORTED_TILING_FORMATS & BIT(tiling);
+}
+
+static bool compare_results(struct intel_blt_verifier *verifier)
+{
+	void *soft_dst, *blt_dst;
+	int ret;
+	int fd = verifier->fd;
+	uint64_t size = verifier->software_dst->size;
+
+	igt_assert(verifier->blitter_dst->size == size);
+
+	soft_dst = gem_mmap__device_coherent(fd, verifier->software_dst->handle,
+					     0, size, PROT_READ);
+	blt_dst = gem_mmap__device_coherent(fd, verifier->blitter_dst->handle,
+					    0, size, PROT_READ);
+	ret = memcmp(soft_dst, blt_dst, size);
+
+	munmap(soft_dst, size);
+	munmap(blt_dst, size);
+
+	return ret == 0;
+}
+
+int blt_verify_support(struct intel_blt_verifier *verifier,
+		       enum blt_cmd_type command,
+		       enum blt_tiling_type tiling)
+{
+	bool same_results;
+	bool intel_cmds_support;
+
+	if (!verifier_supports_blt_tiling(tiling)) {
+		igt_warn("Tiling %s not supported by the verifier\n",
+			 blt_tiling_name(tiling));
+		return -EINVAL;
+	}
+
+	software_blit(verifier, tiling);
+	blit(verifier, command, tiling);
+
+	same_results = compare_results(verifier);
+	intel_cmds_support = blt_cmd_supports_tiling(verifier->cmds_info,
+						     command, tiling);
+
+	/* platform supports the tiling, but didn't know about it */
+	if (same_results && !intel_cmds_support)
+		return -1;
+
+	/* intel_cmds_info falsely claims support for the tiling format */
+	if (!same_results && intel_cmds_support)
+		return 1;
+
+	return 0;
+}
+
+void blt_verifier_destroy(struct intel_blt_verifier *verifier)
+{
+	intel_buf_close(verifier->bops, verifier->ref);
+	intel_buf_unmap(verifier->ref);
+
+	buf_ops_destroy(verifier->bops);
+	blt_destroy_object(verifier->fd, verifier->blitter_dst);
+
+	free(verifier);
+}
diff --git a/lib/intel_blt_verifier.h b/lib/intel_blt_verifier.h
new file mode 100644
index 00000000..424a2bc0
--- /dev/null
+++ b/lib/intel_blt_verifier.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef INTEL_BLT_VERIFIER_H
+#define INTEL_BLT_VERIFIER_H
+
+#include "i915/i915_blt.h"
+#include "intel_bufops.h"
+
+struct intel_blt_verifier {
+	int fd;
+	const intel_ctx_t *ctx;
+	const struct intel_cmds_info *cmds_info;
+
+	struct buf_ops *bops;
+	struct intel_buf *ref;
+	struct intel_buf *software_dst;
+	struct blt_copy_object *blitter_dst;
+};
+
+bool verifier_supports_blt_tiling(enum blt_tiling_type tiling);
+
+int blt_verify_support(struct intel_blt_verifier *verifier,
+		       enum blt_cmd_type command,
+		       enum blt_tiling_type tiling);
+// bool blt_verify_support_with_ref(struct intel_buf *ref); <-- later
+
+void blt_verifier_destroy(struct intel_blt_verifier *verifier);
+struct intel_blt_verifier *blt_verifier_init(int fd);
+
+#endif // INTEL_BLT_VERIFIER_H
diff --git a/lib/meson.build b/lib/meson.build
index ad9e2abe..905d49af 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -54,6 +54,7 @@ lib_sources = [
 	'intel_allocator_reloc.c',
 	'intel_allocator_simple.c',
 	'intel_batchbuffer.c',
+	'intel_blt_verifier.c',
 	'intel_bufops.c',
 	'intel_chipset.c',
 	'intel_ctx.c',
-- 
2.25.1



More information about the Intel-gfx-trybot mailing list