[PATCH i-g-t,v3 4/4] i915/gem_ccs: Add testing for CCS
Zbigniew Kempczyński
zbigniew.kempczynski at intel.com
Wed Dec 8 10:43:36 UTC 2021
On Tue, Dec 07, 2021 at 08:32:14PM +0530, apoorva1.singh at intel.com wrote:
> From: CQ Tang <cq.tang at intel.com>
>
> Add gem_ccs test for CCS testing.
> Commands are constructed with XY_BLOCK_COPY_BLT
> and XY_CTRL_SURF_COPY_BLT instructions.
>
> Signed-off-by: CQ Tang <cq.tang at intel.com>
> Signed-off-by: Apoorva Singh <apoorva1.singh at intel.com>
> Cc: Zbigniew Kempczyński <zbigniew.kempczynski at intel.com>
> Cc: Melkaveri, Arjun <arjun.melkaveri at intel.com>
> ---
> lib/i915/gem_engine_topology.c | 38 +++
> lib/i915/gem_engine_topology.h | 5 +
> tests/i915/gem_ccs.c | 492 +++++++++++++++++++++++++++++++++
> tests/meson.build | 1 +
> 4 files changed, 536 insertions(+)
> create mode 100644 tests/i915/gem_ccs.c
>
> diff --git a/lib/i915/gem_engine_topology.c b/lib/i915/gem_engine_topology.c
> index 729f42b0..37b5875e 100644
> --- a/lib/i915/gem_engine_topology.c
> +++ b/lib/i915/gem_engine_topology.c
> @@ -488,6 +488,44 @@ int gem_engine_property_printf(int i915, const char *engine, const char *attr,
> return ret;
> }
>
> +static bool
> +__gem_engine_has_capability(int i915, const char *engine,
> + const char *attr, const char *cap)
> +{
> + char buf[4096] = {};
> + FILE *file;
> +
> + file = __open_attr(igt_sysfs_open(i915), "r",
> + "engine", engine, attr, NULL);
> + if (file) {
> + fread(buf, 1, sizeof(buf) - 1, file);
> + fclose(file);
> + }
> +
> + return strstr(buf, cap);
> +}
> +
> +bool gem_engine_has_capability(int i915, const char *engine, const char *cap)
> +{
> + return __gem_engine_has_capability(i915, engine, "capabilities", cap);
> +}
> +
> +bool gem_engine_has_known_capability(int i915, const char *engine, const char *cap)
> +{
> + return __gem_engine_has_capability(i915, engine, "known_capabilities", cap);
> +}
> +
> +bool gem_engine_can_block_copy(int i915, const struct intel_execution_engine2 *engine)
> +{
> + if (engine->class != I915_ENGINE_CLASS_COPY)
> + return false;
> +
> + if (!gem_engine_has_known_capability(i915, engine->name, "block_copy"))
> + return intel_gen(intel_get_drm_devid(i915)) >= 12;
> +
> + return gem_engine_has_capability(i915, engine->name, "block_copy");
> +}
> +
> uint32_t gem_engine_mmio_base(int i915, const char *engine)
> {
> unsigned int mmio = 0;
> diff --git a/lib/i915/gem_engine_topology.h b/lib/i915/gem_engine_topology.h
> index 4cfab560..d24bc9e8 100644
> --- a/lib/i915/gem_engine_topology.h
> +++ b/lib/i915/gem_engine_topology.h
> @@ -124,6 +124,11 @@ int gem_engine_property_printf(int i915, const char *engine, const char *attr,
>
> uint32_t gem_engine_mmio_base(int i915, const char *engine);
>
> +bool gem_engine_has_capability(int i915, const char *engine, const char *cap);
> +bool gem_engine_has_known_capability(int i915, const char *engine, const char *cap);
> +
> +bool gem_engine_can_block_copy(int i915, const struct intel_execution_engine2 *engine);
> +
> void dyn_sysfs_engines(int i915, int engines, const char *file,
> void (*test)(int i915, int engine));
>
Split the change.
> diff --git a/tests/i915/gem_ccs.c b/tests/i915/gem_ccs.c
> new file mode 100644
> index 00000000..0689b8f9
> --- /dev/null
> +++ b/tests/i915/gem_ccs.c
> @@ -0,0 +1,492 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +
> +#include <errno.h>
> +#include <sys/ioctl.h>
> +#include <sys/time.h>
> +#include <malloc.h>
> +#include "drm.h"
> +#include "igt.h"
> +#include "i915/gem.h"
> +#include "i915/gem_create.h"
> +#include "lib/intel_chipset.h"
> +#include "i915/i915_blt.h"
> +
> +IGT_TEST_DESCRIPTION("Exercise the memory bandwidth compression and "
> + "decompression when copying data between "
> + "system and local memory");
> +
> +static void igt_wr_xy_ctrl_surf_copy_blt(int fd, uint32_t region, uint32_t src,
> + uint32_t dst, uint32_t out, uint64_t ahnd,
> + int ccssize, uint8_t *pattern_buf,
> + uint8_t *read_buf, int bosize,
> + struct intel_execution_engine2 *e)
> +{
> + int ret, i;
> +
> + gem_write(fd, src, 0, pattern_buf, bosize);
> +
> + /*
> + * 'dst' is lmem BO with ccs, directly
> + * copy content in 'src' BO to 'dst' BO's ccs
> + */
> + xy_ctrl_surf_copy_blt(fd, ahnd, src, dst, ahnd,
> + ccssize, true, e);
> +
> + memset(read_buf, 0, ccssize);
> + gem_write(fd, out, 0, read_buf, ccssize);
> +
> + /* copy 'dst' BO's ccs into 'out' BO */
> + xy_ctrl_surf_copy_blt(fd, region, dst, out, ahnd,
> + ccssize, false, e);
> +
> + gem_read(fd, out, 0, read_buf, ccssize);
> +
> + for (i = 0; i < ccssize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(!ret);
Maybe single igt_assert on memcmp()? Do we really need those comments?
> +}
> +
> +static void igt_overwritten_xy_block_copy_blt(int fd, uint32_t region, uint32_t src,
> + uint32_t dst, uint32_t out, uint64_t ahnd,
> + int ccssize, uint8_t *pattern_buf, uint8_t *read_buf,
> + int bosize, struct intel_execution_engine2 *e)
> +{
> + int ret, i;
> + bool enable_compression = true;
> +
> + igt_info("copy random pattern to lmem BO with compression\n");
> +
> + gem_write(fd, src, 0, pattern_buf, bosize);
> + gem_write(fd, dst, 0, pattern_buf, bosize);
> +
> + /*
> + * 'dst' is lmem BO with ccs,
> + * copy content in 'src' BO to 'dst' BO
> + */
> + xy_block_copy_blt(fd, region, src, dst, ahnd, bosize,
> + SYS_TO_LOCAL, enable_compression, e);
> +
> + memset(read_buf, 0, ccssize);
> + gem_write(fd, out, 0, read_buf, ccssize);
> +
> + /* copy 'dst' BO's ccs into 'out' BO */
> + xy_ctrl_surf_copy_blt(fd, region, dst, out, ahnd,
> + ccssize, false, e);
> +
> + gem_read(fd, out, 0, read_buf, ccssize);
> +
> + for (i = 0; i < ccssize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(ret);
memcmp, applies to check code below too? You can compare
to 0 or not 0 so four lines would be squashed to one.
> +
> + memset(read_buf, 0, bosize);
> + gem_read(fd, dst, 0, read_buf, bosize);
> +
> + for (i = 0; i < bosize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(ret);
> +
> + memset(read_buf, 0, bosize);
> + gem_write(fd, out, 0, read_buf, bosize);
> +
> + /* copy 'dst' BO into 'out' BO */
> + xy_block_copy_blt(fd, region, dst, out, ahnd, bosize,
> + LOCAL_TO_SYS, enable_compression, e);
> +
> + gem_read(fd, out, 0, read_buf, bosize);
> +
> + for (i = 0; i < bosize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(!ret);
> +
> + /* decompress 'dst' in place */
> + xy_block_copy_blt(fd, region, dst, dst, ahnd, bosize,
> + LOCAL_TO_LOCAL, enable_compression, e);
> +
> + memset(read_buf, 0, bosize);
> + gem_read(fd, dst, 0, read_buf, bosize);
> +
> + for (i = 0; i < bosize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(!ret);
> +
> + memset(read_buf, 0, bosize);
> + gem_write(fd, out, 0, read_buf, bosize);
> +
> + /* copy decompressed 'dst' to 'out' */
> + xy_block_copy_blt(fd, region, dst, out, ahnd, bosize,
> + LOCAL_TO_SYS, enable_compression, e);
> +
> + gem_read(fd, out, 0, read_buf, bosize);
> +
> + for (i = 0; i < bosize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(!ret);
> +}
> +
> +static void igt_corrupted_xy_ctrl_surf_copy_blt(int fd, uint32_t region, uint32_t src,
> + uint32_t dst, uint32_t out, uint64_t ahnd,
> + int ccssize, uint8_t *pattern_buf, uint8_t *read_buf,
> + int bosize, struct intel_execution_engine2 *e)
> +{
> + int ret, i;
> + bool enable_compression = true;
> +
> + gem_write(fd, src, 0, pattern_buf, bosize);
> +
> + igt_info("corrupt CCS via XY_CTRL_SURF_COPY_BLT\n");
> +
> + /* corrupt 'dst' BO's ccs by writing directly */
> + xy_ctrl_surf_copy_blt(fd, region, src, dst, ahnd,
> + ccssize, true, e);
> +
> + memset(read_buf, 0, bosize);
> + gem_write(fd, out, 0, read_buf, bosize);
> +
> + /* copy 'dst' BO into 'out' BO */
> + xy_block_copy_blt(fd, region, dst, out, ahnd, bosize,
> + LOCAL_TO_SYS, enable_compression, e);
> +
> + gem_read(fd, out, 0, read_buf, bosize);
> +
> + for (i = 0; i < bosize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(ret);
> +
> + memset(read_buf, 0, ccssize);
> + gem_write(fd, out, 0, read_buf, ccssize);
> +
> + /* copy 'dst' BO's ccs into 'out' BO */
> + xy_ctrl_surf_copy_blt(fd, region, dst, out, ahnd,
> + ccssize, false, e);
> +
> + gem_read(fd, out, 0, read_buf, ccssize);
> +
> + for (i = 0; i < ccssize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(!ret);
> +}
> +
> +static void igt_copy_zero_pattern_xy_block_copy_blt(int fd, uint32_t region, uint32_t src,
> + uint32_t dst, uint32_t out, uint64_t ahnd,
> + int ccssize, uint8_t *pattern_buf, uint8_t *read_buf,
> + uint8_t *input_buf, int bosize,
> + struct intel_execution_engine2 *e)
> +{
> + int ret, i;
> + bool enable_compression = true;
> +
> + igt_info("copy zeros pattern to lmem BO with compression\n");
> +
> + gem_write(fd, src, 0, pattern_buf, bosize);
> + gem_write(fd, dst, 0, pattern_buf, bosize);
> + /* set ccs to random pattern */
> + xy_ctrl_surf_copy_blt(fd, region, src, dst, ahnd,
> + ccssize, true, e);
> +
> + memset(input_buf, 0, bosize);
> + gem_write(fd, src, 0, input_buf, bosize);
> +
> + /* copy 'src' to 'dst' with compression */
> + xy_block_copy_blt(fd, region, src, dst, ahnd, bosize,
> + SYS_TO_LOCAL, enable_compression, e);
> +
> + gem_write(fd, out, 0, pattern_buf, bosize);
> +
> + /* copy 'dst' BO back into 'out' BO */
> + xy_block_copy_blt(fd, region, dst, out, ahnd, bosize,
> + LOCAL_TO_SYS, enable_compression, e);
> +
> + gem_read(fd, out, 0, read_buf, bosize);
> +
> + for (i = 0; i < bosize; i++) {
> + if (read_buf[i] != input_buf[i])
> + ret++;
> + }
> + igt_assert(!ret);
> +
> + memset(read_buf, 0, bosize);
> + gem_read(fd, dst, 0, read_buf, bosize);
> +
> + for (i = 0; i < bosize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(!ret);
> +
> + memset(read_buf, 0, ccssize);
> + gem_write(fd, out, 0, read_buf, ccssize);
> +
> + /* copy 'dst' BO's ccs into 'out' BO */
> + xy_ctrl_surf_copy_blt(fd, region, dst, out, ahnd,
> + ccssize, false, e);
> +
> + gem_read(fd, out, 0, read_buf, ccssize);
> +
> + for (i = 0; i < ccssize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(ret);
> +}
> +
> +static void igt_copy_repeat_pattern_xy_block_copy_blt(int fd, uint32_t region, uint32_t src,
> + uint32_t dst, uint32_t out, uint64_t ahnd,
> + int ccssize, uint8_t *pattern_buf, uint8_t *read_buf,
> + uint8_t *input_buf, int bosize,
> + struct intel_execution_engine2 *e)
> +{
> + int ret, i;
> + bool enable_compression = true;
> +
> + igt_info("copy repeat pattern to lmem BO with compression\n");
> +
> + gem_write(fd, src, 0, pattern_buf, bosize);
> + gem_write(fd, src, 0, pattern_buf, ccssize);
> +
> + xy_ctrl_surf_copy_blt(fd, region, src, dst, ahnd,
> + ccssize, true, e);
> + gem_write(fd, dst, 0, pattern_buf, bosize);
> +
> + /* generate repeating pattern */
> + input_buf[0] = (uint8_t)rand();
> + input_buf[1] = (uint8_t)rand();
> + input_buf[2] = (uint8_t)rand();
> + input_buf[3] = (uint8_t)rand();
> + for (i = 4; i < bosize; i++)
> + input_buf[i] = input_buf[i - 4];
> + gem_write(fd, src, 0, input_buf, bosize);
> +
> + xy_block_copy_blt(fd, region, src, dst, ahnd, bosize,
> + SYS_TO_LOCAL, enable_compression, e);
> +
> + memset(read_buf, 0, bosize);
> + gem_write(fd, out, 0, read_buf, bosize);
> +
> + /* copy 'dst' BO back into 'out' BO */
> + xy_block_copy_blt(fd, region, dst, out, ahnd, bosize,
> + LOCAL_TO_SYS, enable_compression, e);
> +
> + gem_read(fd, out, 0, read_buf, bosize);
> +
> + for (i = 0; i < bosize; i++) {
> + if (read_buf[i] != input_buf[i])
> + ret++;
> + }
> + igt_assert(!ret);
> +
> + memset(read_buf, 0, bosize);
> + gem_read(fd, dst, 0, read_buf, bosize);
> +
> + for (i = 0; i < bosize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(ret);
> +
> + memset(read_buf, 0, ccssize);
> + gem_write(fd, out, 0, read_buf, ccssize);
> +
> + /* copy 'dst' BO's ccs into 'out' BO */
> + xy_ctrl_surf_copy_blt(fd, region, dst, out, ahnd,
> + ccssize, false, e);
> +
> + gem_read(fd, out, 0, read_buf, ccssize);
> +
> + for (i = 0; i < ccssize; i++) {
> + if (read_buf[i] != pattern_buf[i])
> + ret++;
> + }
> + igt_assert(ret);
> +}
> +
> +/*
> + * Allocate a BO in SMEM.
> + * Fill a pattern
> + * Use XY_BLOCK_COPY_BLT to copy it to LMEM with compression enabled
> + * Clear the BO in SMEM, and the pattern_buf in which the pattern was
> + * stored
> + * Use XY_BLOCK_COPY_BLT to copy it back to the BO in SMEM with
> + * resolve
> + * Compare the value in the BO in SMEM matches the pattern
> + */
> +static void test_ccs(int fd, int size, uint32_t region, char *sub_name,
> + struct intel_execution_engine2 *e)
> +{
> + int bosize, ccssize, ret, i;
> + int start, end;
> + uint32_t src, dst, out;
> + uint8_t *pattern_buf, *input_buf, *read_buf;
> + uint64_t ahnd;
> + struct timeval tv;
> +
> + ahnd = get_reloc_ahnd(fd, 0);
Ok, test uses default context.
> +
> + if (size > 0) {
> + start = size;
> + end = start + 1;
> + } else {
> + start = BOSIZE_MIN;
> + end = BOSIZE_MAX;
> + }
> +
> + for (bosize = start; bosize < end; bosize *= 2) {
> + /* allocate working buffers */
> + pattern_buf = malloc(bosize);
> + igt_assert(pattern_buf);
> + input_buf = malloc(bosize);
> + igt_assert(input_buf);
> + read_buf = malloc(bosize);
> + igt_assert(read_buf);
> +
> + ccssize = bosize / CCS_RATIO;
> +
> + /* allocate working BOs in the right location */
> + src = gem_create_in_memory_regions(fd, bosize,
> + INTEL_MEMORY_REGION_ID(I915_SYSTEM_MEMORY, 0));
> + dst = gem_create_in_memory_regions(fd, bosize, region);
> + out = gem_create_in_memory_regions(fd, bosize,
> + INTEL_MEMORY_REGION_ID(I915_SYSTEM_MEMORY, 0));
Be aware requested bosize can be less or equal to gem object created.
So passing requested size to allocator can lead to failures.
> +
> + /* fill in random pattern */
> + ret = gettimeofday(&tv, NULL);
> + igt_assert(!ret);
> + srandom((int)tv.tv_usec);
> +
> + for (i = 0; i < bosize; i++)
> + pattern_buf[i] = (uint8_t)rand();
> +
> + igt_info("progress: bosize %d, ccssize %d\n", bosize, ccssize);
> +
> + igt_dynamic_f("write_read_in_ccs_surface-%s-%s", sub_name, e->name)
> + igt_wr_xy_ctrl_surf_copy_blt(fd, region, src, dst, out, ahnd,
> + ccssize, pattern_buf, read_buf,
> + bosize, e);
> + igt_dynamic_f("verify_compression_of_random_data-%s-%s", sub_name, e->name)
> + igt_overwritten_xy_block_copy_blt(fd, region, src, dst, out, ahnd,
> + ccssize, pattern_buf, read_buf,
> + bosize, e);
> + igt_dynamic_f("verify_corrupted_pattern_in_ccs_surface-%s-%s", sub_name, e->name)
> + igt_corrupted_xy_ctrl_surf_copy_blt(fd, region, src, dst, out, ahnd,
> + ccssize, pattern_buf, read_buf,
> + bosize, e);
> + igt_dynamic_f("copy_zero_pattern_with_compression-%s-%s", sub_name, e->name)
> + igt_copy_zero_pattern_xy_block_copy_blt(fd, region, src, dst, out, ahnd,
> + ccssize, pattern_buf, read_buf,
> + input_buf, bosize, e);
> + igt_dynamic_f("copy_repeat_pattern_with_compression-%s-%s", sub_name, e->name)
> + igt_copy_repeat_pattern_xy_block_copy_blt(fd, region, src, dst, out, ahnd,
> + ccssize, pattern_buf, read_buf,
> + input_buf, bosize, e);
> +
> + gem_close(fd, out);
> + gem_close(fd, dst);
> + gem_close(fd, src);
> + free(read_buf);
> + free(input_buf);
> + free(pattern_buf);
> + }
> +
> + put_ahnd(ahnd);
> +}
> +
> +igt_main
> +{
> + struct drm_i915_query_memory_regions *query_info;
> + struct intel_execution_engine2 *e;
> + struct igt_collection *regions, *set;
> + char *sub_name;
> + uint32_t region;
> + int drm_fd;
> +
> + igt_fixture {
> + drm_fd = drm_open_driver(DRIVER_INTEL);
> + igt_require_gem(drm_fd);
> + igt_require(AT_LEAST_GEN(intel_get_drm_devid(drm_fd), 12) > 0);
> + igt_require(HAS_FLAT_CCS(intel_get_drm_devid(drm_fd)));
> +
> + query_info = gem_get_query_memory_regions(drm_fd);
> + igt_require(query_info);
> +
> + set = get_memory_region_set(query_info, I915_DEVICE_MEMORY);
> + }
> +
> + igt_subtest_with_dynamic("basic-gem-ccs-4K") {
> + for_each_physical_engine(drm_fd, e) {
> + if (!gem_engine_can_block_copy(drm_fd, e))
> + continue;
> +
> + for_each_combination(regions, 1, set) {
> + sub_name = memregion_dynamic_subtest_name(regions);
> + region = igt_collection_get_value(regions, 0);
> + test_ccs(drm_fd, 4 * 1024, region, sub_name, e);
> + free(sub_name);
> + }
> + }
> + }
> +
> + igt_subtest_with_dynamic("basic-gem-ccs-64K") {
> + for_each_physical_engine(drm_fd, e) {
> + if (!gem_engine_can_block_copy(drm_fd, e))
> + continue;
> +
> + for_each_combination(regions, 1, set) {
> + sub_name = memregion_dynamic_subtest_name(regions);
> + region = igt_collection_get_value(regions, 0);
> + test_ccs(drm_fd, 64 * 1024, region, sub_name, e);
> + free(sub_name);
> + }
> + }
> + }
> +
> + igt_subtest_with_dynamic("basic-gem-ccs-1M") {
> + for_each_physical_engine(drm_fd, e) {
> + if (!gem_engine_can_block_copy(drm_fd, e))
> + continue;
> +
> + for_each_combination(regions, 1, set) {
> + sub_name = memregion_dynamic_subtest_name(regions);
> + region = igt_collection_get_value(regions, 0);
> + test_ccs(drm_fd, 1024 * 1024, region, sub_name, e);
> + free(sub_name);
> + }
> + }
> + }
> +
> + igt_subtest_with_dynamic("basic-gem-ccs-all") {
> + for_each_physical_engine(drm_fd, e) {
> + if (!gem_engine_can_block_copy(drm_fd, e))
> + continue;
> +
> + for_each_combination(regions, 1, set) {
> + sub_name = memregion_dynamic_subtest_name(regions);
> + region = igt_collection_get_value(regions, 0);
> + test_ccs(drm_fd, 0, region, sub_name, e);
> + free(sub_name);
> + }
> + }
> + }
All above looks same with some differences, write a macro or
function to avoid code duplication.
Last thing - you should also provide additional test where non
compressed block copy command is used, otherwise we won't test
that on TGL. I'm not sure gem_ccs.c is good place for this test,
so create a new one or maybe gem_blits? I got no strong preference.
--
Zbigniew
> +
> + igt_fixture {
> + close(drm_fd);
> + }
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 7b7d6bf8..48b6f5a2 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -106,6 +106,7 @@ i915_progs = [
> 'gem_blits',
> 'gem_busy',
> 'gem_caching',
> + 'gem_ccs',
> 'gem_close',
> 'gem_close_race',
> 'gem_concurrent_blit',
> --
> 2.25.1
>
More information about the Intel-gfx-trybot
mailing list