gtk2/gsk/gl/gskglprofiler.c
Alexander Larsson cc643df88b Convert all profiler times from nsec to usec
usec is the scale of the monotonic timer which is where we get almost
all the times from. The only actual source of nsec is the opengl
GPU time (but who knows what the actual resulution of that is).

Changing this to usec allows us to get rid of " * 1000" in a *lot* of
places all over the codebase, which are ugly and confusing.
2020-02-12 10:44:17 +01:00

176 lines
4.2 KiB
C

#include "config.h"
#include "gskglprofilerprivate.h"
#include <epoxy/gl.h>
#define N_QUERIES 4
struct _GskGLProfiler
{
GObject parent_instance;
GdkGLContext *gl_context;
/* Creating GL queries is kind of expensive, so we pay the
* price upfront and create a circular buffer of queries
*/
GLuint gl_queries[N_QUERIES];
GLuint active_query;
gboolean has_timer : 1;
gboolean first_frame : 1;
};
enum {
PROP_GL_CONTEXT = 1,
N_PROPERTIES
};
static GParamSpec *gsk_gl_profiler_properties[N_PROPERTIES];
G_DEFINE_TYPE (GskGLProfiler, gsk_gl_profiler, G_TYPE_OBJECT)
static void
gsk_gl_profiler_finalize (GObject *gobject)
{
GskGLProfiler *self = GSK_GL_PROFILER (gobject);
glDeleteQueries (N_QUERIES, self->gl_queries);
g_clear_object (&self->gl_context);
G_OBJECT_CLASS (gsk_gl_profiler_parent_class)->finalize (gobject);
}
static void
gsk_gl_profiler_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GskGLProfiler *self = GSK_GL_PROFILER (gobject);
switch (prop_id)
{
case PROP_GL_CONTEXT:
self->gl_context = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
gsk_gl_profiler_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GskGLProfiler *self = GSK_GL_PROFILER (gobject);
switch (prop_id)
{
case PROP_GL_CONTEXT:
g_value_set_object (value, self->gl_context);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
gsk_gl_profiler_class_init (GskGLProfilerClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gsk_gl_profiler_set_property;
gobject_class->get_property = gsk_gl_profiler_get_property;
gobject_class->finalize = gsk_gl_profiler_finalize;
gsk_gl_profiler_properties[PROP_GL_CONTEXT] =
g_param_spec_object ("gl-context",
"GL Context",
"The GdkGLContext used by the GL profiler",
GDK_TYPE_GL_CONTEXT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPERTIES, gsk_gl_profiler_properties);
}
static void
gsk_gl_profiler_init (GskGLProfiler *self)
{
glGenQueries (N_QUERIES, self->gl_queries);
self->first_frame = TRUE;
self->has_timer = epoxy_has_gl_extension ("GL_ARB_timer_query");
}
GskGLProfiler *
gsk_gl_profiler_new (GdkGLContext *context)
{
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
return g_object_new (GSK_TYPE_GL_PROFILER, "gl-context", context, NULL);
}
void
gsk_gl_profiler_begin_gpu_region (GskGLProfiler *profiler)
{
GLuint query_id;
g_return_if_fail (GSK_IS_GL_PROFILER (profiler));
if (!profiler->has_timer)
return;
query_id = profiler->gl_queries[profiler->active_query];
glBeginQuery (GL_TIME_ELAPSED, query_id);
}
guint64
gsk_gl_profiler_end_gpu_region (GskGLProfiler *profiler)
{
GLuint last_query_id;
GLint res;
GLuint64 elapsed;
g_return_val_if_fail (GSK_IS_GL_PROFILER (profiler), 0);
if (!profiler->has_timer)
return 0;
glEndQuery (GL_TIME_ELAPSED);
if (profiler->active_query == 0)
last_query_id = N_QUERIES - 1;
else
last_query_id = profiler->active_query - 1;
/* Advance iterator */
profiler->active_query += 1;
if (profiler->active_query == N_QUERIES)
profiler->active_query = 0;
/* If this is the first frame we already have a result */
if (profiler->first_frame)
{
profiler->first_frame = FALSE;
return 0;
}
glGetQueryObjectiv (profiler->gl_queries[last_query_id], GL_QUERY_RESULT_AVAILABLE, &res);
if (res == 1)
glGetQueryObjectui64v (profiler->gl_queries[last_query_id], GL_QUERY_RESULT, &elapsed);
else
elapsed = 0;
return elapsed / 1000; /* Convert to usec to match other profiler APIs */
}