[v2,4/7] egl-context-preemption: check that preemption actually happened.

Submitted by Rafael Antognolli on Oct. 29, 2018, 5:16 p.m.

Details

Message ID 20181029171635.25080-5-rafael.antognolli@intel.com
State New
Headers show
Series "Preemption test." ( rev: 1 ) in Piglit

Not browsing as part of any series.

Commit Message

Rafael Antognolli Oct. 29, 2018, 5:16 p.m.
After both the main and the high priority threads have finished, check
their render timestamps to try to figure out if preemption has kicked
in.
---
 tests/egl/egl-context-preemption.c | 88 ++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

Patch hide | download patch | download mbox

diff --git a/tests/egl/egl-context-preemption.c b/tests/egl/egl-context-preemption.c
index 8f0245e49..e9180d4ee 100644
--- a/tests/egl/egl-context-preemption.c
+++ b/tests/egl/egl-context-preemption.c
@@ -263,6 +263,36 @@  init_other_display(EGLDisplay *out_other_dpy)
 	return result;
 }
 
+/* Return the time difference between t1 and t2, taking into account wrapping
+ * around 'nbits'.
+ *
+ * Note: this function only works if the time difference is up to
+ * 1 << (nbits - 1).
+ */
+static int64_t
+time_diff(int64_t t1, int64_t t2, int nbits)
+{
+	const int64_t max_delta = 1ULL << (nbits - 1);
+	const int64_t bitmask = (1ULL << nbits) - 1;
+	const int64_t diff = t1 - t2;
+	const bool wrapped = llabs(t1 - t2) > max_delta;
+
+	/* First find out which one came first
+	 *  diff < 0 -- if t1 < t2
+	 *  diff == 0  -- if t1 == t2
+	 *  diff > 0 -- if t1 > t2
+	 */
+	const int64_t diff_wrap = wrapped ? -diff : diff;
+
+	/* Then calculate the difference between them, taking overflow into
+	 * account
+	 */
+	if (diff_wrap > 0)
+		return (t1 - t2) & bitmask;
+	else
+		return -((t2 - t1) & bitmask);
+}
+
 static enum piglit_result
 setup_thread_context(struct test_data *d)
 {
@@ -510,6 +540,9 @@  test_preemption(void *data)
 		goto cleanup;
 	}
 
+	GLint nbits;
+	glGetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, &nbits);
+
 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
 	err = pthread_join(thread2, NULL);
@@ -519,6 +552,61 @@  test_preemption(void *data)
 		goto cleanup;
 	}
 
+	/* In this loop we are only looking for the first high priority render
+	 * that started after the main workload. In theory the first one should
+	 * already start after the main, but we run this loop just to confirm
+	 * that assumption.
+	 */
+	int first_run = -1;
+	for (int i = 0; i < d.nruns; i++) {
+		if (time_diff(d.tstarted[i], d.main_tstarted, nbits) > 0) {
+			first_run = i;
+			break;
+		}
+	}
+
+	if (first_run < 0) {
+		piglit_loge("Something went wrong, all high priority workloads"
+			    " started before the main workload.");
+		result = PIGLIT_FAIL;
+		goto cleanup;
+	}
+
+	/* If mid-command preemption is enabled, the first workload to start
+	 * after the main workload should finish first.
+	 */
+	if (time_diff(d.tfinished[first_run], d.main_tfinished, nbits) >= 0) {
+		piglit_loge("First preemption failed.");
+		result = PIGLIT_FAIL;
+		goto cleanup;
+	}
+
+	int second_run = first_run + 1;
+	if (second_run >= d.nruns) {
+		piglit_loge("The first run to start after the main draw was"
+			    " also the last one, so we can't check the second"
+			    " run time.");
+		piglit_loge("First run: %d, second run: %d, nruns: %d",
+			    first_run, second_run, d.nruns);
+		result = PIGLIT_WARN;
+	}
+
+	/* On i965, it looks like even if mid-command preemption is not
+	 * supported/enabled, it might report that the first high priority
+	 * render finished before the main render. So we check the timing of
+	 * the second high priority render too, which should also finish
+	 * earlier than the main render, if mid-command preemption is enabled.
+	 */
+	if (time_diff(d.tfinished[second_run], d.main_tfinished, nbits) >= 0) {
+		piglit_loge("Second preemption failed.");
+		result = PIGLIT_FAIL;
+		goto cleanup;
+	}
+
+	/* TODO: Calculate the time to run each of the high priority workloads,
+	 * and print the average latency.
+	 */
+
 cleanup:
 	free(ref_image);
 	return result;