[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