From c0c549440d852153d1777eca3fa962c1b70483b3 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 6 May 2013 11:18:33 -0700 Subject: [PATCH] Move metrics-tracking code from glwrap.c to new metrics.c We're moving toward having separate *wrap.c files for each flavor of GL, (glwrap.c, glxwrap.c, and eglwrap.c). But this metrics-tracking code is generic to all of those so belongs in a separate module. --- Makefile.local | 3 +- glwrap.c | 156 ++---------------------------------------- glwrap.h | 6 -- metrics.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++ metrics.h | 53 ++++++++++++++ 5 files changed, 242 insertions(+), 158 deletions(-) create mode 100644 metrics.c create mode 100644 metrics.h diff --git a/Makefile.local b/Makefile.local index c82590c..2f9b5f0 100644 --- a/Makefile.local +++ b/Makefile.local @@ -82,7 +82,8 @@ extra_cflags += -I$(srcdir) -fPIC libfips_srcs = \ dlwrap.c \ glwrap.c \ - glxwrap.c + glxwrap.c \ + metrics.c libfips_32_modules = $(libfips_srcs:.c=-32.o) diff --git a/glwrap.c b/glwrap.c index 9537271..beb1c97 100644 --- a/glwrap.c +++ b/glwrap.c @@ -23,6 +23,8 @@ #include "glwrap.h" +#include "metrics.h" + /* The prototypes for some OpenGL functions changed at one point from: * * const void* *indices @@ -43,66 +45,8 @@ #define GL_GLEXT_PROTOTYPES #include -#include - #include "dlwrap.h" -typedef struct counter -{ - unsigned id; - unsigned program; - struct counter *next; -} counter_t; - -typedef struct program_metrics -{ - unsigned id; - double ticks; -} program_metrics_t; - -typedef struct context -{ - unsigned int program; - - counter_t *counter_head; - counter_t *counter_tail; - - unsigned num_program_metrics; - program_metrics_t *program_metrics; -} context_t; - -/* FIXME: Need a map from integers to context objects and track the - * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */ - -context_t current_context; - -static unsigned -add_counter (void) -{ - counter_t *counter; - - counter = malloc (sizeof(counter_t)); - if (counter == NULL) { - fprintf (stderr, "Out of memory\n"); - exit (1); - } - - glGenQueries (1, &counter->id); - - counter->program = current_context.program; - counter->next = NULL; - - if (current_context.counter_tail) { - current_context.counter_tail->next = counter; - current_context.counter_tail = counter; - } else { - current_context.counter_tail = counter; - current_context.counter_head = counter; - } - - return counter->id; -} - void * glwrap_lookup (char *name) { @@ -124,7 +68,7 @@ glwrap_lookup (char *name) /* Execute a glBegineQuery/glEndQuery pair around an OpenGL call. */ #define TIMED_DEFER(function,...) do { \ unsigned counter; \ - counter = add_counter (); \ + counter = metrics_add_counter (); \ glBeginQuery (GL_TIME_ELAPSED, counter); \ GLWRAP_DEFER(function, __VA_ARGS__); \ glEndQuery (GL_TIME_ELAPSED); \ @@ -426,7 +370,7 @@ glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, void glUseProgram (GLuint program) { - current_context.program = program; + metrics_set_current_program (program); GLWRAP_DEFER(glUseProgram, program); } @@ -434,97 +378,7 @@ glUseProgram (GLuint program) void glUseProgramObjectARB (GLhandleARB programObj) { - current_context.program = programObj; + metrics_set_current_program (programObj); GLWRAP_DEFER(glUseProgramObjectARB, programObj); } - -static void -accumulate_program_ticks (unsigned program_id, unsigned ticks) -{ - context_t *ctx = ¤t_context; - unsigned i; - - if (program_id >= ctx->num_program_metrics) { - ctx->program_metrics = realloc (ctx->program_metrics, - (program_id + 1) * sizeof (program_metrics_t)); - for (i = ctx->num_program_metrics; i < program_id + 1; i++) { - ctx->program_metrics[i].id = i; - ctx->program_metrics[i].ticks = 0.0; - } - - ctx->num_program_metrics = program_id + 1; - } - - ctx->program_metrics[program_id].ticks += ticks; -} - -/* FIXME: Should sort the metrics, print out percentages, etc. */ -static void -print_program_metrics (void) -{ - context_t *ctx = ¤t_context; - unsigned i; - - for (i = 0; i < ctx->num_program_metrics; i++) { - if (ctx->program_metrics[i].ticks == 0.0) - continue; - printf ("Program %d:\t%7.2f mega-ticks\n", - i, ctx->program_metrics[i].ticks / 1e6); - } -} - -void -glwrap_end_frame (void) -{ - static int initialized = 0; - static int frames; - static struct timeval tv_start, tv_now; - - if (! initialized) { - frames = 0; - gettimeofday (&tv_start, NULL); - initialized = 1; - } - - - frames++; - - if (frames % 60 == 0) { - double fps; - gettimeofday (&tv_now, NULL); - - fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec + - (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6); - - printf("FPS: %.3f\n", fps); - - print_program_metrics (); - } - - /* Consume all counters that are ready. */ - counter_t *counter = current_context.counter_head; - - while (counter) { - GLint available; - GLuint elapsed; - - glGetQueryObjectiv (counter->id, GL_QUERY_RESULT_AVAILABLE, - &available); - if (! available) - break; - - glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed); - - accumulate_program_ticks (counter->program, elapsed); - - current_context.counter_head = counter->next; - if (current_context.counter_head == NULL) - current_context.counter_tail = NULL; - - glDeleteQueries (1, &counter->id); - - free (counter); - counter = current_context.counter_head; - } -} diff --git a/glwrap.h b/glwrap.h index 2dc1838..9195007 100644 --- a/glwrap.h +++ b/glwrap.h @@ -37,10 +37,4 @@ glwrap_lookup (char *name); real_ ## function(__VA_ARGS__); \ } while (0); -/* Should be called at the end of ever function wrapper for an OpenGL - * function that ends a frame, (glXSwapBuffers and similar). - */ -void -glwrap_end_frame (void); - #endif diff --git a/metrics.c b/metrics.c new file mode 100644 index 0000000..f4c0a21 --- /dev/null +++ b/metrics.c @@ -0,0 +1,182 @@ +/* Copyright © 2013, Intel Corporation + * + * 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, sublicense, 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#include +#include + +#include + +#define GL_GLEXT_PROTOTYPES +#include + +#include "metrics.h" + +typedef struct counter +{ + unsigned id; + unsigned program; + struct counter *next; +} counter_t; + +typedef struct program_metrics +{ + unsigned id; + double ticks; +} program_metrics_t; + +typedef struct context +{ + unsigned int program; + + counter_t *counter_head; + counter_t *counter_tail; + + unsigned num_program_metrics; + program_metrics_t *program_metrics; +} context_t; + +/* FIXME: Need a map from integers to context objects and track the + * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */ + +context_t current_context; + +unsigned +metrics_add_counter (void) +{ + counter_t *counter; + + counter = malloc (sizeof(counter_t)); + if (counter == NULL) { + fprintf (stderr, "Out of memory\n"); + exit (1); + } + + glGenQueries (1, &counter->id); + + counter->program = current_context.program; + counter->next = NULL; + + if (current_context.counter_tail) { + current_context.counter_tail->next = counter; + current_context.counter_tail = counter; + } else { + current_context.counter_tail = counter; + current_context.counter_head = counter; + } + + return counter->id; +} + +void +metrics_set_current_program (unsigned program) +{ + current_context.program = program; +} + +static void +accumulate_program_ticks (unsigned program_id, unsigned ticks) +{ + context_t *ctx = ¤t_context; + unsigned i; + + if (program_id >= ctx->num_program_metrics) { + ctx->program_metrics = realloc (ctx->program_metrics, + (program_id + 1) * sizeof (program_metrics_t)); + for (i = ctx->num_program_metrics; i < program_id + 1; i++) { + ctx->program_metrics[i].id = i; + ctx->program_metrics[i].ticks = 0.0; + } + + ctx->num_program_metrics = program_id + 1; + } + + ctx->program_metrics[program_id].ticks += ticks; +} + +/* FIXME: Should sort the metrics, print out percentages, etc. */ +static void +print_program_metrics (void) +{ + context_t *ctx = ¤t_context; + unsigned i; + + for (i = 0; i < ctx->num_program_metrics; i++) { + if (ctx->program_metrics[i].ticks == 0.0) + continue; + printf ("Program %d:\t%7.2f mega-ticks\n", + i, ctx->program_metrics[i].ticks / 1e6); + } +} + +void +metrics_end_frame (void) +{ + static int initialized = 0; + static int frames; + static struct timeval tv_start, tv_now; + + if (! initialized) { + frames = 0; + gettimeofday (&tv_start, NULL); + initialized = 1; + } + + + frames++; + + if (frames % 60 == 0) { + double fps; + gettimeofday (&tv_now, NULL); + + fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec + + (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6); + + printf("FPS: %.3f\n", fps); + + print_program_metrics (); + } + + /* Consume all counters that are ready. */ + counter_t *counter = current_context.counter_head; + + while (counter) { + GLint available; + GLuint elapsed; + + glGetQueryObjectiv (counter->id, GL_QUERY_RESULT_AVAILABLE, + &available); + if (! available) + break; + + glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed); + + accumulate_program_ticks (counter->program, elapsed); + + current_context.counter_head = counter->next; + if (current_context.counter_head == NULL) + current_context.counter_tail = NULL; + + glDeleteQueries (1, &counter->id); + + free (counter); + counter = current_context.counter_head; + } +} diff --git a/metrics.h b/metrics.h new file mode 100644 index 0000000..261a5a5 --- /dev/null +++ b/metrics.h @@ -0,0 +1,53 @@ +/* Copyright © 2013, Intel Corporation + * + * 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, sublicense, 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +#ifndef METRICS_H +#define METRICS_H + +/* Add a new counter to the metrics tracking state. + * + * The value accumulated in this counter be accounted against the + * current program (as set with metrics_set_current_program). + * + * Returns: A counter ID suitable for use with glBeginQuery/glEndQuery + */ +unsigned +metrics_add_counter (void); + +/* Set the ID of the currently executing shader program. + * + * The metrics-tracking code will account for per-shader-program + * timings by accumulating counter values measured while each porogram + * is active (see metrics_add_counter). + */ +void +metrics_set_current_program (unsigned program); + +/* Should be called at the end of every function wrapper for a + * function that ends a frame, (glXSwapBuffers and similar). + * + * This function performs whatever bookkeeping is necessary to + * generate a timing report, then emits that report. + */ +void +metrics_end_frame (void); + +#endif -- 2.43.0