[PATCH libdrm 5/5] [libdrm] add syncobj timeline tests

Daniel Vetter daniel at ffwll.ch
Tue Nov 6 10:25:58 UTC 2018


On Mon, Nov 05, 2018 at 10:07:24AM +0000, Zhou, David(ChunMing) wrote:
> 
> 
> > -----Original Message-----
> > From: Daniel Vetter <daniel.vetter at ffwll.ch> On Behalf Of Daniel Vetter
> > Sent: Monday, November 05, 2018 5:39 PM
> > To: Zhou, David(ChunMing) <David1.Zhou at amd.com>
> > Cc: dri-devel at lists.freedesktop.org; amd-gfx at lists.freedesktop.org
> > Subject: Re: [PATCH libdrm 5/5] [libdrm] add syncobj timeline tests
> > 
> > On Fri, Nov 02, 2018 at 04:26:49PM +0800, Chunming Zhou wrote:
> > > Signed-off-by: Chunming Zhou <david1.zhou at amd.com>
> > > ---
> > >  tests/amdgpu/Makefile.am     |   3 +-
> > >  tests/amdgpu/amdgpu_test.c   |  12 ++
> > >  tests/amdgpu/amdgpu_test.h   |  21 +++
> > >  tests/amdgpu/meson.build     |   2 +-
> > >  tests/amdgpu/syncobj_tests.c | 263
> > > +++++++++++++++++++++++++++++++++++
> > >  5 files changed, 299 insertions(+), 2 deletions(-)  create mode
> > > 100644 tests/amdgpu/syncobj_tests.c
> > 
> > This testcase seems very much a happy sunday scenario, no tests at all for
> > corner cases, invalid input, and generally trying to pull the kernel over the
> > table. I think we need a lot more, and preferrably in igt, where we already
> > have a good baseline of drm_syncobj tests.
> Hi Daniel,
> 
> OK, if you insist on that, I would switch to implement a timeline test on IGT.
> Btw,  timeline syncobj test needs based on command submission, Can I write it with amdgpu driver on IGT?
> And after that, where should I send igt patch to review? 

We have used vgem and sw_fence in the past to be able to have very
controlled timelines. This allows us to write generic testcases. The
current igt tests for syncobj are neither i915 nor amdgpu specific.

You might still want to have an amgpu test on top, we do have some i915
tests for the i915 execbuf integration of syncobj of course. But that's a
fairly minor part of the syncobj api.

For contributing to igt, see https://gitlab.freedesktop.org/drm/igt-gpu-tools/blob/master/CONTRIBUTING.md

> Last, if you are free, Could you also take a look the u/k interface of timeline syncobj?

Looked reasonable, the detailed questions need userspace (and so probably
better answered by someone who has mesa/vk/gl clue). I can help review
corner cases of the uapi, but that's much easier to do once we have
test-cases to exercise them all. See existing igts for an idea of what
exhaustive testing of uapi corner cases looks like.
-Daniel


