#include "vg_console.h"
#include "vg_profiler.h"
+#include "vg_mem_view.h"
#ifndef VG_NO_AUDIO
#include "vg_audio.h"
#endif
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
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;
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();
}
#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"
--- /dev/null
+#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 );
+}