Refactor, GLFW->SDL
[vg.git] / vg_profiler.h
diff --git a/vg_profiler.h b/vg_profiler.h
new file mode 100644 (file)
index 0000000..784fc28
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef VG_PROFILER_H
+#define VG_PROFILER_H
+
+#include "vg.h"
+#include "vg_platform.h"
+
+#define VG_PROFILE_SAMPLE_COUNT 128
+
+static int vg_profiler = 0;
+
+struct vg_profile
+{
+   const char *name;
+
+   u32 samples[ VG_PROFILE_SAMPLE_COUNT ];
+   u32 buffer_count, buffer_current;
+
+   enum profile_mode
+   {
+      k_profile_mode_frame,
+      k_profile_mode_accum
+   }
+   mode;
+
+   u64 start;
+};
+
+VG_STATIC void vg_profile_begin( struct vg_profile *profile )
+{
+   profile->start = SDL_GetPerformanceCounter();
+}
+
+VG_STATIC void vg_profile_increment( struct vg_profile *profile )
+{
+   profile->buffer_current ++;
+
+   if( profile->buffer_count < VG_PROFILE_SAMPLE_COUNT )
+      profile->buffer_count ++;
+
+   if( profile->buffer_current >= VG_PROFILE_SAMPLE_COUNT )
+      profile->buffer_current = 0;
+
+   profile->samples[ profile->buffer_current ] = 0.0f;
+}
+
+VG_STATIC void vg_profile_end( struct vg_profile *profile )
+{
+   u64 time_end;
+
+   time_end = SDL_GetPerformanceCounter();
+   u64 delta = profile->start - time_end;
+
+   if( profile->mode == k_profile_mode_frame )
+   {
+      profile->samples[ profile->buffer_current ] = delta;
+      vg_profile_increment( profile );
+   }
+   else
+   {
+      profile->samples[ profile->buffer_current ] += delta;
+   }
+}
+
+VG_STATIC void vg_profile_drawn( struct vg_profile **profiles, u32 count,
+                              float budget, ui_rect panel, u32 colour_offset )
+{
+   if( !vg_profiler )
+      return;
+
+   if( panel[2] == 0 )
+      panel[2] = 256;
+
+   if( panel[3] == 0 )
+      panel[3] = VG_PROFILE_SAMPLE_COUNT * 2;
+
+   float sh = panel[3] / VG_PROFILE_SAMPLE_COUNT,
+         sw = panel[2];
+
+   ui_fill_rect( panel, 0xa0000000 );
+
+   assert( count <= 8 );
+   float avgs[8];
+   int   ptrs[8];
+
+   for( int i=0; i<count; i++ )
+   {
+      ptrs[i] = profiles[i]->buffer_current;
+      avgs[i] = 0.0f;
+   }
+
+   u32 colours[] = { 0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000,
+                     0xffff00ff, 0xffffff00 };
+
+   float rate_mul = 1.0f / (float)SDL_GetPerformanceFrequency();
+
+   for( int i=0; i<VG_PROFILE_SAMPLE_COUNT-1; i++ )
+   {
+      float total = 0.0f;
+
+      for( int j=0; j<count; j++ )
+      {
+         ptrs[j] --;
+
+         if( ptrs[j] < 0 )
+            ptrs[j] = VG_PROFILE_SAMPLE_COUNT-1;
+
+         float sample  = (float)profiles[j]->samples[ptrs[j]] * rate_mul,
+               px      = (total  / (budget)) * sw,
+               wx      = (sample / (budget)) * sw;
+
+         ui_rect block = { panel[0] + px, panel[1] + (float)i*sh,
+                           wx,            sh };
+
+         u32 colour = colours[ (j+colour_offset) % vg_list_size(colours) ];
+         ui_fill_rect( block, colour );
+
+         total += sample;
+         avgs[j] += sample;
+      }
+   }
+
+   char infbuf[64];
+
+   for( int i=0; i<count; i++ )
+   {
+      snprintf( infbuf, 64, "%.4fms %s", 
+                        avgs[i] * (1.0f/(VG_PROFILE_SAMPLE_COUNT-1)),
+                        profiles[i]->name );
+
+      ui_text( (ui_rect){ panel[0] + panel[2] + 4,
+                          panel[1] + i * 14, 0, 0 }, 
+                          infbuf,
+                          1,
+                          k_text_align_left );
+   }
+}
+
+VG_STATIC void vg_profiler_init(void)
+{
+   vg_convar_push( (struct vg_convar){
+      .name = "vg_profiler",
+      .data = &vg_profiler,
+      .data_type = k_convar_dtype_i32,
+      .opt_i32 = { .min=0, .max=1, .clamp=1 },
+      .persistent = 1
+   });
+}
+
+#endif /* VG_PROFILER_H */