> 
> 
> Thanks,
> David Zhou
> > -Daniel
> > 
> > >
> > > diff --git a/tests/amdgpu/Makefile.am b/tests/amdgpu/Makefile.am index
> > > 447ff217..d3fbe2bb 100644
> > > --- a/tests/amdgpu/Makefile.am
> > > +++ b/tests/amdgpu/Makefile.am
> > > @@ -33,4 +33,5 @@ amdgpu_test_SOURCES = \
> > >  	vcn_tests.c \
> > >  	uve_ib.h \
> > >  	deadlock_tests.c \
> > > -	vm_tests.c
> > > +	vm_tests.c \
> > > +	syncobj_tests.c
> > > diff --git a/tests/amdgpu/amdgpu_test.c b/tests/amdgpu/amdgpu_test.c
> > > index 96fcd687..cdcb93a5 100644
> > > --- a/tests/amdgpu/amdgpu_test.c
> > > +++ b/tests/amdgpu/amdgpu_test.c
> > > @@ -56,6 +56,7 @@
> > >  #define UVD_ENC_TESTS_STR "UVD ENC Tests"
> > >  #define DEADLOCK_TESTS_STR "Deadlock Tests"
> > >  #define VM_TESTS_STR "VM Tests"
> > > +#define SYNCOBJ_TIMELINE_TESTS_STR "SYNCOBJ TIMELINE Tests"
> > >
> > >  /**
> > >   *  Open handles for amdgpu devices
> > > @@ -116,6 +117,12 @@ static CU_SuiteInfo suites[] = {
> > >  		.pCleanupFunc = suite_vm_tests_clean,
> > >  		.pTests = vm_tests,
> > >  	},
> > > +	{
> > > +		.pName = SYNCOBJ_TIMELINE_TESTS_STR,
> > > +		.pInitFunc = suite_syncobj_timeline_tests_init,
> > > +		.pCleanupFunc = suite_syncobj_timeline_tests_clean,
> > > +		.pTests = syncobj_timeline_tests,
> > > +	},
> > >
> > >  	CU_SUITE_INFO_NULL,
> > >  };
> > > @@ -165,6 +172,11 @@ static Suites_Active_Status suites_active_stat[] = {
> > >  			.pName = VM_TESTS_STR,
> > >  			.pActive = suite_vm_tests_enable,
> > >  		},
> > > +		{
> > > +			.pName = SYNCOBJ_TIMELINE_TESTS_STR,
> > > +			.pActive = suite_syncobj_timeline_tests_enable,
> > > +		},
> > > +
> > >  };
> > >
> > >
> > > diff --git a/tests/amdgpu/amdgpu_test.h b/tests/amdgpu/amdgpu_test.h
> > > index 0609a74b..946e91c2 100644
> > > --- a/tests/amdgpu/amdgpu_test.h
> > > +++ b/tests/amdgpu/amdgpu_test.h
> > > @@ -194,6 +194,27 @@ CU_BOOL suite_vm_tests_enable(void);
> > >   */
> > >  extern CU_TestInfo vm_tests[];
> > >
> > > +/**
> > > + * Initialize syncobj timeline test suite  */ int
> > > +suite_syncobj_timeline_tests_init();
> > > +
> > > +/**
> > > + * Deinitialize syncobj timeline test suite  */ int
> > > +suite_syncobj_timeline_tests_clean();
> > > +
> > > +/**
> > > + * Decide if the suite is enabled by default or not.
> > > + */
> > > +CU_BOOL suite_syncobj_timeline_tests_enable(void);
> > > +
> > > +/**
> > > + * Tests in syncobj timeline test suite  */ extern CU_TestInfo
> > > +syncobj_timeline_tests[];
> > > +
> > > +
> > >  /**
> > >   * Helper functions
> > >   */
> > > diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build index
> > > 4c1237c6..3ceec715 100644
> > > --- a/tests/amdgpu/meson.build
> > > +++ b/tests/amdgpu/meson.build
> > > @@ -24,7 +24,7 @@ if dep_cunit.found()
> > >      files(
> > >        'amdgpu_test.c', 'basic_tests.c', 'bo_tests.c', 'cs_tests.c',
> > >        'vce_tests.c', 'uvd_enc_tests.c', 'vcn_tests.c', 'deadlock_tests.c',
> > > -      'vm_tests.c',
> > > +      'vm_tests.c', 'syncobj_tests.c',
> > >      ),
> > >      dependencies : [dep_cunit, dep_threads],
> > >      include_directories : [inc_root, inc_drm,
> > > include_directories('../../amdgpu')],
> > > diff --git a/tests/amdgpu/syncobj_tests.c
> > > b/tests/amdgpu/syncobj_tests.c new file mode 100644 index
> > > 00000000..2a345490
> > > --- /dev/null
> > > +++ b/tests/amdgpu/syncobj_tests.c
> > > @@ -0,0 +1,263 @@
> > > +/*
> > > + * Copyright 2017 Advanced Micro Devices, Inc.
> > > + *
> > > + * Permission is hereby granted, free of charge, to any person
> > > +obtaining a
> > > + * copy of this software and associated documentation files (the
> > > +"Software"),
> > > + * to deal in the Software without restriction, including without
> > > +limitation
> > > + * the rights to use, copy, modify, merge, publish, distribute,
> > > +sublicense,
> > > + * and/or sell copies of the Software, and to permit persons to whom
> > > +the
> > > + * Software is furnished to do so, subject to the following conditions:
> > > + *
> > > + * The above copyright notice and this permission notice shall be
> > > +included in
> > > + * all copies or substantial portions of the Software.
> > > + *
> > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> > KIND,
> > > +EXPRESS OR
> > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> > > +MERCHANTABILITY,
> > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN
> > NO EVENT
> > > +SHALL
> > > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM,
> > > +DAMAGES OR
> > > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
> > > +OTHERWISE,
> > > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
> > THE USE
> > > +OR
> > > + * OTHER DEALINGS IN THE SOFTWARE.
> > > + *
> > > +*/
> > > +
> > > +#include "CUnit/Basic.h"
> > > +
> > > +#include "amdgpu_test.h"
> > > +#include "amdgpu_drm.h"
> > > +#include "amdgpu_internal.h"
> > > +#include <pthread.h>
> > > +
> > > +static  amdgpu_device_handle device_handle; static  uint32_t
> > > +major_version; static  uint32_t  minor_version;
> > > +
> > > +static void amdgpu_syncobj_timeline_test(void);
> > > +
> > > +CU_BOOL suite_syncobj_timeline_tests_enable(void)
> > > +{
> > > +	return CU_TRUE;
> > > +}
> > > +
> > > +int suite_syncobj_timeline_tests_init(void)
> > > +{
> > > +	int r;
> > > +
> > > +	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
> > > +				   &minor_version, &device_handle);
> > > +
> > > +	if (r) {
> > > +		if ((r == -EACCES) && (errno == EACCES))
> > > +			printf("\n\nError:%s. "
> > > +				"Hint:Try to run this test program as root.",
> > > +				strerror(errno));
> > > +		return CUE_SINIT_FAILED;
> > > +	}
> > > +
> > > +	return CUE_SUCCESS;
> > > +}
> > > +
> > > +int suite_syncobj_timeline_tests_clean(void)
> > > +{
> > > +	int r = amdgpu_device_deinitialize(device_handle);
> > > +
> > > +	if (r == 0)
> > > +		return CUE_SUCCESS;
> > > +	else
> > > +		return CUE_SCLEAN_FAILED;
> > > +}
> > > +
> > > +
> > > +CU_TestInfo syncobj_timeline_tests[] = {
> > > +	{ "syncobj timeline test",  amdgpu_syncobj_timeline_test },
> > > +	CU_TEST_INFO_NULL,
> > > +};
> > > +
> > > +#define GFX_COMPUTE_NOP  0xffff1000
> > > +#define SDMA_NOP  0x0
> > > +static int syncobj_command_submission_helper(uint32_t syncobj_handle,
> > bool
> > > +					     wait_or_signal, uint64_t point) {
> > > +	amdgpu_context_handle context_handle;
> > > +	amdgpu_bo_handle ib_result_handle;
> > > +	void *ib_result_cpu;
> > > +	uint64_t ib_result_mc_address;
> > > +	struct drm_amdgpu_cs_chunk chunks[2];
> > > +	struct drm_amdgpu_cs_chunk_data chunk_data;
> > > +	struct drm_amdgpu_cs_chunk_syncobj syncobj_data;
> > > +	struct amdgpu_cs_fence fence_status;
> > > +	amdgpu_bo_list_handle bo_list;
> > > +	amdgpu_va_handle va_handle;
> > > +	uint32_t expired, flags;
> > > +	int i, r;
> > > +	uint64_t seq_no;
> > > +	static uint32_t *ptr;
> > > +
> > > +	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
> > > +				    AMDGPU_GEM_DOMAIN_GTT, 0,
> > > +				    &ib_result_handle, &ib_result_cpu,
> > > +				    &ib_result_mc_address, &va_handle);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL,
> > > +			       &bo_list);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	ptr = ib_result_cpu;
> > > +
> > > +	for (i = 0; i < 16; ++i)
> > > +		ptr[i] = wait_or_signal ? GFX_COMPUTE_NOP: SDMA_NOP;
> > > +
> > > +	chunks[0].chunk_id = AMDGPU_CHUNK_ID_IB;
> > > +	chunks[0].length_dw = sizeof(struct drm_amdgpu_cs_chunk_ib) / 4;
> > > +	chunks[0].chunk_data = (uint64_t)(uintptr_t)&chunk_data;
> > > +	chunk_data.ib_data._pad = 0;
> > > +	chunk_data.ib_data.va_start = ib_result_mc_address;
> > > +	chunk_data.ib_data.ib_bytes = 16 * 4;
> > > +	chunk_data.ib_data.ip_type = wait_or_signal ?
> > AMDGPU_HW_IP_GFX :
> > > +		AMDGPU_HW_IP_DMA;
> > > +	chunk_data.ib_data.ip_instance = 0;
> > > +	chunk_data.ib_data.ring = 0;
> > > +	chunk_data.ib_data.flags = 0;
> > > +
> > > +	chunks[1].chunk_id = wait_or_signal ?
> > > +		AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT :
> > > +		AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL;
> > > +	chunks[1].length_dw = sizeof(struct
> > drm_amdgpu_cs_chunk_syncobj) / 4;
> > > +	chunks[1].chunk_data = (uint64_t)(uintptr_t)&syncobj_data;
> > > +	syncobj_data.handle = syncobj_handle;
> > > +	syncobj_data.point = point;
> > > +	syncobj_data.flags =
> > DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
> > > +
> > > +	r = amdgpu_cs_submit_raw(device_handle,
> > > +				 context_handle,
> > > +				 bo_list,
> > > +				 2,
> > > +				 chunks,
> > > +				 &seq_no);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +
> > > +	memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));
> > > +	fence_status.context = context_handle;
> > > +	fence_status.ip_type = wait_or_signal ? AMDGPU_HW_IP_GFX:
> > > +		AMDGPU_HW_IP_DMA;
> > > +	fence_status.ip_instance = 0;
> > > +	fence_status.ring = 0;
> > > +	fence_status.fence = seq_no;
> > > +
> > > +	r = amdgpu_cs_query_fence_status(&fence_status,
> > > +			AMDGPU_TIMEOUT_INFINITE,0, &expired);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	r = amdgpu_bo_list_destroy(bo_list);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,
> > > +				     ib_result_mc_address, 4096);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	r = amdgpu_cs_ctx_free(context_handle);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	return r;
> > > +}
> > > +
> > > +struct syncobj_point {
> > > +	uint32_t syncobj_handle;
> > > +	uint64_t point;
> > > +};
> > > +
> > > +static void *syncobj_wait(void *data) {
> > > +	struct syncobj_point *sp = (struct syncobj_point *)data;
> > > +	int r;
> > > +
> > > +	r = syncobj_command_submission_helper(sp->syncobj_handle, true,
> > > +					      sp->point);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	return (void *)r;
> > > +}
> > > +
> > > +static void *syncobj_signal(void *data) {
> > > +	struct syncobj_point *sp = (struct syncobj_point *)data;
> > > +	int r;
> > > +
> > > +	r = syncobj_command_submission_helper(sp->syncobj_handle,
> > false,
> > > +					      sp->point);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	return (void *)r;
> > > +}
> > > +
> > > +static void amdgpu_syncobj_timeline_test(void)
> > > +{
> > > +	static pthread_t wait_thread;
> > > +	static pthread_t signal_thread;
> > > +	static pthread_t c_thread;
> > > +	struct syncobj_point sp1, sp2, sp3;
> > > +	uint32_t syncobj_handle;
> > > +	uint64_t payload;
> > > +	uint64_t *p_payload;
> > > +	uint64_t wait_point;
> > > +	int r;
> > > +	void *tmp;
> > > +
> > > +	r =  amdgpu_cs_create_syncobj2(device_handle,
> > DRM_SYNCOBJ_CREATE_TYPE_TIMELINE,
> > > +				       &syncobj_handle);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	// wait on point 5
> > > +	sp1.syncobj_handle = syncobj_handle;
> > > +	sp1.point = 5;
> > > +	r = pthread_create(&wait_thread, NULL, syncobj_wait, &sp1);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	// signal on point 10
> > > +	sp2.syncobj_handle = syncobj_handle;
> > > +	sp2.point = 10;
> > > +	r = pthread_create(&signal_thread, NULL, syncobj_signal, &sp2);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +	r = pthread_join(wait_thread, &tmp);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +	CU_ASSERT_EQUAL(tmp, 0);
> > > +
> > > +	r = pthread_join(signal_thread, &tmp);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +	CU_ASSERT_EQUAL(tmp, 0);
> > > +
> > > +	//query timeline payload
> > > +	p_payload = &payload;
> > > +	r = amdgpu_cs_syncobj_query(device_handle, &syncobj_handle,
> > &p_payload, 1);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +	CU_ASSERT_EQUAL(payload, 10);
> > > +
> > > +	//signal on point 16
> > > +	sp3.syncobj_handle = syncobj_handle;
> > > +	sp3.point = 16;
> > > +	r = pthread_create(&c_thread, NULL, syncobj_signal, &sp3);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +	//CPU wait on point 16
> > > +	wait_point = 16;
> > > +	r = amdgpu_cs_syncobj_timeline_wait(device_handle,
> > &syncobj_handle,
> > > +					    &wait_point, 1,
> > > +					    0x10000000000, //10s
> > > +
> > DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |
> > > +
> > DRM_SYNCOBJ_WAIT_FLAGS_WAIT_COMPLETED |
> > > +
> > DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
> > > +					    NULL);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +	r = pthread_join(c_thread, &tmp);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +	CU_ASSERT_EQUAL(tmp, 0);
> > > +
> > > +	r = amdgpu_cs_destroy_syncobj(device_handle, syncobj_handle);
> > > +	CU_ASSERT_EQUAL(r, 0);
> > > +
> > > +}
> > > --
> > > 2.17.1
> > >
> > > _______________________________________________
> > > dri-devel mailing list
> > > dri-devel at lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> > 
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list