]> git.tdb.fi Git - gldbg.git/blob - flavors/gl/source/profiler.cpp
4b95208c4b0425424a2ca89d5973d096a4cce049
[gldbg.git] / flavors / gl / source / profiler.cpp
1 /* $Id$
2
3 This file is part of gldbg
4 Copyright © 2010-2011  Mikko Rasa, Mikkosoft Productions
5 Distributed under the GPL
6 */
7
8 #include <stdexcept>
9 #include <cstdio>
10 #include <ctime>
11 #include "gldbg.h"
12 #include "profiler.h"
13
14 using namespace std;
15
16 Profiler::Profiler(GlDbg &dbg):
17         decoder(gldecoder_new(this, 0)),
18         enabled(false)
19 {
20         dbg.get_command_interpreter().register_command("profile", this, &Profiler::cmd_profile)
21                 .set_help("Profiles GL usage and performance",
22                         "profile {on|off}\n"
23                         "  Enables or disables profiling\n");
24
25         decoder->glDrawArrays = glDrawArrays;
26         decoder->glDrawElements = glDrawElements;
27         decoder->glDrawRangeElements = glDrawRangeElements;
28         decoder->glXSwapBuffers = glXSwapBuffers;
29 }
30
31 void Profiler::decode(const char *data, unsigned len)
32 {
33         if(enabled)
34                 gldecoder_decode(decoder, data, len);
35 }
36
37 void Profiler::cmd_profile(const string &args)
38 {
39         if(args.empty() || args=="on")
40         {
41                 enabled = true;
42                 frames = 0;
43                 draw_calls = 0;
44                 vertices = 0;
45                 triangles = 0;
46                 start = get_time();
47         }
48         else if(args=="off")
49                 enabled = false;
50         else
51                 throw runtime_error("Invalid argument");
52 }
53
54 void Profiler::glDrawArrays(void *user_data, GLenum mode, int, int count)
55 {
56         glDrawElements(user_data, mode, count, 0, 0);
57 }
58
59 void Profiler::glDrawElements(void *user_data, GLenum mode, int count, GLenum, const void *)
60 {
61         Profiler *self = reinterpret_cast<Profiler *>(user_data);
62
63         ++self->draw_calls;
64         self->vertices += count;
65
66         switch(mode)
67         {
68         case GL_TRIANGLES:
69                 self->triangles += count/3;
70                 break;
71         case GL_TRIANGLE_STRIP:
72         case GL_TRIANGLE_FAN:
73                 if(count>2)
74                         self->triangles += count-2;
75                 break;
76         case GL_QUADS:
77                 self->triangles += count/4;
78                 break;
79         case GL_QUAD_STRIP:
80                 if(count>3)
81                         self->triangles += count/2-1;
82                 break;
83         }
84 }
85
86 void Profiler::glDrawRangeElements(void *user_data, GLenum mode, unsigned, unsigned, int count, GLenum type, const void *data)
87 {
88         glDrawElements(user_data, mode, count, type, data);
89 }
90
91 void Profiler::glXSwapBuffers(void *user_data, Display *, GLXDrawable)
92 {
93         Profiler *self = reinterpret_cast<Profiler *>(user_data);
94
95         printf("%d draw calls, %d vertices, %d triangles\n", self->draw_calls, self->vertices, self->triangles);
96         self->draw_calls = 0;
97         self->vertices = 0;
98         self->triangles = 0;
99
100         ++self->frames;
101         Time t = get_time();
102         float dt = (t-self->start)/1e6;
103         if(dt>1)
104         {
105                 printf("%d frames in %.2f seconds\n", self->frames, dt);
106                 self->start = t;
107                 self->frames = 0;
108         }
109 }
110
111 Profiler::Time Profiler::get_time()
112 {
113         struct timespec ts;
114         clock_gettime(CLOCK_REALTIME, &ts);
115         return ts.tv_sec*1000000+ts.tv_nsec/1000;
116 }