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 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx