@@ -205,13 +205,12 @@ static void latency_from_ring(int fd,
const int gen = intel_gen(intel_get_drm_devid(fd));
const int has_64bit_reloc = gen >= 8;
struct drm_i915_gem_exec_object2 obj[3];
- struct drm_i915_gem_relocation_entry reloc;
struct drm_i915_gem_execbuffer2 execbuf;
- const unsigned int repeats = ring_size / 2;
+ uint64_t presumed_offset;
unsigned int other;
uint32_t *map, *results;
uint32_t ctx[2] = {};
- int i, j;
+ int j;
if (flags & PREEMPT) {
ctx[0] = gem_context_create(fd);
@@ -241,100 +240,81 @@ static void latency_from_ring(int fd,
map[0] = MI_BATCH_BUFFER_END;
gem_execbuf(fd, &execbuf);
- memset(&reloc,0, sizeof(reloc));
- obj[2].relocation_count = 1;
- obj[2].relocs_ptr = to_user_pointer(&reloc);
-
gem_set_domain(fd, obj[2].handle,
I915_GEM_DOMAIN_GTT,
I915_GEM_DOMAIN_GTT);
+ presumed_offset = obj[1].offset;
+ for (j = 0; j < 1024; j++) {
+ uint64_t offset = sizeof(uint32_t) * j + presumed_offset;
+ int i = 16 * j;
- reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
- reloc.write_domain = I915_GEM_DOMAIN_INSTRUCTION;
- reloc.presumed_offset = obj[1].offset;
- reloc.target_handle = flags & CORK ? 1 : 0;
+ /* MI_STORE_REG_MEM */
+ map[i++] = 0x24 << 23 | 1;
+ if (has_64bit_reloc)
+ map[i-1]++;
+ map[i++] = RCS_TIMESTAMP; /* ring local! */
+ map[i++] = offset;
+ if (has_64bit_reloc)
+ map[i++] = offset >> 32;
+
+ map[i++] = MI_BATCH_BUFFER_END;
+ }
+ igt_assert(ring_size <= 1024);
for_each_physical_engine(fd, other) {
- igt_spin_t *spin = NULL;
- IGT_CORK_HANDLE(c);
+ if (flags & PREEMPT && other == ring)
+ continue;
- gem_set_domain(fd, obj[2].handle,
- I915_GEM_DOMAIN_GTT,
- I915_GEM_DOMAIN_GTT);
+ for (int qlen = 1; qlen < ring_size/2; qlen *= 2) {
+ unsigned int count = 32 * ring_size / qlen;
+ igt_stats_t stats;
- if (flags & PREEMPT)
- spin = __igt_spin_batch_new(fd, ctx[0], ring, 0);
+ igt_stats_init_with_size(&stats, count);
+ for (unsigned int rep = 0; rep < count; rep++) {
+ igt_spin_t *spin = NULL;
+ IGT_CORK_HANDLE(c);
- if (flags & CORK) {
- obj[0].handle = igt_cork_plug(&c, fd);
- execbuf.buffers_ptr = to_user_pointer(&obj[0]);
- execbuf.buffer_count = 3;
- }
+ if (flags & PREEMPT)
+ spin = __igt_spin_batch_new(fd, ctx[0], other, 0);
- for (j = 0; j < repeats; j++) {
- uint64_t offset;
-
- execbuf.flags &= ~ENGINE_FLAGS;
- execbuf.flags |= ring;
-
- execbuf.batch_start_offset = 64 * j;
- reloc.offset =
- execbuf.batch_start_offset + sizeof(uint32_t);
- reloc.delta = sizeof(uint32_t) * j;
-
- reloc.presumed_offset = obj[1].offset;
- offset = reloc.presumed_offset;
- offset += reloc.delta;
-
- i = 16 * j;
- /* MI_STORE_REG_MEM */
- map[i++] = 0x24 << 23 | 1;
- if (has_64bit_reloc)
- map[i-1]++;
- map[i++] = RCS_TIMESTAMP; /* ring local! */
- map[i++] = offset;
- if (has_64bit_reloc)
- map[i++] = offset >> 32;
- map[i++] = MI_BATCH_BUFFER_END;
-
- gem_execbuf(fd, &execbuf);
-
- execbuf.flags &= ~ENGINE_FLAGS;
- execbuf.flags |= other;
-
- execbuf.batch_start_offset = 64 * (j + repeats);
- reloc.offset =
- execbuf.batch_start_offset + sizeof(uint32_t);
- reloc.delta = sizeof(uint32_t) * (j + repeats);
-
- reloc.presumed_offset = obj[1].offset;
- offset = reloc.presumed_offset;
- offset += reloc.delta;
-
- i = 16 * (j + repeats);
- /* MI_STORE_REG_MEM */
- map[i++] = 0x24 << 23 | 1;
- if (has_64bit_reloc)
- map[i-1]++;
- map[i++] = RCS_TIMESTAMP; /* ring local! */
- map[i++] = offset;
- if (has_64bit_reloc)
- map[i++] = offset >> 32;
- map[i++] = MI_BATCH_BUFFER_END;
-
- gem_execbuf(fd, &execbuf);
- }
+ if (flags & CORK) {
+ obj[0].handle = igt_cork_plug(&c, fd);
+ execbuf.buffers_ptr = to_user_pointer(&obj[0]);
+ execbuf.buffer_count = 3;
+ }
+
+ for (j = 0; j < qlen; j++) {
+ execbuf.flags &= ~ENGINE_FLAGS;
+ execbuf.flags |= ring;
+ execbuf.batch_start_offset = 64 * j;
+
+ gem_execbuf(fd, &execbuf);
- if (flags & CORK)
- igt_cork_unplug(&c);
- gem_set_domain(fd, obj[1].handle,
- I915_GEM_DOMAIN_GTT,
- I915_GEM_DOMAIN_GTT);
- igt_spin_batch_free(fd, spin);
+ execbuf.flags &= ~ENGINE_FLAGS;
+ execbuf.flags |= other;
+ execbuf.batch_start_offset = 64 * (j + qlen);
- igt_info("%s-%s delay: %.2f\n",
- name, e__->name,
- (results[2*repeats-1] - results[0]) / (double)repeats);
+ gem_execbuf(fd, &execbuf);
+ }
+
+ if (flags & CORK)
+ igt_cork_unplug(&c);
+ gem_set_domain(fd, obj[1].handle,
+ I915_GEM_DOMAIN_GTT,
+ I915_GEM_DOMAIN_GTT);
+ igt_spin_batch_free(fd, spin);
+
+ igt_assert_eq_u64(obj[1].offset,
+ presumed_offset);
+ igt_stats_push(&stats,
+ ((uint64_t)(results[2*qlen-1] - results[0]) << 32) / qlen);
+ }
+
+ igt_info("%s-%s-%d delay: %.2f\n",
+ name, e__->name, qlen,
+ igt_stats_get_median(&stats) / (1ull << 32));
+ igt_stats_fini(&stats);
+ }
}
munmap(map, 64*1024);
@@ -416,6 +396,11 @@ igt_main
latency_from_ring(device,
e->exec_id | e->flags,
e->name, PREEMPT);
+
+ igt_subtest_f("%s-preemption-queued", e->name)
+ latency_from_ring(device,
+ e->exec_id | e->flags,
+ e->name, PREEMPT | CORK);
}
}
}
Repeat the latency measurements and present the median over many so that the results are more reliable. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> --- tests/gem_exec_latency.c | 155 ++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 85 deletions(-)