]> git.cworth.org Git - fips/blob - metrics.c
Add an explanatory comment for a surprisingly-unused field.
[fips] / metrics.c
1 /* Copyright © 2013, Intel Corporation
2  *
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:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
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
19  * THE SOFTWARE.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <sys/time.h>
26
27 #include "fips-dispatch-gl.h"
28
29 #include "metrics.h"
30
31 typedef struct counter
32 {
33         unsigned id;
34         unsigned program;
35         struct counter *next;
36 } counter_t;
37
38 typedef struct program_metrics
39 {
40         /* This happens to also be the index into the
41          * ctx->program_metrics array currently
42          */
43         unsigned id;
44         double ticks;
45 } program_metrics_t;
46
47 typedef struct context
48 {
49         unsigned int program;
50
51         counter_t *counter_head;
52         counter_t *counter_tail;
53
54         unsigned num_program_metrics;
55         program_metrics_t *program_metrics;
56 } context_t;
57
58 /* FIXME: Need a map from integers to context objects and track the
59  * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */
60
61 context_t current_context;
62
63 int frames;
64 int verbose;
65
66 unsigned
67 metrics_counter_new (void)
68 {
69         counter_t *counter;
70
71         counter = malloc (sizeof(counter_t));
72         if (counter == NULL) {
73                 fprintf (stderr, "Out of memory\n");
74                 exit (1);
75         }
76
77         glGenQueries (1, &counter->id);
78
79         counter->program = current_context.program;
80         counter->next = NULL;
81
82         if (current_context.counter_tail) {
83                 current_context.counter_tail->next = counter;
84                 current_context.counter_tail = counter;
85         } else {
86                 current_context.counter_tail = counter;
87                 current_context.counter_head = counter;
88         }
89
90         return counter->id;
91 }
92
93 void
94 metrics_counter_start (unsigned counter)
95 {
96         glBeginQuery (GL_TIME_ELAPSED, counter);
97 }
98
99 void
100 metrics_counter_stop (void)
101 {
102         glEndQuery (GL_TIME_ELAPSED);
103 }
104
105 void
106 metrics_set_current_program (unsigned program)
107 {
108         current_context.program = program;
109 }
110
111 static void
112 accumulate_program_ticks (unsigned program_id, unsigned ticks)
113 {
114         context_t *ctx = &current_context;
115         unsigned i;
116
117         if (program_id >= ctx->num_program_metrics) {
118                 ctx->program_metrics = realloc (ctx->program_metrics,
119                                                 (program_id + 1) * sizeof (program_metrics_t));
120                 for (i = ctx->num_program_metrics; i < program_id + 1; i++) {
121                         ctx->program_metrics[i].id = i;
122                         ctx->program_metrics[i].ticks = 0.0;
123                 }
124
125                 ctx->num_program_metrics = program_id + 1;
126         }
127
128         ctx->program_metrics[program_id].ticks += ticks;
129 }
130
131 /* FIXME: Should sort the metrics, print out percentages, etc. */
132 static void
133 print_program_metrics (void)
134 {
135         context_t *ctx = &current_context;
136         unsigned i;
137
138         for (i = 0; i < ctx->num_program_metrics; i++) {
139                 if (ctx->program_metrics[i].ticks == 0.0)
140                         continue;
141                 printf ("Program %d:\t%7.2f ms\n",
142                         i, ctx->program_metrics[i].ticks / 1e6);
143         }
144 }
145
146 /* Called at program exit */
147 static void
148 metrics_exit (void)
149 {
150         if (verbose)
151                 printf ("fips: terminating\n");
152 }
153
154
155 void
156 metrics_end_frame (void)
157 {
158         static int initialized = 0;
159         static struct timeval tv_start, tv_now;
160
161         if (! initialized) {
162                 gettimeofday (&tv_start, NULL);
163                 atexit (metrics_exit);
164                 if (getenv ("FIPS_VERBOSE"))
165                         verbose = 1;
166                 initialized = 1;
167         }
168
169         if (verbose)
170                 printf ("fips: frame %d complete\n", frames);
171
172         frames++;
173         gettimeofday (&tv_now, NULL);
174
175         /* Consume all counters that are ready. */
176         counter_t *counter = current_context.counter_head;
177
178         while (counter) {
179                 GLuint available, elapsed;
180
181                 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT_AVAILABLE,
182                                      &available);
183                 if (! available)
184                         break;
185
186                 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed);
187
188                 accumulate_program_ticks (counter->program, elapsed);
189
190                 current_context.counter_head = counter->next;
191                 if (current_context.counter_head == NULL)
192                         current_context.counter_tail = NULL;
193
194                 glDeleteQueries (1, &counter->id);
195
196                 free (counter);
197                 counter = current_context.counter_head;
198         }
199
200         if (frames % 60 == 0) {
201                 double fps;
202
203                 fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec +
204                                          (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6);
205
206                 printf("FPS: %.3f\n", fps);
207
208                 print_program_metrics ();
209         }
210 }