699e2a72eadfdacac40abac419c53737554c34dd
[vg.git] / vg_profiler.h
1 #ifndef VG_PROFILER_H
2 #define VG_PROFILER_H
3
4 #define VG_GAME
5 #include "vg.h"
6 #include "vg_platform.h"
7
8 #define VG_PROFILE_SAMPLE_COUNT 128
9
10 static int vg_profiler = 0;
11
12 struct vg_profile
13 {
14 const char *name;
15
16 u64 samples[ VG_PROFILE_SAMPLE_COUNT ];
17 u32 buffer_count, buffer_current;
18
19 enum profile_mode
20 {
21 k_profile_mode_frame,
22 k_profile_mode_accum
23 }
24 mode;
25
26 u64 start;
27 };
28
29 static void vg_profile_begin( struct vg_profile *profile )
30 {
31 profile->start = SDL_GetPerformanceCounter();
32 }
33
34 static void vg_profile_increment( struct vg_profile *profile )
35 {
36 profile->buffer_current ++;
37
38 if( profile->buffer_count < VG_PROFILE_SAMPLE_COUNT )
39 profile->buffer_count ++;
40
41 if( profile->buffer_current >= VG_PROFILE_SAMPLE_COUNT )
42 profile->buffer_current = 0;
43
44 profile->samples[ profile->buffer_current ] = 0;
45 }
46
47 static void vg_profile_end( struct vg_profile *profile )
48 {
49 u64 time_end = SDL_GetPerformanceCounter(),
50 delta = time_end - profile->start;
51
52 if( profile->mode == k_profile_mode_frame ){
53 profile->samples[ profile->buffer_current ] = delta;
54 vg_profile_increment( profile );
55 }
56 else{
57 profile->samples[ profile->buffer_current ] += delta;
58 }
59 }
60
61 static void vg_profile_drawn( struct vg_profile **profiles, u32 count,
62 f64 budget, ui_rect panel,
63 int dir, i32 normalize )
64 {
65 if( panel[2] == 0 )
66 panel[2] = 256;
67
68 if( panel[3] == 0 )
69 panel[3] = VG_PROFILE_SAMPLE_COUNT * 2;
70
71 f64 sh = (f32)panel[3^dir] / (f32)VG_PROFILE_SAMPLE_COUNT,
72 sw = (f32)panel[2^dir];
73
74 ui_fill( panel, 0xa0000000 );
75
76 assert( count <= 8 );
77 f64 avgs[8];
78 u32 colours[8];
79 for( u32 i=0; i<count; i ++ ){
80 avgs[i] = 0.0;
81 colours[i] = ui_colour( k_ui_red + ((i*3)&0xe) );
82 }
83
84 f64 rate_mul = 1000.0 / (f64)SDL_GetPerformanceFrequency();
85
86 for( i32 i=0; i<VG_PROFILE_SAMPLE_COUNT; i++ ){
87 f64 total = 0.0;
88
89 if( normalize ){
90 budget = 0.0;
91 for( u32 j=0; j<count; j++ )
92 budget += (f64)profiles[j]->samples[i] * rate_mul;
93 }
94
95 for( int j=0; j<count; j++ ){
96 f64 sample = (f64)profiles[j]->samples[i] * rate_mul,
97 px = (total / budget) * sw,
98 wx = (sample / budget) * sw;
99
100 ui_rect block;
101 block[0^dir] = panel[0^dir] + px;
102 block[1^dir] = panel[1^dir] + (f32)i*sh;
103 block[2^dir] = VG_MAX( 1, wx-1 );
104 block[3^dir] = ceilf(sh)-1;
105 ui_fill( block, colours[j] );
106
107 total += sample;
108 avgs[j] += sample;
109 }
110 }
111
112 char infbuf[64];
113
114 snprintf( infbuf, 64, "accuracy: %.7fms", rate_mul );
115 ui_text( (ui_rect){ panel[0] + 4,
116 panel[1] + panel[3] - 14, 500, 30 },
117 infbuf,
118 1,
119 k_ui_align_left, 0 );
120
121 for( int i=0; i<count; i++ ){
122 snprintf( infbuf, 64, "%.4fms %s",
123 avgs[i] * (1.0f/(VG_PROFILE_SAMPLE_COUNT-1)),
124 profiles[i]->name );
125
126 ui_text( (ui_rect){ panel[0] + 4,
127 panel[1] + panel[3] + 4 + i*14,
128 panel[2]-8, 14 },
129 infbuf, 1, k_ui_align_left, 0 );
130 }
131 }
132
133 static void vg_profiler_init(void)
134 {
135 VG_VAR_I32( vg_profiler, flags=VG_VAR_PERSISTENT );
136 }
137
138 #endif /* VG_PROFILER_H */