[Intel-gfx] [RFC i-g-t v2] tests/gem_exec_pad_to_size: Test object padding at execbuf

Chris Wilson chris at chris-wilson.co.uk
Wed Apr 1 06:06:53 PDT 2015


On Wed, Apr 01, 2015 at 12:21:14PM +0100, Tvrtko Ursulin wrote:

> +static int
> +exec(int fd, uint32_t handles[3], uint32_t pad_to_size[2], uint64_t *offsets)
> +{
> +	struct drm_i915_gem_execbuffer2 execbuf;
> +	struct local_drm_i915_gem_exec_object2 gem_exec[3];
> +	int ret = 0;
> +
> +	memset(gem_exec, 0, sizeof(gem_exec));
> +
> +	gem_exec[0].handle = handles[1];
> +	gem_exec[0].relocation_count = 0;
> +	gem_exec[0].relocs_ptr = 0;
> +	gem_exec[0].alignment = 0;
> +	gem_exec[0].offset = 0;
Ignore the unused fields (they are explicitly memset(0)) so that we can
focus on the important ones under test.

> +	gem_exec[0].flags = pad_to_size[0] ?
> +			    LOCAL_EXEC_OBJECT_PAD_TO_SIZE : 0;
> +	gem_exec[0].pad_to_size = pad_to_size[0];
> +

memset(execbuf) and skip boring fields
> +	execbuf.buffers_ptr = (uintptr_t)gem_exec;
> +	execbuf.buffer_count = 3;
> +	execbuf.batch_start_offset = 0;
> +	execbuf.batch_len = 8;
> +	execbuf.flags = I915_EXEC_RENDER;
This can be just I915_EXEC_DEFAULT (i.e. 0);


> +	if (drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf))
> +			ret = -errno;

> +	if (ret == 0) {
> +		gem_sync(fd, handles[0]);
Not required for this test. However... You probably want to do the
gem_sync() first. (Yes, there is an amusing reason to do :)

> +		if (offsets) {
> +			offsets[0] = gem_exec[0].offset;
> +			offsets[1] = gem_exec[1].offset;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static void
> +require_pad_to_size(int fd, uint32_t handles[3])
> +{
> +	igt_require(exec(fd, handles, (uint32_t[2]){ PAGE_SIZE, PAGE_SIZE },
> +			 NULL) == 0);
> +}
> +
> +static void
> +not_aligned(int fd, uint32_t handles[3])
> +{
> +	require_pad_to_size(fd, handles);
> +
> +	igt_require(exec(fd, handles, (uint32_t[2]){1 ,1},
> +			 NULL) == -EINVAL);
> +}
> +
> +static void
> +padding(int fd, uint32_t handles[3])
> +{
> +	uint32_t pad_to_size[2] = {0, 0};
> +	uint64_t offsets[2];
> +	uint32_t distance;
> +	bool neighbours = false;
> +	unsigned int try, idx;
> +	const unsigned int max_tries = 1024; /* Finger in the air. */
> +	uint32_t *loc_handles;
> +	uint32_t eb_handles[3];
> +
> +	require_pad_to_size(fd, handles);
> +
> +	loc_handles = calloc(max_tries * 2, sizeof(uint32_t));
> +	igt_assert(loc_handles);
> +
> +	/* Try with passed in handles first. */
> +	loc_handles[0] = handles[1];
> +	loc_handles[1] = handles[2];
> +
> +	/* Try to get two buffer object next to each other in GTT space. */
/* Try to get two buffer object next to each other in GTT space.
 * We presume that sequential reservations are likely to be aligned and
 * try until we find a pair that is.
 */

> +	for (try = 0, idx = 0; try < max_tries;) {
> +		eb_handles[0] = handles[0];
> +		eb_handles[1] = loc_handles[idx];
> +		eb_handles[2] = loc_handles[idx + 1];
> +
> +		igt_assert(exec(fd, eb_handles, (uint32_t[2]){0, 0},
> +				offsets) == 0);
> +
> +		if (offsets[1] > offsets[0]) {
> +			distance = offsets[1] - offsets[0];
> +			if (distance == PAGE_SIZE)
> +				neighbours = true;
> +			pad_to_size[0] = ALIGN(distance + PAGE_SIZE, PAGE_SIZE);
> +		} else {
> +			distance = offsets[0] - offsets[1];
> +			if (distance == PAGE_SIZE)
> +				neighbours = true;
> +			pad_to_size[1] = ALIGN(distance + PAGE_SIZE, PAGE_SIZE);
> +		}
> +
> +		if (neighbours)
> +			break;
> +
> +		try++;
> +		idx +=2;

Just use idx++ here and allocate a new handle one at a time. Just as
likely to be adjacent to the previous handle as the next one will be to
us. For extra paranoia, you could even try an evict-everything pass :)

Otherwise looks fine.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the Intel-gfx mailing list