[Mesa-dev] [PATCH] gallium/hud: add frametime graph

Matthias Groß grmat at sub.red
Tue May 15 15:39:32 UTC 2018


Frametimes are often a more useful metric than FPS, because fps are an
averaged-value for the duration of a rather long period (one second).

Example: 59 frames are rendered in 16 ms each, but one frame takes 56 ms
to compute. That's exactly 60 FPS, but there is very noticeable stutter.
Some modern game engines and game testers also utilise frametimes graphs.

This graph is enabled via GALLIUM_HUD=frametime and will show the
frametime of each frame and therefore also the stutter in a
comprehensible way. It is useful to use the ceiling and/or dynamic
modifier, though, to clip extreme anomalies, e.g. during loading.
---
 src/gallium/auxiliary/hud/hud_context.c   |  4 ++
 src/gallium/auxiliary/hud/hud_frametime.c | 85 +++++++++++++++++++++++
 src/gallium/auxiliary/hud/hud_private.h   |  1 +
 src/gallium/auxiliary/meson.build         |  1 +
 4 files changed, 91 insertions(+)
 create mode 100644 src/gallium/auxiliary/hud/hud_frametime.c

diff --git a/src/gallium/auxiliary/hud/hud_context.c b/src/gallium/auxiliary/hud/hud_context.c
index 6ed9ccffdb..61db98b4b0 100644
--- a/src/gallium/auxiliary/hud/hud_context.c
+++ b/src/gallium/auxiliary/hud/hud_context.c
@@ -1247,6 +1247,9 @@ hud_parse_env_var(struct hud_context *hud, struct pipe_screen *screen,
       if (strcmp(name, "fps") == 0) {
          hud_fps_graph_install(pane);
       }
+      else if (strcmp(name, "frametime") == 0) {
+         hud_frametime_graph_install(pane);
+      }
       else if (strcmp(name, "cpu") == 0) {
          hud_cpu_graph_install(pane, ALL_CPUS);
       }
@@ -1557,6 +1560,7 @@ print_help(struct pipe_screen *screen)
    puts("");
    puts("  Available names:");
    puts("    fps");
+   puts("    frametime");
    puts("    cpu");
 
    for (i = 0; i < num_cpus; i++)
diff --git a/src/gallium/auxiliary/hud/hud_frametime.c b/src/gallium/auxiliary/hud/hud_frametime.c
new file mode 100644
index 0000000000..0f5e9f7430
--- /dev/null
+++ b/src/gallium/auxiliary/hud/hud_frametime.c
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * Copyright 2018 <grmat at sub.red>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* This file contains code for displaying frametimes on the HUD.
+ */
+
+#include "hud/hud_private.h"
+#include "util/os_time.h"
+#include "util/u_memory.h"
+
+struct frametime_info {
+   uint64_t last_time;
+};
+
+static void
+query_frametime(struct hud_graph *gr, struct pipe_context *pipe)
+{
+   struct frametime_info *info = gr->query_data;
+   uint64_t now = os_time_get();
+
+   if (info->last_time) {
+      float frametime = ((double)now - (double)info->last_time) / 1000.0;
+      info->last_time = now;
+
+      hud_graph_add_value(gr, frametime);
+   }
+   else {
+      info->last_time = now;
+   }
+}
+
+static void
+free_query_data(void *p, struct pipe_context *pipe)
+{
+   FREE(p);
+}
+
+void
+hud_frametime_graph_install(struct hud_pane *pane)
+{
+   struct hud_graph *gr = CALLOC_STRUCT(hud_graph);
+
+   if (!gr)
+      return;
+
+   strcpy(gr->name, "frametime (ms)");
+   gr->query_data = CALLOC_STRUCT(frametime_info);
+   if (!gr->query_data) {
+      FREE(gr);
+      return;
+   }
+
+   gr->query_new_value = query_frametime;
+
+   /* Don't use free() as our callback as that messes up Gallium's
+    * memory debugger.  Use simple free_query_data() wrapper.
+    */
+   gr->free_query_data = free_query_data;
+
+   hud_pane_add_graph(pane, gr);
+}
diff --git a/src/gallium/auxiliary/hud/hud_private.h b/src/gallium/auxiliary/hud/hud_private.h
index b64e29e93e..deed329a8a 100644
--- a/src/gallium/auxiliary/hud/hud_private.h
+++ b/src/gallium/auxiliary/hud/hud_private.h
@@ -157,6 +157,7 @@ struct hud_batch_query_context;
 int hud_get_num_cpus(void);
 
 void hud_fps_graph_install(struct hud_pane *pane);
+void hud_frametime_graph_install(struct hud_pane *pane);
 void hud_cpu_graph_install(struct hud_pane *pane, unsigned cpu_index);
 void hud_thread_busy_install(struct hud_pane *pane, const char *name, bool main);
 void hud_thread_counter_install(struct hud_pane *pane, const char *name,
diff --git a/src/gallium/auxiliary/meson.build b/src/gallium/auxiliary/meson.build
index 92cfb8f7af..7b019326a7 100644
--- a/src/gallium/auxiliary/meson.build
+++ b/src/gallium/auxiliary/meson.build
@@ -117,6 +117,7 @@ files_libgallium = files(
   'hud/hud_sensors_temp.c',
   'hud/hud_driver_query.c',
   'hud/hud_fps.c',
+  'hud/hud_frametime.c',
   'hud/hud_private.h',
   'indices/u_indices.h',
   'indices/u_indices_priv.h',
-- 
2.17.0



More information about the mesa-dev mailing list