latest
[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 float 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 VG_STATIC void vg_profile_begin( struct vg_profile *profile )
30 {
31 profile->start = SDL_GetPerformanceCounter();
32 }
33
34 VG_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.0f;
45 }
46
47 VG_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 {
54 profile->samples[ profile->buffer_current ] = (float)delta;
55 vg_profile_increment( profile );
56 }
57 else
58 {
59 profile->samples[ profile->buffer_current ] += delta;
60 }
61 }
62
63 VG_STATIC void vg_profile_graph_sample( struct vg_profile *profile, float s )
64 {
65 profile->samples[ profile->buffer_current ] = s;
66 vg_profile_increment( profile );
67 }
68
69 VG_STATIC void vg_profile_drawn( struct vg_profile **profiles, u32 count,
70 float budget, ui_rect panel, u32 colour_offset )
71 {
72 if( !vg_profiler )
73 return;
74
75 if( panel[2] == 0 )
76 panel[2] = 256;
77
78 if( panel[3] == 0 )
79 panel[3] = VG_PROFILE_SAMPLE_COUNT * 2;
80
81 float sh = panel[3] / VG_PROFILE_SAMPLE_COUNT,
82 sw = panel[2];
83
84 ui_fill_rect( panel, 0xa0000000 );
85
86 assert( count <= 8 );
87 float avgs[8];
88 int ptrs[8];
89
90 for( int i=0; i<count; i++ )
91 {
92 ptrs[i] = profiles[i]->buffer_current;
93 avgs[i] = 0.0f;
94 }
95
96 u32 colours[] = { 0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000,
97 0xffff00ff, 0xffffff00 };
98
99 float rate_mul = 1000.0f / (float)SDL_GetPerformanceFrequency();
100
101 for( int i=0; i<VG_PROFILE_SAMPLE_COUNT-1; i++ )
102 {
103 float total = 0.0f;
104
105 for( int j=0; j<count; j++ )
106 {
107 ptrs[j] --;
108
109 if( ptrs[j] < 0 )
110 ptrs[j] = VG_PROFILE_SAMPLE_COUNT-1;
111
112 float sample = profiles[j]->samples[ptrs[j]] * rate_mul,
113 px = (total / (budget)) * sw,
114 wx = (sample / (budget)) * sw;
115
116 ui_rect block = { panel[0] + px, panel[1] + (float)i*sh,
117 wx, sh };
118
119 u32 colour = colours[ (j+colour_offset) % vg_list_size(colours) ];
120 ui_fill_rect( block, colour );
121
122 total += sample;
123 avgs[j] += sample;
124 }
125 }
126
127 char infbuf[64];
128
129 for( int i=0; i<count; i++ )
130 {
131 snprintf( infbuf, 64, "%.4fms %s",
132 avgs[i] * (1.0f/(VG_PROFILE_SAMPLE_COUNT-1)),
133 profiles[i]->name );
134
135 ui_text( (ui_rect){ panel[0] + panel[2] + 4,
136 panel[1] + i * 14, 0, 0 },
137 infbuf,
138 1,
139 k_text_align_left );
140 }
141 }
142
143 VG_STATIC void vg_profiler_init(void)
144 {
145 vg_var_push( (struct vg_var){
146 .name = "vg_profiler",
147 .data = &vg_profiler,
148 .data_type = k_var_dtype_i32,
149 .opt_i32 = { .min=0, .max=1, .clamp=1 },
150 .persistent = 1
151 });
152 }
153
154 #endif /* VG_PROFILER_H */