[mutter] cogl: Add GPU timestamp querying utilities
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] cogl: Add GPU timestamp querying utilities
- Date: Tue, 13 Jul 2021 08:41:55 +0000 (UTC)
commit fbe6740df121db60e1dbe0fbc6b01a72a6401461
Author: Ivan Molodetskikh <yalterz gmail com>
Date: Sat May 15 13:56:49 2021 +0300
cogl: Add GPU timestamp querying utilities
Add utilities that allow getting the current GPU timestamp and creating
a query which completes upon completion of all operations currently
submitted on a framebuffer. Combined, these two allow measuring how long
it took the GPU to finish rendering something to a framebuffer.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
cogl/cogl/cogl-context-private.h | 5 +++
cogl/cogl/cogl-context.c | 24 ++++++++++++
cogl/cogl/cogl-context.h | 23 +++++++++++
cogl/cogl/cogl-driver.h | 14 +++++++
cogl/cogl/cogl-framebuffer.c | 25 ++++++++++++
cogl/cogl/cogl-framebuffer.h | 13 +++++++
cogl/cogl/driver/gl/cogl-util-gl-private.h | 21 ++++++++++
cogl/cogl/driver/gl/cogl-util-gl.c | 60 +++++++++++++++++++++++++++++
cogl/cogl/driver/gl/gl/cogl-driver-gl.c | 10 +++++
cogl/cogl/driver/gl/gles/cogl-driver-gles.c | 10 +++++
10 files changed, 205 insertions(+)
---
diff --git a/cogl/cogl/cogl-context-private.h b/cogl/cogl/cogl-context-private.h
index 25004c3933..5856f76e98 100644
--- a/cogl/cogl/cogl-context-private.h
+++ b/cogl/cogl/cogl-context-private.h
@@ -62,6 +62,11 @@ typedef struct
GLubyte c[4];
} CoglTextureGLVertex;
+struct _CoglTimestampQuery
+{
+ unsigned int id;
+};
+
struct _CoglContext
{
CoglObject _parent;
diff --git a/cogl/cogl/cogl-context.c b/cogl/cogl/cogl-context.c
index b7bf14f87e..89019e908d 100644
--- a/cogl/cogl/cogl-context.c
+++ b/cogl/cogl/cogl-context.c
@@ -491,3 +491,27 @@ cogl_context_get_named_pipeline (CoglContext *context,
{
return g_hash_table_lookup (context->named_pipelines, key);
}
+
+void
+cogl_context_free_timestamp_query (CoglContext *context,
+ CoglTimestampQuery *query)
+{
+ context->driver_vtable->free_timestamp_query (context, query);
+}
+
+int64_t
+cogl_context_timestamp_query_get_time_ns (CoglContext *context,
+ CoglTimestampQuery *query)
+{
+ return context->driver_vtable->timestamp_query_get_time_ns (context, query);
+}
+
+int64_t
+cogl_context_get_gpu_time_ns (CoglContext *context)
+{
+ g_return_val_if_fail (cogl_has_feature (context,
+ COGL_FEATURE_ID_GET_GPU_TIME),
+ 0);
+
+ return context->driver_vtable->get_gpu_time_ns (context);
+}
diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h
index 20b9561b94..38ac11be83 100644
--- a/cogl/cogl/cogl-context.h
+++ b/cogl/cogl/cogl-context.h
@@ -41,6 +41,7 @@
* dependency issues with the following headers.
*/
typedef struct _CoglContext CoglContext;
+typedef struct _CoglTimestampQuery CoglTimestampQuery;
#include <cogl/cogl-defines.h>
#include <cogl/cogl-display.h>
@@ -208,6 +209,8 @@ typedef enum _CoglFeatureID
COGL_FEATURE_ID_BUFFER_AGE,
COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,
COGL_FEATURE_ID_BLIT_FRAMEBUFFER,
+ COGL_FEATURE_ID_TIMESTAMP_QUERY,
+ COGL_FEATURE_ID_GET_GPU_TIME,
/*< private >*/
_COGL_N_FEATURE_IDS /*< skip >*/
@@ -370,6 +373,26 @@ COGL_EXPORT CoglPipeline *
cogl_context_get_named_pipeline (CoglContext *context,
CoglPipelineKey *key);
+COGL_EXPORT void
+cogl_context_free_timestamp_query (CoglContext *context,
+ CoglTimestampQuery *query);
+
+COGL_EXPORT int64_t
+cogl_context_timestamp_query_get_time_ns (CoglContext *context,
+ CoglTimestampQuery *query);
+
+/**
+ * cogl_context_get_gpu_time_ns:
+ * @context: a #CoglContext pointer
+ *
+ * This function should only be called if the COGL_FEATURE_ID_GET_GPU_TIME
+ * feature is advertised.
+ *
+ * Return value: Current GPU time in nanoseconds
+ */
+COGL_EXPORT int64_t
+cogl_context_get_gpu_time_ns (CoglContext *context);
+
G_END_DECLS
#endif /* __COGL_CONTEXT_H__ */
diff --git a/cogl/cogl/cogl-driver.h b/cogl/cogl/cogl-driver.h
index 21519085b2..aeabfe0e75 100644
--- a/cogl/cogl/cogl-driver.h
+++ b/cogl/cogl/cogl-driver.h
@@ -231,6 +231,20 @@ struct _CoglDriverVtable
(* set_uniform) (CoglContext *ctx,
GLint location,
const CoglBoxedValue *value);
+
+ CoglTimestampQuery *
+ (* create_timestamp_query) (CoglContext *context);
+
+ void
+ (* free_timestamp_query) (CoglContext *context,
+ CoglTimestampQuery *query);
+
+ int64_t
+ (* timestamp_query_get_time_ns) (CoglContext *context,
+ CoglTimestampQuery *query);
+
+ int64_t
+ (* get_gpu_time_ns) (CoglContext *context);
};
#define COGL_DRIVER_ERROR (_cogl_driver_error_quark ())
diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
index 7a8acecb96..525b24293f 100644
--- a/cogl/cogl/cogl-framebuffer.c
+++ b/cogl/cogl/cogl-framebuffer.c
@@ -2656,3 +2656,28 @@ cogl_framebuffer_get_driver (CoglFramebuffer *framebuffer)
return priv->driver;
}
+
+CoglTimestampQuery *
+cogl_framebuffer_create_timestamp_query (CoglFramebuffer *framebuffer)
+{
+ CoglFramebufferPrivate *priv =
+ cogl_framebuffer_get_instance_private (framebuffer);
+ const CoglDriverVtable *driver_vtable = priv->context->driver_vtable;
+
+ g_return_val_if_fail (cogl_has_feature (priv->context,
+ COGL_FEATURE_ID_TIMESTAMP_QUERY),
+ NULL);
+
+ /* The timestamp query completes upon completion of all previously submitted
+ * GL commands. So make sure those commands are indeed submitted by flushing
+ * the journal.
+ */
+ _cogl_framebuffer_flush_journal (framebuffer);
+
+ cogl_context_flush_framebuffer_state (priv->context,
+ framebuffer,
+ framebuffer,
+ COGL_FRAMEBUFFER_STATE_BIND);
+
+ return driver_vtable->create_timestamp_query (priv->context);
+}
diff --git a/cogl/cogl/cogl-framebuffer.h b/cogl/cogl/cogl-framebuffer.h
index 993de7a25f..571b489988 100644
--- a/cogl/cogl/cogl-framebuffer.h
+++ b/cogl/cogl/cogl-framebuffer.h
@@ -1564,6 +1564,19 @@ cogl_blit_framebuffer (CoglFramebuffer *framebuffer,
COGL_EXPORT void
cogl_framebuffer_flush (CoglFramebuffer *framebuffer);
+/**
+ * cogl_framebuffer_create_timestamp_query: (skip)
+ *
+ * Creates a query for the GPU timestamp that will complete upon completion of
+ * all previously submitted GL commands related to this framebuffer. E.g. when
+ * the rendering is finished on this framebuffer.
+ *
+ * This function should only be called if the COGL_FEATURE_ID_TIMESTAMP_QUERY
+ * feature is advertised.
+ */
+COGL_EXPORT CoglTimestampQuery *
+cogl_framebuffer_create_timestamp_query (CoglFramebuffer *framebuffer);
+
G_END_DECLS
#endif /* __COGL_FRAMEBUFFER_H */
diff --git a/cogl/cogl/driver/gl/cogl-util-gl-private.h b/cogl/cogl/driver/gl/cogl-util-gl-private.h
index 0b7eaa772e..be8fa1eeb9 100644
--- a/cogl/cogl/driver/gl/cogl-util-gl-private.h
+++ b/cogl/cogl/driver/gl/cogl-util-gl-private.h
@@ -146,6 +146,20 @@ _cogl_gl_util_parse_gl_version (const char *version_string,
CoglGraphicsResetStatus
_cogl_gl_get_graphics_reset_status (CoglContext *context);
+CoglTimestampQuery *
+cogl_gl_create_timestamp_query (CoglContext *context);
+
+void
+cogl_gl_free_timestamp_query (CoglContext *context,
+ CoglTimestampQuery *query);
+
+int64_t
+cogl_gl_timestamp_query_get_time_ns (CoglContext *context,
+ CoglTimestampQuery *query);
+
+int64_t
+cogl_gl_get_gpu_time_ns (CoglContext *context);
+
#ifndef GL_FRAMEBUFFER
#define GL_FRAMEBUFFER 0x8D40
#endif
@@ -229,4 +243,11 @@ _cogl_gl_get_graphics_reset_status (CoglContext *context);
#define GL_STENCIL 0x1802
#endif
+#ifndef GL_TIMESTAMP
+#define GL_TIMESTAMP 0x8E28
+#endif
+#ifndef GL_QUERY_RESULT
+#define GL_QUERY_RESULT 0x8866
+#endif
+
#endif /* _COGL_UTIL_GL_PRIVATE_H_ */
diff --git a/cogl/cogl/driver/gl/cogl-util-gl.c b/cogl/cogl/driver/gl/cogl-util-gl.c
index 9b59bef1d6..096fcb7886 100644
--- a/cogl/cogl/driver/gl/cogl-util-gl.c
+++ b/cogl/cogl/driver/gl/cogl-util-gl.c
@@ -493,3 +493,63 @@ _cogl_gl_get_graphics_reset_status (CoglContext *context)
return COGL_GRAPHICS_RESET_STATUS_NO_ERROR;
}
}
+
+CoglTimestampQuery *
+cogl_gl_create_timestamp_query (CoglContext *context)
+{
+ CoglTimestampQuery *query;
+
+ g_return_val_if_fail (cogl_has_feature (context,
+ COGL_FEATURE_ID_TIMESTAMP_QUERY),
+ NULL);
+
+ query = g_new0 (CoglTimestampQuery, 1);
+
+ GE (context, glGenQueries (1, &query->id));
+ GE (context, glQueryCounter (query->id, GL_TIMESTAMP));
+
+ /* Flush right away so GL knows about our timestamp query.
+ *
+ * E.g. the direct scanout path doesn't call SwapBuffers or any other
+ * glFlush-inducing operation, and skipping explicit glFlush here results in
+ * the timestamp query being placed at the point of glGetQueryObject much
+ * later, resulting in a GPU timestamp much later on in time.
+ */
+ GE (context, glFlush ());
+
+ return query;
+}
+
+void
+cogl_gl_free_timestamp_query (CoglContext *context,
+ CoglTimestampQuery *query)
+{
+ GE (context, glDeleteQueries (1, &query->id));
+ g_free (query);
+}
+
+int64_t
+cogl_gl_timestamp_query_get_time_ns (CoglContext *context,
+ CoglTimestampQuery *query)
+{
+ int64_t query_time_ns;
+
+ GE (context, glGetQueryObjecti64v (query->id,
+ GL_QUERY_RESULT,
+ &query_time_ns));
+
+ return query_time_ns;
+}
+
+int64_t
+cogl_gl_get_gpu_time_ns (CoglContext *context)
+{
+ int64_t gpu_time_ns;
+
+ g_return_val_if_fail (cogl_has_feature (context,
+ COGL_FEATURE_ID_GET_GPU_TIME),
+ 0);
+
+ GE (context, glGetInteger64v (GL_TIMESTAMP, &gpu_time_ns));
+ return gpu_time_ns;
+}
diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
index 35577518d0..ef4a61a09a 100644
--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
+++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
@@ -539,6 +539,12 @@ _cogl_driver_update_features (CoglContext *ctx,
COGL_PRIVATE_FEATURE_TEXTURE_FORMAT_HALF_FLOAT,
TRUE);
+ if (ctx->glGenQueries && ctx->glQueryCounter)
+ COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_TIMESTAMP_QUERY, TRUE);
+
+ if (ctx->glGetInteger64v)
+ COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_GET_GPU_TIME, TRUE);
+
/* Cache features */
for (i = 0; i < G_N_ELEMENTS (private_features); i++)
ctx->private_features[i] |= private_features[i];
@@ -591,4 +597,8 @@ _cogl_driver_gl =
_cogl_sampler_gl_init,
_cogl_sampler_gl_free,
_cogl_gl_set_uniform, /* XXX name is weird... */
+ cogl_gl_create_timestamp_query,
+ cogl_gl_free_timestamp_query,
+ cogl_gl_timestamp_query_get_time_ns,
+ cogl_gl_get_gpu_time_ns,
};
diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
index 3e8ea8a0a2..633e2c4157 100644
--- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
+++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
@@ -432,6 +432,12 @@ _cogl_driver_update_features (CoglContext *context,
COGL_FEATURE_ID_TEXTURE_RG,
TRUE);
+ if (context->glGenQueries && context->glQueryCounter)
+ COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TIMESTAMP_QUERY, TRUE);
+
+ if (context->glGetInteger64v)
+ COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_GET_GPU_TIME, TRUE);
+
/* Cache features */
for (i = 0; i < G_N_ELEMENTS (private_features); i++)
context->private_features[i] |= private_features[i];
@@ -479,4 +485,8 @@ _cogl_driver_gles =
_cogl_sampler_gl_init,
_cogl_sampler_gl_free,
_cogl_gl_set_uniform,
+ cogl_gl_create_timestamp_query,
+ cogl_gl_free_timestamp_query,
+ cogl_gl_timestamp_query_get_time_ns,
+ cogl_gl_get_gpu_time_ns,
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]