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