add basic memory viewer
authorhgn <hgodden00@gmail.com>
Wed, 25 Sep 2024 11:28:52 +0000 (12:28 +0100)
committerhgn <hgodden00@gmail.com>
Wed, 25 Sep 2024 11:28:52 +0000 (12:28 +0100)
vg_engine.c
vg_mem.c
vg_mem_view.c [new file with mode: 0644]
vg_mem_view.h [new file with mode: 0644]

index 37293b0da3e89aeba8ec9c8a58078c2bd0abaf0c..db025c8d8849eda12b6d717e0af8f445300268ed 100644 (file)
@@ -50,6 +50,7 @@ static void _vg_opengl_sync_init(void)
 
 #include "vg_console.h"
 #include "vg_profiler.h"
+#include "vg_mem_view.h"
 #ifndef VG_NO_AUDIO
   #include "vg_audio.h"
 #endif
@@ -128,6 +129,7 @@ vg_info("            '        ' '--' [] '----- '----- '     ' '---'  "
    vg_loader_step( vg_audio_init, vg_audio_free );
 #endif
    vg_loader_step( vg_profiler_init, NULL );
+   vg_loader_step( vg_mem_view_init, NULL );
 
    /* client */
 #ifdef VG_CUSTOM_SHADERS
@@ -314,7 +316,7 @@ static void _vg_gameloop_render(void)
       audio_debug_ui( &vg_ui.ctx, vg.pv );
 #endif
 
-               /* profiling */
+               /* profiling TODO MOVE TO OWN FILE */
       if( vg_profiler ){
          int frame_target = vg.display_refresh_rate;
          if( vg.fps_limit > 0 ) frame_target = vg.fps_limit;
@@ -346,6 +348,14 @@ static void _vg_gameloop_render(void)
          ui_text( &vg_ui.ctx, 
                   (ui_rect){258,4,900,900},perf,1,0,k_ui_align_left);
       }
+
+      if( vg_mem_view && vg_loader_availible() )
+      {
+         vg_mem_view_ui( &vg_ui.ctx, (ui_rect){400,32,
+                                               vg.window_x-400,vg.window_y-64},
+                       vg_mem.rtmemory, 0, "rtmemory" );
+      }
+
       ui_postrender( &vg_ui.ctx, vg.time_frame_delta );
       vg_ui_post_update();
    }
@@ -1336,6 +1346,7 @@ __attribute__((used)) int AmdPowerXpressRequestHighPerformance = 1;
 #include "vg_framebuffer.c"
 #include "vg_render.c"
 #include "vg_opengl.c"
+#include "vg_mem_view.c"
 
 #ifdef VG_CUSTOM_SHADERS
  #include "shaders/impl.c"
index 1b55b09b7e78bd225779b6c292f72451e7ac27fb..0e079188a83fe9a9c1632a99b661b95f4b8b0b2a 100644 (file)
--- a/vg_mem.c
+++ b/vg_mem.c
@@ -126,6 +126,22 @@ void *vg_linear_resize( void *buffer, void *data, u32 newsize )
    else return data;
 }
 
