mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
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>
This commit is contained in:
parent
cc08af48f6
commit
fbe6740df1
@ -62,6 +62,11 @@ typedef struct
|
||||
GLubyte c[4];
|
||||
} CoglTextureGLVertex;
|
||||
|
||||
struct _CoglTimestampQuery
|
||||
{
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
struct _CoglContext
|
||||
{
|
||||
CoglObject _parent;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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 ())
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user