summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2020-05-07 19:37:45 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2020-05-07 19:46:42 +0100
commit5efb4a1c9cc944eff129cae7794951ae617bca17 (patch)
tree29825cc742546fa0bc66210e2fb16c2a4ca50a38 /tests
parentdfa344c88678fff6d80223263c489f92e8e8d527 (diff)
i915/gem_exec_fence: Exercise blocking bonded fences on one engine
Like the parallel, but restricted to a single engine -- assumes we have timeslicing. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Acked-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/i915/gem_exec_fence.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/tests/i915/gem_exec_fence.c b/tests/i915/gem_exec_fence.c
index 20a5d49d..20ff2535 100644
--- a/tests/i915/gem_exec_fence.c
+++ b/tests/i915/gem_exec_fence.c
@@ -692,6 +692,100 @@ static void test_parallel(int i915, const struct intel_execution_engine2 *e)
igt_spin_free(i915, spin);
}
+static void test_concurrent(int i915, const struct intel_execution_engine2 *e)
+{
+ const int gen = intel_gen(intel_get_drm_devid(i915));
+ struct drm_i915_gem_relocation_entry reloc = {
+ .target_handle = gem_create(i915, 4096),
+ .write_domain = I915_GEM_DOMAIN_RENDER,
+ .offset = sizeof(uint32_t),
+ };
+ struct drm_i915_gem_exec_object2 obj[] = {
+ { .handle = reloc.target_handle, },
+ {
+ .handle = gem_create(i915, 4096),
+ .relocs_ptr = to_user_pointer(&reloc),
+ .relocation_count = 1,
+ }
+ };
+ struct drm_i915_gem_execbuffer2 execbuf = {
+ .buffers_ptr = to_user_pointer(obj),
+ .buffer_count = ARRAY_SIZE(obj),
+ .flags = e->flags | I915_EXEC_FENCE_SUBMIT,
+ };
+ IGT_CORK_FENCE(cork);
+ uint32_t batch[16];
+ igt_spin_t *spin;
+ uint32_t result;
+ int fence;
+ int i;
+
+ /*
+ * A variant of test_parallel() that runs a bonded pair on a single
+ * engine and ensures that the secondary batch cannot start before
+ * the master is ready.
+ */
+
+ fence = igt_cork_plug(&cork, i915),
+ spin = igt_spin_new(i915,
+ .engine = e->flags,
+ .fence = fence,
+ .flags = (IGT_SPIN_FENCE_OUT |
+ IGT_SPIN_FENCE_IN));
+ close(fence);
+
+ i = 0;
+ batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
+ if (gen >= 8) {
+ batch[++i] = reloc.delta;
+ batch[++i] = 0;
+ } else if (gen >= 4) {
+ batch[++i] = 0;
+ batch[++i] = reloc.delta;
+ reloc.offset += sizeof(uint32_t);
+ } else {
+ batch[i]--;
+ batch[++i] = reloc.delta;
+ }
+ batch[++i] = 0xd0df0d;
+ batch[++i] = MI_BATCH_BUFFER_END;
+ gem_write(i915, obj[1].handle, 0, batch, sizeof(batch));
+
+ execbuf.rsvd1 = gem_context_create(i915);
+ execbuf.rsvd2 = spin->out_fence;
+ if (gen < 6)
+ execbuf.flags |= I915_EXEC_SECURE;
+
+ gem_execbuf(i915, &execbuf);
+ gem_context_destroy(i915, execbuf.rsvd1);
+ gem_close(i915, obj[1].handle);
+
+ /*
+ * No secondary should be executed since master is stalled. If there
+ * was no dependency chain at all, the secondaries would start
+ * immediately.
+ */
+ usleep(20000);
+ igt_assert(gem_bo_busy(i915, spin->handle));
+ igt_assert(gem_bo_busy(i915, obj[0].handle));
+ igt_cork_unplug(&cork);
+
+ /*
+ * Wait for all secondaries to complete. If we used a regular fence
+ * then the secondaries would not start until the master was complete.
+ * In this case that can only happen with a GPU reset, and so we run
+ * under the hang detector and double check that the master is still
+ * running afterwards.
+ */
+ gem_read(i915, obj[0].handle, 0, &result, sizeof(result));
+ igt_assert_eq_u32(result, 0xd0df0d);
+ gem_close(i915, obj[0].handle);
+
+ /* Master should still be spinning, but all output should be written */
+ igt_assert(gem_bo_busy(i915, spin->handle));
+ igt_spin_free(i915, spin);
+}
+
static uint32_t batch_create(int fd)
{
const uint32_t bbe = MI_BATCH_BUFFER_END;
@@ -1569,6 +1663,16 @@ igt_main
}
}
+ igt_subtest_with_dynamic("concurrent") {
+ igt_require(has_submit_fence(i915));
+ igt_require(gem_scheduler_has_semaphores(i915));
+ igt_require(gem_scheduler_has_preemption(i915));
+ __for_each_physical_engine(i915, e) {
+ igt_dynamic_f("%s", e->name)
+ test_concurrent(i915, e);
+ }
+ }
+
igt_subtest_with_dynamic("submit") {
igt_require(gem_scheduler_has_semaphores(i915));
igt_require(gem_scheduler_has_preemption(i915));