1 /* Copyright © 2013, Intel Corporation
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 #include "fips-dispatch-gl.h"
33 typedef struct counter
40 typedef struct program_metrics
42 /* This happens to also be the index into the
43 * ctx->program_metrics array currently
49 typedef struct context
53 counter_t *counter_head;
54 counter_t *counter_tail;
56 unsigned num_program_metrics;
57 program_metrics_t *program_metrics;
60 /* FIXME: Need a map from integers to context objects and track the
61 * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */
63 context_t current_context;
69 metrics_counter_start (void)
73 counter = malloc (sizeof(counter_t));
74 if (counter == NULL) {
75 fprintf (stderr, "Out of memory\n");
79 glGenQueries (1, &counter->id);
81 counter->program = current_context.program;
84 if (current_context.counter_tail) {
85 current_context.counter_tail->next = counter;
86 current_context.counter_tail = counter;
88 current_context.counter_tail = counter;
89 current_context.counter_head = counter;
92 glBeginQuery (GL_TIME_ELAPSED, counter->id);
96 metrics_counter_stop (void)
98 glEndQuery (GL_TIME_ELAPSED);
102 metrics_set_current_program (unsigned program)
104 current_context.program = program;
108 accumulate_program_time (unsigned program_id, unsigned time_ns)
110 context_t *ctx = ¤t_context;
113 if (program_id >= ctx->num_program_metrics) {
114 ctx->program_metrics = realloc (ctx->program_metrics,
115 (program_id + 1) * sizeof (program_metrics_t));
116 for (i = ctx->num_program_metrics; i < program_id + 1; i++) {
117 ctx->program_metrics[i].id = i;
118 ctx->program_metrics[i].time_ns = 0.0;
121 ctx->num_program_metrics = program_id + 1;
124 ctx->program_metrics[program_id].time_ns += time_ns;
128 time_compare(const void *in_a, const void *in_b, void *arg)
130 int a = *(const int *)in_a;
131 int b = *(const int *)in_b;
132 struct program_metrics *metrics = arg;
134 if (metrics[a].time_ns < metrics[b].time_ns)
136 if (metrics[a].time_ns > metrics[b].time_ns)
142 print_program_metrics (void)
144 context_t *ctx = ¤t_context;
146 int *sorted; /* Sorted indices into the ctx->program_metrics */
149 /* Make a sorted list of the programs by time used, and figure
150 * out to total so we can print percentages.
152 sorted = calloc(ctx->num_program_metrics, sizeof(*sorted));
153 for (i = 0; i < ctx->num_program_metrics; i++) {
155 total += ctx->program_metrics[i].time_ns;
157 qsort_r(sorted, ctx->num_program_metrics, sizeof(*sorted),
158 time_compare, ctx->program_metrics);
160 for (i = 0; i < ctx->num_program_metrics; i++) {
161 struct program_metrics *metric =
162 &ctx->program_metrics[sorted[i]];
164 /* Since we sparsely fill the array based on program
165 * id, many "programs" have no time.
167 if (metric->time_ns == 0.0)
170 printf ("Program %d:\t%7.2f ms (% 2.1f%%)\n",
171 metric->id, metric->time_ns / 1e6,
172 metric->time_ns / total * 100);
176 /* Called at program exit */
181 printf ("fips: terminating\n");
186 metrics_end_frame (void)
188 static int initialized = 0;
189 static struct timeval tv_start, tv_now;
192 gettimeofday (&tv_start, NULL);
193 atexit (metrics_exit);
194 if (getenv ("FIPS_VERBOSE"))
200 printf ("fips: frame %d complete\n", frames);
203 gettimeofday (&tv_now, NULL);
205 /* Consume all counters that are ready. */
206 counter_t *counter = current_context.counter_head;
209 GLuint available, elapsed;
211 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT_AVAILABLE,
216 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed);
218 accumulate_program_time (counter->program, elapsed);
220 current_context.counter_head = counter->next;
221 if (current_context.counter_head == NULL)
222 current_context.counter_tail = NULL;
224 glDeleteQueries (1, &counter->id);
227 counter = current_context.counter_head;
230 if (frames % 60 == 0) {
233 fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec +
234 (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6);
236 printf("FPS: %.3f\n", fps);
238 print_program_metrics ();