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(+)
diff --git a/tests/egl/egl-context-preemption.c b/tests/egl/egl-context-preemption.c index 566416312..85f5c8fd5 100644 --- a/tests/egl/egl-context-preemption.c +++ b/tests/egl/egl-context-preemption.c @@ -270,6 +270,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) { @@ -517,6 +547,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); @@ -526,6 +559,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; -- 2.19.0 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/piglit