]> git.cworth.org Git - fips/blob - metrics.c
glxwrap: Initialize fips_dispatch when glxMakeContextCurrent is called
[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         unsigned id;
41         double ticks;
42 } program_metrics_t;
43
44 typedef struct context
45 {
46         unsigned int program;
47
48         counter_t *counter_head;
49         counter_t *counter_tail;
50
51         unsigned num_program_metrics;
52         program_metrics_t *program_metrics;
53 } context_t;
54
55 /* FIXME: Need a map from integers to context objects and track the
56  * current context with glXMakeContextCurrent, eglMakeCurrent, etc. */
57
58 context_t current_context;
59
60 int frames;
61 int verbose;
62
63 unsigned
64 metrics_counter_new (void)
65 {
66         counter_t *counter;
67
68         counter = malloc (sizeof(counter_t));
69         if (counter == NULL) {
70                 fprintf (stderr, "Out of memory\n");
71                 exit (1);
72         }
73
74         glGenQueries (1, &counter->id);
75
76         counter->program = current_context.program;
77         counter->next = NULL;
78
79         if (current_context.counter_tail) {
80                 current_context.counter_tail->next = counter;
81                 current_context.counter_tail = counter;
82         } else {
83                 current_context.counter_tail = counter;
84                 current_context.counter_head = counter;
85         }
86
87         return counter->id;
88 }
89
90 void
91 metrics_counter_start (unsigned counter)
92 {
93         glBeginQuery (GL_TIME_ELAPSED, counter);
94 }
95
96 void
97 metrics_counter_stop (void)
98 {
99         glEndQuery (GL_TIME_ELAPSED);
100 }
101
102 void
103 metrics_set_current_program (unsigned program)
104 {
105         current_context.program = program;
106 }
107
108 static void
109 accumulate_program_ticks (unsigned program_id, unsigned ticks)
110 {
111         context_t *ctx = &current_context;
112         unsigned i;
113
114         if (program_id >= ctx->num_program_metrics) {
115                 ctx->program_metrics = realloc (ctx->program_metrics,
116                                                 (program_id + 1) * sizeof (program_metrics_t));
117                 for (i = ctx->num_program_metrics; i < program_id + 1; i++) {
118                         ctx->program_metrics[i].id = i;
119                         ctx->program_metrics[i].ticks = 0.0;
120                 }
121
122                 ctx->num_program_metrics = program_id + 1;
123         }
124
125         ctx->program_metrics[program_id].ticks += ticks;
126 }
127
128 /* FIXME: Should sort the metrics, print out percentages, etc. */
129 static void
130 print_program_metrics (void)
131 {
132         context_t *ctx = &current_context;
133         unsigned i;
134
135         for (i = 0; i < ctx->num_program_metrics; i++) {
136                 if (ctx->program_metrics[i].ticks == 0.0)
137                         continue;
138                 printf ("Program %d:\t%7.2f mega-ticks\n",
139                         i, ctx->program_metrics[i].ticks / 1e6);
140         }
141 }
142
143 /* Called at program exit */
144 static void
145 metrics_exit (void)
146 {
147         if (verbose)
148                 printf ("fips: terminating\n");
149 }
150
151
152 void
153 metrics_end_frame (void)
154 {
155         static int initialized = 0;
156         static struct timeval tv_start, tv_now;
157
158         if (! initialized) {
159                 gettimeofday (&tv_start, NULL);
160                 atexit (metrics_exit);
161                 if (getenv ("FIPS_VERBOSE"))
162                         verbose = 1;
163                 initialized = 1;
164         }
165
166         if (verbose)
167                 printf ("fips: frame %d complete\n", frames);
168
169         frames++;
170         gettimeofday (&tv_now, NULL);
171
172         /* Consume all counters that are ready. */
173         counter_t *counter = current_context.counter_head;
174
175         while (counter) {
176                 GLuint available, elapsed;
177
178                 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT_AVAILABLE,
179                                      &available);
180                 if (! available)
181                         break;
182
183                 glGetQueryObjectuiv (counter->id, GL_QUERY_RESULT, &elapsed);
184
185                 accumulate_program_ticks (counter->program, elapsed);
186
187                 current_context.counter_head = counter->next;
188                 if (current_context.counter_head == NULL)
189                         current_context.counter_tail = NULL;
190
191                 glDeleteQueries (1, &counter->id);
192
193                 free (counter);
194                 counter = current_context.counter_head;
195         }
196
197         if (frames % 60 == 0) {
198                 double fps;
199
200                 fps = (double) frames / (tv_now.tv_sec - tv_start.tv_sec +
201                                          (tv_now.tv_usec - tv_start.tv_usec) / 1.0e6);
202
203                 printf("FPS: %.3f\n", fps);
204
205                 print_program_metrics ();
206         }
207 }