+void vg_libc_del_recursive( void *buffer )
+{
+   vg_linear_allocator *alloc = vg_linear_header( buffer );
+   for( u32 i=0; i<alloc->allocation_count; i ++ )
+   {
+      vg_allocation_meta *meta = &alloc->alloc_table[i];
+      if( meta->type == k_allocation_type_linear )
+         vg_libc_del_recursive( meta->data );
+      else
+         free( meta->data );
+   }
+
+   free( alloc->alloc_table );
+   free( alloc );
+}
+
 /* its possible to delete just the last item */
 void vg_linear_del( void *buffer, void *data )
 {
@@ -139,9 +155,9 @@ void vg_linear_del( void *buffer, void *data )
    {
       vg_allocation_meta *meta = &alloc->alloc_table[alloc->allocation_count-1];
       if( meta->type == k_allocation_type_linear )
-         vg_fatal_error( "Cannot free a linear allocator in this conext" );
-
-      free( data );
+         vg_libc_del_recursive( meta->data );
+      else
+         free( data );
    }
 
    alloc->allocation_count --;
diff --git a/vg_mem_view.c b/vg_mem_view.c
new file mode 100644 (file)
index 0000000..92af16d
--- /dev/null
@@ -0,0 +1,196 @@
+#include "vg_ui/imgui.h"
+
+int vg_mem_view = 0;
+
+void squarey_layout( ui_rect rect, f32 *areas, u32 area_count,
+                     void (*cb)( u32, ui_rect, void* ), void *cb_user )
+{
+   f32 area_total = 0.0f;
+   for( u32 i=0; i<area_count; i ++ )
+      area_total += areas[i];
+
+   u32 i=0, row_start=0, row_count=1;
+   f32 s = areas[0];
+
+L_LOOP_ADJUST:;
+   u32 short_side = rect[3] < rect[2]? 1: 0;
+   f32 norm = ((f32)rect[2] * (f32)rect[3]) / area_total,
+       w = rect[ 2+short_side ],
+       w2n = w*w*norm;
+L_LOOP:
+   i ++;
+   if( i == area_count )
+   {
+      cb( area_count-1, rect, cb_user );
+      return;
+   }
+
+   f32 s0 = s*norm,
+       s1 = s0+areas[i]*norm,
+       cur = vg_maxf( w2n*areas[row_start]/(s0*s0), (s0*s0)/(w2n*areas[i-1]) ),
+       new = vg_maxf( w2n*areas[row_start]/(s1*s1), (s1*s1)/(w2n*areas[i  ]) );
+
+   if( (new < cur) && (i != area_count-1) )
+   {
+      s += areas[ i ];
+      row_count ++;
+      goto L_LOOP;
+   }
+
+   ui_px height = s0 / w;
+   ui_rect out_box = { rect[0], rect[1] };
+   out_box[ 2+short_side^0x1 ] = height;
+   f32 ihn = (1.0f/(f32)height) * norm;
+
+   f32 x = rect[ short_side ];
+   ui_px start = x, end;
+   for( u32 j=0; j<row_count; j ++ )
+   {
+      if( j == row_count-1 ) 
+         end = rect[short_side]+rect[2+short_side];
+      else 
+      {
+         x += areas[ row_start + j ] * ihn;
+         end = x;
+      }
+
+      out_box[ short_side ] = start;
+      out_box[ 2+short_side ] = end-start;
+      cb( row_start + j, out_box, cb_user );
+      start=end;
+   }
+
+   rect[ short_side^0x1 ] += height;
+   rect[ 2+short_side^0x1 ] -= height;
+
+   area_total -= s;
+   s = areas[ i ];
+
+   row_count = 1;
+   row_start = i;
+   goto L_LOOP_ADJUST;
+}
+
+struct vg_mem_draw_inf
+{
+   ui_context *ui_ctx;
+   vg_linear_allocator *alloc;
+   i32 *indices;
+};
+
+void vg_mem_view_ui( ui_context *ctx, ui_rect rect, 
+                     void *lin_alloc, int depth, const char *name );
+
+static void vg_mem_draw_cb( u32 idx, ui_rect rect, void *user )
+{
+   struct vg_mem_draw_inf *inf = user;
+   ui_rect tmp;
+   rect_copy( rect, tmp );
+   tmp[2] --;
+   tmp[3] --;
+
+   idx = inf->indices[idx];
+   vg_allocation_meta *meta = &inf->alloc->alloc_table[idx];
+
+   if( meta->type == k_allocation_type_block )
+   {
+      ui_fill( inf->ui_ctx, tmp, 0x80000000 | (~0xff000000&(idx*0x45d9f3b)) );
+
+      if( tmp[2] > 20 && tmp[3] > 16 )
+         ui_text( inf->ui_ctx, tmp, meta->name, 1, k_ui_align_left, 0 );
+   }
+   else
+   {
+      vg_mem_view_ui( inf->ui_ctx, tmp, meta->data, 0, meta->name );
+   }
+
+   return;
+
+
+   char buf[32];
+   vg_mem_print_size( meta->size, buf );
+   ui_text( inf->ui_ctx, tmp, buf, 1, k_ui_align_middle_center, 0 );
+}
+
+vg_linear_allocator *_CB_values;
+int _CB_vg_mem_sort( const void *a, const void *b )
+{
+   i32 ia = *((const i32 *)a), ib = *((const i32 *)b);
+   f32 fa = _CB_values->alloc_table[ ia ].size,
+       fb = _CB_values->alloc_table[ ib ].size;
+   return (fa < fb) - (fa > fb);
+}
+
+void vg_mem_view_ui( ui_context *ctx, ui_rect rect, 
+                     void *lin_alloc, int depth, const char *name )
+{
+   f32 sizes[ VG_MAX_ALLOCATIONS ];
+   i32 indices[ VG_MAX_ALLOCATIONS ];
+
+   if( vg_mem.use_libc_malloc )
+   {
+      vg_linear_allocator *alloc = vg_linear_header( lin_alloc );
+      struct vg_mem_draw_inf inf = 
+      {
+         .ui_ctx = ctx,
+         .alloc = alloc,
+         .indices = indices,
+      };
+
+      if( alloc->allocation_count )
+      {
+         if( alloc->cur < alloc->size )
+         {
+            u32 short_side = rect[3] < rect[2]? 1: 0;
+            f32 p = 1.0f-((f32)alloc->cur / (f32)alloc->size);
+            ui_px h = (f32)rect[2+short_side^0x1] * p*p;
+            ui_rect out_box = {rect[0], rect[1]};
+            out_box[ 2+short_side^0x1 ] = h;
+            out_box[ 2+short_side ] = rect[ 2+short_side ];
+
+            ui_fill( ctx, out_box, 0x80303030 );
+
+            rect[ short_side^0x1 ] += h;
+            rect[ 2+short_side^0x1 ] -= h;
+         }
+
+         if( alloc->flags & VG_MEMORY_SYSTEM )
+         {
+            for( i32 i=0; i<alloc->allocation_count; i ++ )
+               indices[i] = i;
+
+            u32 count = alloc->allocation_count;
+            _CB_values = alloc;
+            qsort( indices, count, sizeof(i32), _CB_vg_mem_sort );
+
+            for( u32 i=0; i<alloc->allocation_count; i++ )
+            {
+               i32 indice = indices[i];
+
+               vg_allocation_meta *meta = &alloc->alloc_table[indice];
+               sizes[i] = sqrtf(meta->size);
+            }
+
+            squarey_layout( rect, sizes, count, vg_mem_draw_cb, &inf );
+         }
+         else
+         {
+            //printf( "<opaque memory> (UNTRACKED)\n" );
+         }
+      }
+      else
+      {
+         ui_fill( ctx, rect, 0x80101010 );
+         ui_text( ctx, rect, name, 1, k_ui_align_left, 0 );
+      }
+   }
+   else
+   {
+      //vg_error( "allocations are not tracked (turn on libc mode)\n" );
+   }
+}
+
+void vg_mem_view_init(void)
+{
+   VG_VAR_I32( vg_mem_view, flags=VG_VAR_PERSISTENT );
+}
diff --git a/vg_mem_view.h b/vg_mem_view.h
new file mode 100644 (file)
index 0000000..8792257
--- /dev/null
@@ -0,0 +1,5 @@
+#pragma once
+#include "vg_ui/imgui.h"
+extern int vg_mem_view;
+void vg_mem_view_init(void);
+void vg_mem_view_ui( ui_context *ctx, ui_rect rect, void *lin_alloc, int depth, const char *name );