[igt-dev] [PATCH i-g-t] tests/amdgpu: add uvd encoder test

vitaly.prosyak at amd.com vitaly.prosyak at amd.com
Thu Jul 6 00:00:25 UTC 2023


From: Vitaly Prosyak <vitaly.prosyak at amd.com>

Ported and refactored drmlib uvd_enc_tests.c and  the following is done:

1. Remove everywhere global variables.
2. Reuse common functions from amd_mmd_shared.h
3. Properly formatted code to meet igt guidelines.

Signed-off-by: Vitaly Prosyak <vitaly.prosyak at amd.com>
Acked-by: Leo Liu <leo.liu at amd.com>
---
 tests/amdgpu/amd_uvd_enc.c | 337 +++++++++++++++++++++++++++++++++++++
 tests/amdgpu/meson.build   |   1 +
 2 files changed, 338 insertions(+)
 create mode 100644 tests/amdgpu/amd_uvd_enc.c

diff --git a/tests/amdgpu/amd_uvd_enc.c b/tests/amdgpu/amd_uvd_enc.c
new file mode 100644
index 000000000..e3e85522f
--- /dev/null
+++ b/tests/amdgpu/amd_uvd_enc.c
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: MIT
+// Copyright 2023 Advanced Micro Devices, Inc.
+// Copyright 2017 Advanced Micro Devices, Inc.
+
+#include "lib/amdgpu/amd_mmd_shared.h"
+
+static bool
+is_uvd_enc_enable(amdgpu_device_handle device_handle)
+{
+	int r;
+	struct drm_amdgpu_info_hw_ip info = {};
+
+	r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_UVD_ENC, 0, &info);
+
+	if (!info.available_rings)
+		igt_info("\n\nThe ASIC NOT support UVD ENC, test skipped\n");
+
+	return (r == 0 && (info.available_rings ? true : false));
+}
+
+static void
+amdgpu_uvd_enc_create(amdgpu_device_handle device_handle,
+					struct uvd_enc_context *context)
+{
+	context->enc.width = 160;
+	context->enc.height = 128;
+
+	context->uvd.num_resources  = 0;
+	alloc_resource(device_handle, &context->enc.session,
+			128 * 1024, AMDGPU_GEM_DOMAIN_GTT);
+	context->uvd.resources[context->uvd.num_resources++] = context->enc.session.handle;
+	context->uvd.resources[context->uvd.num_resources++] = context->uvd.ib_handle;
+}
+
+static void
+check_result(struct amdgpu_uvd_enc *enc)
+{
+	uint64_t sum;
+	uint32_t s = 175602;
+	uint32_t *ptr, size;
+	int j, r;
+
+	r = amdgpu_bo_cpu_map(enc->fb.handle, (void **)&enc->fb.ptr);
+	igt_assert_eq(r, 0);
+	ptr = (uint32_t *)enc->fb.ptr;
+	size = ptr[6];
+	r = amdgpu_bo_cpu_unmap(enc->fb.handle);
+	igt_assert_eq(r, 0);
+	r = amdgpu_bo_cpu_map(enc->bs.handle, (void **)&enc->bs.ptr);
+	igt_assert_eq(r, 0);
+	for (j = 0, sum = 0; j < size; ++j)
+		sum += enc->bs.ptr[j];
+	igt_assert_eq(sum, s);
+	r = amdgpu_bo_cpu_unmap(enc->bs.handle);
+	igt_assert_eq(r, 0);
+
+}
+
+static void
+amdgpu_uvd_enc_session_init(amdgpu_device_handle device_handle,
+		struct uvd_enc_context *context)
+{
+	int len, r;
+
+	len = 0;
+	memcpy((context->uvd.ib_cpu + len), uve_session_info, sizeof(uve_session_info));
+	len += sizeof(uve_session_info) / 4;
+	context->uvd.ib_cpu[len++] = context->enc.session.addr >> 32;
+	context->uvd.ib_cpu[len++] = context->enc.session.addr;
+
+	memcpy((context->uvd.ib_cpu + len), uve_task_info, sizeof(uve_task_info));
+	len += sizeof(uve_task_info) / 4;
+	context->uvd.ib_cpu[len++] = 0x000000d8;
+	context->uvd.ib_cpu[len++] = 0x00000000;
+	context->uvd.ib_cpu[len++] = 0x00000000;
+
+	memcpy((context->uvd.ib_cpu + len), uve_op_init, sizeof(uve_op_init));
+	len += sizeof(uve_op_init) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_session_init, sizeof(uve_session_init));
+	len += sizeof(uve_session_init) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_layer_ctrl, sizeof(uve_layer_ctrl));
+	len += sizeof(uve_layer_ctrl) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_slice_ctrl, sizeof(uve_slice_ctrl));
+	len += sizeof(uve_slice_ctrl) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_spec_misc, sizeof(uve_spec_misc));
+	len += sizeof(uve_spec_misc) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_rc_session_init,
+			sizeof(uve_rc_session_init));
+	len += sizeof(uve_rc_session_init) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_deblocking_filter,
+			sizeof(uve_deblocking_filter));
+	len += sizeof(uve_deblocking_filter) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_quality_params,
+			sizeof(uve_quality_params));
+	len += sizeof(uve_quality_params) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_op_init_rc, sizeof(uve_op_init_rc));
+	len += sizeof(uve_op_init_rc) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_op_init_rc_vbv_level,
+			sizeof(uve_op_init_rc_vbv_level));
+	len += sizeof(uve_op_init_rc_vbv_level) / 4;
+
+	r = submit(device_handle, &context->uvd, len, AMDGPU_HW_IP_UVD_ENC);
+	igt_assert_eq(r, 0);
+}
+
+static void
+amdgpu_uvd_enc_encode(amdgpu_device_handle device_handle,
+		struct uvd_enc_context *context)
+{
+	int len, r, i;
+	uint64_t luma_offset, chroma_offset;
+	unsigned int luma_size;
+	uint32_t vbuf_size, bs_size = 0x003f4800, cpb_size;
+	unsigned int align = (context->uvd.family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
+
+	vbuf_size = ALIGN(context->enc.width, align) *
+			ALIGN(context->enc.height, 16) * 1.5;
+	cpb_size = vbuf_size * 10;
+	context->uvd.num_resources  = 0;
+	alloc_resource(device_handle, &context->enc.fb, 4096,
+			AMDGPU_GEM_DOMAIN_VRAM);
+	context->uvd.resources[context->uvd.num_resources++] = context->enc.fb.handle;
+	alloc_resource(device_handle, &context->enc.bs, bs_size,
+			AMDGPU_GEM_DOMAIN_VRAM);
+	context->uvd.resources[context->uvd.num_resources++] = context->enc.bs.handle;
+	alloc_resource(device_handle, &context->enc.vbuf, vbuf_size,
+			AMDGPU_GEM_DOMAIN_VRAM);
+	context->uvd.resources[context->uvd.num_resources++] = context->enc.vbuf.handle;
+	alloc_resource(device_handle, &context->enc.cpb, cpb_size,
+			AMDGPU_GEM_DOMAIN_VRAM);
+	context->uvd.resources[context->uvd.num_resources++] = context->enc.cpb.handle;
+	context->uvd.resources[context->uvd.num_resources++] = context->uvd.ib_handle;
+
+	r = amdgpu_bo_cpu_map(context->enc.vbuf.handle, (void **)&context->enc.vbuf.ptr);
+	igt_assert_eq(r, 0);
+
+	memset(context->enc.vbuf.ptr, 0, vbuf_size);
+	for (i = 0; i < context->enc.height; ++i) {
+		memcpy(context->enc.vbuf.ptr, (frame + i * context->enc.width),
+				context->enc.width);
+		context->enc.vbuf.ptr += ALIGN(context->enc.width, align);
+	}
+	for (i = 0; i < context->enc.height / 2; ++i) {
+		memcpy(context->enc.vbuf.ptr, ((frame + context->enc.height *
+				context->enc.width) + i * context->enc.width), context->enc.width);
+		context->enc.vbuf.ptr += ALIGN(context->enc.width, align);
+	}
+
+	r = amdgpu_bo_cpu_unmap(context->enc.vbuf.handle);
+	igt_assert_eq(r, 0);
+
+	len = 0;
+	memcpy((context->uvd.ib_cpu + len), uve_session_info, sizeof(uve_session_info));
+	len += sizeof(uve_session_info) / 4;
+	context->uvd.ib_cpu[len++] = context->enc.session.addr >> 32;
+	context->uvd.ib_cpu[len++] = context->enc.session.addr;
+
+	memcpy((context->uvd.ib_cpu + len), uve_task_info, sizeof(uve_task_info));
+	len += sizeof(uve_task_info) / 4;
+	context->uvd.ib_cpu[len++] = 0x000005e0;
+	context->uvd.ib_cpu[len++] = 0x00000001;
+	context->uvd.ib_cpu[len++] = 0x00000001;
+
+	memcpy((context->uvd.ib_cpu + len), uve_nalu_buffer_1, sizeof(uve_nalu_buffer_1));
+	len += sizeof(uve_nalu_buffer_1) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_nalu_buffer_2, sizeof(uve_nalu_buffer_2));
+	len += sizeof(uve_nalu_buffer_2) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_nalu_buffer_3, sizeof(uve_nalu_buffer_3));
+	len += sizeof(uve_nalu_buffer_3) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_nalu_buffer_4, sizeof(uve_nalu_buffer_4));
+	len += sizeof(uve_nalu_buffer_4) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_slice_header, sizeof(uve_slice_header));
+	len += sizeof(uve_slice_header) / 4;
+
+	context->uvd.ib_cpu[len++] = 0x00000254;
+	context->uvd.ib_cpu[len++] = 0x00000010;
+	context->uvd.ib_cpu[len++] = context->enc.cpb.addr >> 32;
+	context->uvd.ib_cpu[len++] = context->enc.cpb.addr;
+	memcpy((context->uvd.ib_cpu + len), uve_ctx_buffer, sizeof(uve_ctx_buffer));
+	len += sizeof(uve_ctx_buffer) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_bitstream_buffer,
+			sizeof(uve_bitstream_buffer));
+	len += sizeof(uve_bitstream_buffer) / 4;
+	context->uvd.ib_cpu[len++] = 0x00000000;
+	context->uvd.ib_cpu[len++] = context->enc.bs.addr >> 32;
+	context->uvd.ib_cpu[len++] = context->enc.bs.addr;
+	context->uvd.ib_cpu[len++] = 0x003f4800;
+	context->uvd.ib_cpu[len++] = 0x00000000;
+
+	memcpy((context->uvd.ib_cpu + len), uve_feedback_buffer,
+			sizeof(uve_feedback_buffer));
+	len += sizeof(uve_feedback_buffer) / 4;
+	context->uvd.ib_cpu[len++] = context->enc.fb.addr >> 32;
+	context->uvd.ib_cpu[len++] = context->enc.fb.addr;
+	context->uvd.ib_cpu[len++] = 0x00000010;
+	context->uvd.ib_cpu[len++] = 0x00000028;
+
+	memcpy((context->uvd.ib_cpu + len), uve_feedback_buffer_additional,
+			sizeof(uve_feedback_buffer_additional));
+	len += sizeof(uve_feedback_buffer_additional) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_intra_refresh, sizeof(uve_intra_refresh));
+	len += sizeof(uve_intra_refresh) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_layer_select, sizeof(uve_layer_select));
+	len += sizeof(uve_layer_select) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_rc_layer_init, sizeof(uve_rc_layer_init));
+	len += sizeof(uve_rc_layer_init) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_layer_select, sizeof(uve_layer_select));
+	len += sizeof(uve_layer_select) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_rc_per_pic, sizeof(uve_rc_per_pic));
+	len += sizeof(uve_rc_per_pic) / 4;
+
+	luma_size = ALIGN(context->enc.width, align) * ALIGN(context->enc.height, 16);
+	luma_offset = context->enc.vbuf.addr;
+	chroma_offset = luma_offset + luma_size;
+	context->uvd.ib_cpu[len++] = 0x00000054;
+	context->uvd.ib_cpu[len++] = 0x0000000c;
+	context->uvd.ib_cpu[len++] = 0x00000002;
+	context->uvd.ib_cpu[len++] = 0x003f4800;
+	context->uvd.ib_cpu[len++] = luma_offset >> 32;
+	context->uvd.ib_cpu[len++] = luma_offset;
+	context->uvd.ib_cpu[len++] = chroma_offset >> 32;
+	context->uvd.ib_cpu[len++] = chroma_offset;
+	memcpy((context->uvd.ib_cpu + len), uve_encode_param, sizeof(uve_encode_param));
+	context->uvd.ib_cpu[len] = ALIGN(context->enc.width, align);
+	context->uvd.ib_cpu[len + 1] = ALIGN(context->enc.width, align);
+	len += sizeof(uve_encode_param) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_op_speed_enc_mode,
+			sizeof(uve_op_speed_enc_mode));
+	len += sizeof(uve_op_speed_enc_mode) / 4;
+
+	memcpy((context->uvd.ib_cpu + len), uve_op_encode, sizeof(uve_op_encode));
+	len += sizeof(uve_op_encode) / 4;
+
+	r = submit(device_handle, &context->uvd, len, AMDGPU_HW_IP_UVD_ENC);
+	igt_assert_eq(r, 0);
+
+	check_result(&context->enc);
+
+	free_resource(&context->enc.fb);
+	free_resource(&context->enc.bs);
+	free_resource(&context->enc.vbuf);
+	free_resource(&context->enc.cpb);
+}
+
+static void
+amdgpu_uvd_enc_destroy(amdgpu_device_handle device_handle,
+		struct uvd_enc_context *context)
+{
+	int len, r;
+
+	context->uvd.num_resources  = 0;
+	context->uvd.resources[context->uvd.num_resources++] = context->uvd.ib_handle;
+
+	len = 0;
+	memcpy((context->uvd.ib_cpu + len), uve_session_info, sizeof(uve_session_info));
+	len += sizeof(uve_session_info) / 4;
+	context->uvd.ib_cpu[len++] = context->enc.session.addr >> 32;
+	context->uvd.ib_cpu[len++] = context->enc.session.addr;
+
+	memcpy((context->uvd.ib_cpu + len), uve_task_info, sizeof(uve_task_info));
+	len += sizeof(uve_task_info) / 4;
+	context->uvd.ib_cpu[len++] = 0xffffffff;
+	context->uvd.ib_cpu[len++] = 0x00000002;
+	context->uvd.ib_cpu[len++] = 0x00000000;
+
+	memcpy((context->uvd.ib_cpu + len), uve_op_close, sizeof(uve_op_close));
+	len += sizeof(uve_op_close) / 4;
+
+	r = submit(device_handle, &context->uvd, len, AMDGPU_HW_IP_UVD_ENC);
+	igt_assert_eq(r, 0);
+
+	free_resource(&context->enc.session);
+}
+
+igt_main
+{
+	amdgpu_device_handle device;
+	struct uvd_enc_context context = {};
+	int fd = -1;
+
+	igt_fixture {
+		uint32_t major, minor;
+		int err;
+
+		fd = drm_open_driver(DRIVER_AMDGPU);
+		err = amdgpu_device_initialize(fd, &major, &minor, &device);
+		igt_require(err == 0);
+		igt_info("Initialized amdgpu, driver version %d.%d\n",
+			 major, minor);
+		err = mmd_context_init(device, &context.uvd);
+		igt_require(err == 0);
+
+		igt_skip_on(!is_uvd_enc_enable(device));
+	}
+
+	igt_describe("Test whether uvd enc is created");
+	igt_subtest("uvd_enc_create")
+	amdgpu_uvd_enc_create(device, &context);
+
+	igt_describe("Test whether uvd enc session init");
+	igt_subtest("amdgpu_uvd_enc_session_init")
+	amdgpu_uvd_enc_session_init(device, &context);
+
+	igt_describe("Test whether uvd enc encode");
+	igt_subtest("amdgpu_uvd_enc_encode")
+	amdgpu_uvd_enc_encode(device, &context);
+
+	igt_describe("Test whether uvd enc is destroyed");
+	igt_subtest("uvd_enc_destroy")
+	amdgpu_uvd_enc_destroy(device, &context);
+
+	igt_fixture {
+		mmd_context_clean(device, &context.uvd);
+		amdgpu_device_deinitialize(device);
+		drm_close_driver(fd);
+	}
+}
diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build
index 690bc38db..576333aab 100644
--- a/tests/amdgpu/meson.build
+++ b/tests/amdgpu/meson.build
@@ -25,6 +25,7 @@ if libdrm_amdgpu.found()
 			  'amd_prime',
 			  'amd_psr',
 			  'amd_uvd_dec',
+			  'amd_uvd_enc',
 			  'amd_vrr_range',
 			]
 	amdgpu_deps += libdrm_amdgpu
-- 
2.25.1



More information about the igt-dev mailing list