From 7b1c18255abd16db3d426fcb136c7f1123562c0d Mon Sep 17 00:00:00 2001
From: Jakob Bornecrantz <jakob@collabora.com>
Date: Wed, 2 Nov 2022 00:22:16 +0000
Subject: [PATCH] u/pacing: Work around issues with frame reuse

The code creates a frame with the timing information, and keeps track of the
times the applications does various things during the frame loop. Like
starting to render and finished rendering and so on. It keeps track of that
frame until it has determined that the application or the system compositor
will never do anything thing with that frame.

Now the allocation side of thing is very simple, just a long array of
FRAME_COUNT size that is reused with frame_id % FRAME_COUNT. So if the
application or the compositor keeps a frame along for too long it will try to
reuse that frame. The code has asserts to catch this. Making FRAME_COUNT makes
that re-use more unlikely.
---
 src/xrt/auxiliary/util/u_pacing_app.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/src/xrt/auxiliary/util/u_pacing_app.c b/src/xrt/auxiliary/util/u_pacing_app.c
index af04f7e98..ca125c2a7 100644
--- a/src/xrt/auxiliary/util/u_pacing_app.c
+++ b/src/xrt/auxiliary/util/u_pacing_app.c
@@ -1,4 +1,4 @@
-// Copyright 2020-2021, Collabora, Ltd.
+// Copyright 2020-2022, Collabora, Ltd.
 // SPDX-License-Identifier: BSL-1.0
 /*!
  * @file
@@ -28,6 +28,12 @@ DEBUG_GET_ONCE_LOG_OPTION(log_level, "U_PACING_APP_LOG", U_LOGGING_WARN)
 #define UPA_LOG_W(...) U_LOG_IFL_W(debug_get_log_option_log_level(), __VA_ARGS__)
 #define UPA_LOG_E(...) U_LOG_IFL_E(debug_get_log_option_log_level(), __VA_ARGS__)
 
+/*!
+ * Define to validate latched and retired call. Currently disabled due to
+ * simplistic frame allocation code, enable once improved.
+ */
+#undef VALIDATE_LATCHED_AND_RETIRED
+
 
 /*
  *
@@ -451,6 +457,13 @@ pa_mark_gpu_done(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
 
 	// Write out tracing data.
 	do_tracing(pa, f);
+
+#ifndef VALIDATE_LATCHED_AND_RETIRED
+	// Reset the frame.
+	U_ZERO(f);
+	f->state = U_PA_READY;
+	f->frame_id = -1;
+#endif
 }
 
 static void
@@ -458,7 +471,14 @@ pa_latched(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns, int64_t
 {
 	struct pacing_app *pa = pacing_app(upa);
 
+#ifdef VALIDATE_LATCHED_AND_RETIRED
+	size_t index = GET_INDEX_FROM_ID(pa, frame_id);
+	struct u_pa_frame *f = &pa->frames[index];
+	assert(f->frame_id == frame_id);
+	assert(f->state == U_RT_GPU_DONE);
+#else
 	(void)pa;
+#endif
 }
 
 static void
@@ -466,14 +486,19 @@ pa_retired(struct u_pacing_app *upa, int64_t frame_id, uint64_t when_ns)
 {
 	struct pacing_app *pa = pacing_app(upa);
 
+#ifdef VALIDATE_LATCHED_AND_RETIRED
 	size_t index = GET_INDEX_FROM_ID(pa, frame_id);
 	struct u_pa_frame *f = &pa->frames[index];
 	assert(f->frame_id == frame_id);
 	assert(f->state == U_RT_GPU_DONE || f->state == U_RT_DELIVERED);
 
 	// Reset the frame.
+	U_ZERO(f);
 	f->state = U_PA_READY;
 	f->frame_id = -1;
+#else
+	(void)pa;
+#endif
 }
 
 static void