/* clip loading from disk
* -------------------------------------------------------------------------------
*/
-void audio_clip_load( audio_clip *clip, void *lin_alloc )
+void audio_clip_load( audio_clip *clip, vg_stack_allocator *stack )
{
- if( lin_alloc == NULL )
- lin_alloc = _vg_audio.data_allocator;
+ if( stack == NULL )
+ stack = _vg_audio.permanent_stack;
if( _vg_audio.always_keep_clips_compressed )
{
vg_error( "No path specified, embeded vorbis unsupported\n" );
vg_audio_lock();
- clip->any_data = vg_file_read( lin_alloc, clip->path, &clip->size );
+ clip->any_data = vg_file_read( stack, clip->path, &clip->size, 0 );
vg_audio_unlock();
if( !clip->any_data )
if( total_size > AUDIO_DECODE_SIZE )
vg_error( "Bird coding too long, and exceeds maximum decode size\n" );
- struct synth_bird *bird = vg_linear_alloc( lin_alloc, total_size );
+ struct synth_bird *bird = vg_stack_allocate( stack, total_size, 8, NULL );
memcpy( &bird->settings, clip->any_data, clip->size );
clip->any_data = bird;
else
{
if( !clip->path )
- {
vg_error( "No path specified, embeded mono unsupported\n" );
- }
- vg_linear_clear( vg_mem.scratch );
+ vg_stack_clear( &vg.scratch );
u32 fsize;
stb_vorbis_alloc alloc = {
- .alloc_buffer = vg_linear_alloc( vg_mem.scratch, AUDIO_DECODE_SIZE ),
+ .alloc_buffer = vg_stack_allocate( &vg.scratch, AUDIO_DECODE_SIZE, 8, NULL ),
.alloc_buffer_length_in_bytes = AUDIO_DECODE_SIZE
};
- void *filedata = vg_file_read( vg_mem.scratch, clip->path, &fsize );
+ void *filedata = vg_file_read( &vg.scratch, clip->path, &fsize, 0 );
int err;
stb_vorbis *decoder = stb_vorbis_open_memory( filedata, fsize, &err, &alloc );
data_size = length_samples * sizeof(i16);
vg_audio_lock();
- clip->any_data = vg_linear_alloc( lin_alloc, vg_align8(data_size) );
+ clip->any_data = vg_stack_allocate( stack, data_size, 8, NULL );
clip->size = length_samples;
vg_audio_unlock();
}
}
-void audio_clip_loadn( audio_clip *arr, int count, void *lin_alloc )
+void audio_clip_loadn( audio_clip *arr, int count, vg_stack_allocator *stack )
{
for( int i=0; i<count; i++ )
- audio_clip_load( &arr[i], lin_alloc );
+ audio_clip_load( &arr[i], stack );
}
/*
vg_fatal_error( "SDL2: %s\n", SDL_GetError() );
_vg_profile_reg_set( &_vg_prof_audio );
-
- /* allocate memory */
- /* 32mb fixed */
- _vg_audio.data_allocator = vg_create_linear_allocator( vg_mem.rtmemory, 1024*1024*32, VG_MEMORY_SYSTEM );
+ _vg_audio.permanent_stack = vg_stack_make_substack( &vg.rtmem, VG_MB(32), "Permanent audio data" );
+ vg_stack_set_flags( _vg_audio.permanent_stack, VG_STACK_ALLOCATOR_METADATA );
/* fixed */
u32 decode_size = AUDIO_DECODE_SIZE * AUDIO_CHANNELS;
- _vg_audio.decoding_buffer = vg_linear_alloc( vg_mem.rtmemory, decode_size );
+ _vg_audio.decoding_buffer = vg_stack_allocate( &vg.rtmem, decode_size, 8, "Decoding buffers" );
struct audio_master_controls *master_controls = &_vg_audio.controls;
master_controls->dsp_enabled = _vg_audio.dsp_enabled_ui;
SDL_AudioDeviceID sdl_output_device;
vg_str device_choice; /* buffer is null? use default from OS */
- void *data_allocator; /* allocator for practically static sound data */
- void *decoding_buffer; /* place where raw samples get decoded into */
+ vg_stack_allocator *permanent_stack;
+ void *decoding_buffer;
SDL_mutex *mutex;
u32 samples_written_last_audio_frame;
void vg_audio_init(void);
void vg_audio_free(void);
-void audio_clip_load( audio_clip *clip, void *lin_alloc );
-void audio_clip_loadn( audio_clip *arr, int count, void *lin_alloc );
+void audio_clip_load( audio_clip *clip, vg_stack_allocator *stack );
+void audio_clip_loadn( audio_clip *arr, int count, vg_stack_allocator *stack );
void vg_audio_lock(void);
void vg_audio_unlock(void);
void vg_dsp_init( void )
{
vg_rand_seed( &vg_dsp.rand, 461 );
- vg_dsp.buffer = vg_linear_alloc( vg_mem.rtmemory, 1024*1024*1 );
+ vg_dsp.buffer = vg_stack_allocate( &vg.rtmem, VG_MB(1), 8, "Audio DSP Buffer" );
/* temporary global design */
dsp_init_lpf( &__lpf_mud_free, 125.0f );
vg_strcat( &cmd, " -Wall -ferror-limit=10\\\n"
" -Wno-unused-function -Wno-unused-variable\\\n"
" -Wno-unused-command-line-argument -Wno-unused-but-set-variable\\\n"
+ " -Wunused-result\\\n"
);
if( env->compiler != k_compiler_clang )
bh_subdivide( bh, 0 );
}
-bh_tree *bh_create( void *lin_alloc, bh_system *system,
- void *user, u32 item_count, u32 max_per_leaf )
+bh_tree *bh_create( vg_stack_allocator *stack, bh_system *system, void *user, u32 item_count, u32 max_per_leaf )
{
u32 alloc_count = VG_MAX( 1, item_count );
u32 totsize = sizeof(bh_tree) + sizeof(bh_node)*(alloc_count*2-1);
- bh_tree *bh = lin_alloc? vg_linear_alloc( lin_alloc, vg_align8(totsize) ):
- malloc( totsize );
+ bh_tree *bh = stack? vg_stack_allocate( stack, totsize, 8, "BVH Tree" ): vg_malloc( totsize );
bh->system = system;
bh->user = user;
bh->max_per_leaf = max_per_leaf;
bh_rebuild( bh, item_count );
- if( lin_alloc ){
- totsize = vg_align8(sizeof(bh_tree) + sizeof(bh_node) * bh->node_count);
- bh = vg_linear_resize( lin_alloc, bh, totsize );
- }
+ totsize = sizeof(bh_tree) + sizeof(bh_node) * bh->node_count;
+
+ if( stack ) vg_stack_resize_last( stack, totsize );
+ else bh = vg_realloc( bh, totsize );
vg_success( "BVH done, size: %u/%u\n", bh->node_count, (alloc_count*2-1) );
return bh;
{
vg_line_boxf( node->bbx, 0xff00ff00 );
- if( bh->system->item_debug ){
- for( u32 i=0; i<node->count; i++ ){
+ if( bh->system->item_debug )
+ {
+ for( u32 i=0; i<node->count; i++ )
+ {
u32 idx = node->start+i;
bh->system->item_debug( bh->user, idx );
}
void bh_update_bounds( bh_tree *bh, u32 inode );
void bh_subdivide( bh_tree *bh, u32 inode );
void bh_rebuild( bh_tree *bh, u32 item_count );
-bh_tree *bh_create( void *lin_alloc, bh_system *system,
- void *user, u32 item_count, u32 max_per_leaf );
+
+bh_tree *bh_create( vg_stack_allocator *stack, bh_system *system, void *user, u32 item_count, u32 max_per_leaf );
void bh_debug_leaf( bh_tree *bh, bh_node *node );
char *exe_basepath = SDL_GetBasePath();
u32 len = vg_align8( strlen(exe_basepath)+1 );
- char *dest = vg_linear_alloc( vg_mem.rtmemory, len );
+ char *dest = vg_stack_allocate( &vg.rtmem, len, 1, "Exe basepath" );
strcpy( dest, exe_basepath );
SDL_free( exe_basepath );
vg.base_path = dest;
exit(0);
}
-static int cmd_log_memory( int argc, const char *argv[] )
-{
- vg_mem_log( vg_mem.rtmemory, 0, "rtmemory" );
- return 0;
-}
-
static int _vg_loader_thread( void *pfn )
{
SDL_TLSSet( vg.thread_purpose, &_thread_purpose_loader, NULL );
if( (arg = vg_long_opt_arg( "samples", "Rendering samples per pixel" )) )
vg.samples = VG_MAX( 0, VG_MIN( 8, atoi( arg ) ) );
- if( vg_long_opt( "use-libc-malloc", "Use standard libc allocator" ) )
- vg_mem.use_libc_malloc = 1;
-
if( vg_long_opt( "high-performance", "Turn graphics to lowest quality" ) )
vg.quality_profile = k_quality_profile_low;
exit(0);
/* Systems init */
- vg_alloc_quota();
vg_console_init();
vg_magi_init();
vg_console_load_autos();
vg_console_reg_cmd( "vg_settings", cmd_vg_settings_toggle, NULL );
- vg_console_reg_cmd( "vg_rtmemory", cmd_log_memory, NULL );
_vg_init_window( vg.window_name );
SDL_SetRelativeMouseMode(1);
struct vg_engine
{
+ vg_stack_allocator rtmem, scratch;
+
/* Engine sync */
SDL_Window *window;
SDL_GLContext gl_context;
}
}
-vg_framebuffer *vg_framebuffer_allocate( void *alloc, u32 attachment_count, bool track )
+vg_framebuffer *vg_framebuffer_allocate( vg_stack_allocator *stack, u32 attachment_count, bool track )
{
- vg_framebuffer *fb = vg_linear_alloc( alloc, sizeof(vg_framebuffer) );
+ vg_framebuffer *fb = VG_STACK_ALLOCATE_STRUCT( stack, vg_framebuffer );
if( track )
{
}
}
- fb->attachments = vg_linear_alloc( alloc, sizeof(vg_framebuffer_attachment) * attachment_count );
+ fb->attachments = vg_stack_allocate( stack, sizeof(vg_framebuffer_attachment) * attachment_count, 8, NULL );
fb->attachment_count = attachment_count;
-
return fb;
}
* Allocation of a framebuffer memory. Optionally, track this framebuffer in
* debugging systems.
*/
-vg_framebuffer *vg_framebuffer_allocate( void *alloc, u32 attachment_count, bool track );
+vg_framebuffer *vg_framebuffer_allocate( vg_stack_allocator *stack, u32 attachment_count, bool track );
/*
* Allocate graphics memory and initialize
}
}
-#define VG_FILE_IO_CHUNK_SIZE 1024*256
+#define VG_FILE_IO_CHUNK_SIZE VG_KB(256)
/* read entire binary file */
-void *vg_file_read( void *lin_alloc, const char *path, u32 *size )
+void *vg_file_read( vg_stack_allocator *stack, const char *path, u32 *size, bool text )
{
FILE *f = fopen( path, "rb" );
if( f )
{
- void *buffer = lin_alloc? vg_linear_alloc( lin_alloc, 0 ): NULL;
+ if( !stack )
+ {
+ stack = alloca( sizeof(vg_stack_allocator) );
+ vg_stack_init( stack, NULL, VG_FILE_IO_CHUNK_SIZE, "Stretchy file buffer" );
+ vg_stack_set_flags( stack, VG_STACK_ALLOCATOR_DOUBLE_IF_FULL );
+ }
+
+ u8 *buffer = vg_stack_allocate( stack, 0, 8, "File data" );
u64 current = 0;
/* read in chunks */
for( u32 i=0; 1; i++ )
{
- if( lin_alloc )
- buffer = vg_linear_extend( lin_alloc,buffer,VG_FILE_IO_CHUNK_SIZE );
- else
- buffer = realloc( buffer, current + VG_FILE_IO_CHUNK_SIZE );
-
+ vg_stack_extend_last( stack, VG_FILE_IO_CHUNK_SIZE );
u64 l = fread( buffer + current, 1, VG_FILE_IO_CHUNK_SIZE, f );
current += l;
if( l != VG_FILE_IO_CHUNK_SIZE )
{
if( feof( f ) )
- {
break;
- }
else
{
if( ferror( f ) )
}
}
- if( lin_alloc )
- buffer = vg_linear_resize( lin_alloc, buffer, vg_align8(current) );
- else
- buffer = realloc( buffer, vg_align8(current) );
+ if( text )
+ {
+ vg_stack_extend_last( stack, 1 );
+ buffer[ current ++ ] = '\0';
+ }
+ vg_stack_resize_last( stack, current );
fclose( f );
*size = (u32)current;
return buffer;
}
- else{
+ else
+ {
vg_error( "vg_disk_open_read: %s (file: %s)\n", strerror(errno), path );
return NULL;
}
}
-/* read entire file and append a null on the end */
-char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz )
-{
- u32 size;
- char *str = vg_file_read( lin_alloc, path, &size );
-
- if( !str )
- return NULL;
-
- /* include null terminator */
- if( lin_alloc )
- str = vg_linear_extend( lin_alloc, str, 1 );
- else
- str = realloc( str, size+1 );
-
- str[ size ] = '\0';
- *sz = size+1;
-
- return str;
-}
-
-
-int vg_asset_write( const char *path, void *data, i64 size )
+bool vg_asset_write( const char *path, void *data, i64 size )
{
FILE *f = fopen( path, "wb" );
- if( f ){
+ if( f )
+ {
fwrite( data, size, 1, f );
fclose( f );
return 1;
}
- else{
+ else
return 0;
- }
-}
-
-/* TODO: error handling if read fails */
-int vg_file_copy( const char *src, const char *dst, void *lin_alloc )
-{
- vg_info( "vg_file_copy( %s -> %s )\n", src, dst );
- u32 size;
- void *data = vg_file_read( lin_alloc, src, &size );
- return vg_asset_write( dst, data, size );
}
const char *vg_path_filename( const char *path )
{
const char *base = path;
-
- for( int i=0; i<1024; i++ ){
- if( path[i] == '\0' ) break;
- if( path[i] == '/' ){
+ for( int i=0; i<1024; i++ )
+ {
+ if( path[i] == '\0' )
+ break;
+ if( path[i] == '/' )
base = path+i+1;
- }
}
return base;
* File I/O
*/
-/* read entire binary file */
-void *vg_file_read( void *lin_alloc, const char *path, u32 *size );
+/* read entire binary file, if text is 1, appends a nul to the end of the buffer */
+void *vg_file_read( vg_stack_allocator *stack, const char *path, u32 *size, bool text );
-/* read entire file and append a null on the end */
-char *vg_file_read_text( void *lin_alloc, const char *path, u32 *sz );
-
-int vg_asset_write( const char *path, void *data, i64 size );
-int vg_file_copy( const char *src, const char *dst, void *lin_alloc );
+bool vg_asset_write( const char *path, void *data, i64 size );
const char *vg_path_filename( const char *path );
void vg_file_error_info( FILE *fp );
--- /dev/null
+#include "vg_kv.h"
+
+
--- /dev/null
+#pragma once
+#include "vg_platform.h"
+
+struct vg_kv
+{
+ u32 key_info; /* 20 bit hash, 10 bit key length, 2 bit type */
+ u32 key_offset; /* into the raw text buffer */
+ u32 brother_offset;/* 24 bits, relative jump past all descendents to the next key */
+
+ union
+ {
+ struct
+ {
+ u16 offset_from_key, length;
+ }
+ value;
+
+ u32 children; /* 24 bits */
+ };
+};
}
};
-#define VG_LINES_BUFFER_SIZE 50000 * sizeof( struct vg_lines_vert )
+#define VG_LINES_MAX_VERTS 50000
static void async_vg_lines_init( void *_ )
{
glGenBuffers( 1, &vg_lines.vbo );
glBindVertexArray( vg_lines.vao );
glBindBuffer( GL_ARRAY_BUFFER, vg_lines.vbo );
-
- glBufferData( GL_ARRAY_BUFFER, VG_LINES_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW );
+ glBufferData( GL_ARRAY_BUFFER, VG_LINES_MAX_VERTS*sizeof(struct vg_lines_vert), NULL, GL_DYNAMIC_DRAW );
glBindVertexArray( vg_lines.vao );
/* Pointers */
void vg_lines_init(void)
{
THREAD_1;
+ vg_lines.vertex_buffer = vg_stack_allocate( &vg.rtmem, VG_LINES_MAX_VERTS*sizeof(struct vg_lines_vert),
+ 8, "Debugging Lines" );
- vg_lines.vertex_buffer = vg_create_linear_allocator( vg_mem.rtmemory, VG_LINES_BUFFER_SIZE, VG_MEMORY_REALTIME);
vg_async_call( &vg.main_tasks, async_vg_lines_init, NULL );
vg_console_reg_var( "vg_lines", &vg_lines.render, k_var_dtype_i32, VG_VAR_CHEAT );
vg_shader_register( &_shader_lines );
void vg_lines_drawall( void )
{
glUseProgram( _shader_lines.id );
-
- glUniformMatrix4fv( glGetUniformLocation( _shader_lines.id, "uPv" ),
- 1, GL_FALSE, (float *)vg.pv );
+ glUniformMatrix4fv( glGetUniformLocation( _shader_lines.id, "uPv" ), 1, GL_FALSE, (f32 *)vg.pv );
glBindVertexArray( vg_lines.vao );
glBindBuffer( GL_ARRAY_BUFFER, vg_lines.vbo );
-
- u32 bufusage = vg_linear_get_cur(vg_lines.vertex_buffer);
- glBufferSubData( GL_ARRAY_BUFFER, 0, bufusage, vg_lines.vertex_buffer );
+ glBufferSubData( GL_ARRAY_BUFFER, 0, vg_lines.vertex_count*sizeof(struct vg_lines_vert), vg_lines.vertex_buffer );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glBlendEquation( GL_FUNC_ADD );
if( vg_lines.render )
- glDrawArrays( GL_LINES, 0, bufusage / sizeof(struct vg_lines_vert) );
+ glDrawArrays( GL_LINES, 0, vg_lines.vertex_count );
glDisable( GL_BLEND );
- vg_linear_clear( vg_lines.vertex_buffer );
+ vg_lines.vertex_count = 0;
}
void vg_line2( line_co from, line_co to, u32 fc, u32 tc )
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
- u32 size = 2 * sizeof(struct vg_lines_vert);
- struct vg_lines_vert *v = vg_linear_alloc( vg_lines.vertex_buffer, size );
+ if( vg_lines.vertex_count < VG_LINES_MAX_VERTS )
+ {
+ struct vg_lines_vert *v = &vg_lines.vertex_buffer[ vg_lines.vertex_count ];
- v3_copy( from, v[0].co );
- v3_copy( to, v[1].co );
+ v3_copy( from, v[0].co );
+ v3_copy( to, v[1].co );
- v[0].colour = fc;
- v[1].colour = tc;
+ v[0].colour = fc;
+ v[1].colour = tc;
+
+ vg_lines.vertex_count += 2;
+ }
}
void vg_line( line_co from, line_co to, u32 colour )
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
vg_line2( from, to, colour, colour );
}
-void vg_line_arrow( line_co co, line_co dir, float size, u32 colour )
+void vg_line_arrow( line_co co, line_co dir, f32 size, u32 colour )
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
v3f p1, tx, ty, p2, p3;
v3_muladds( co, dir, size, p1 );
void vg_line_box_verts( boxf box, v3f verts[8] )
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
- for( u32 i=0; i<8; i++ ){
- for( u32 j=0; j<3; j++ ){
+ for( u32 i=0; i<8; i++ )
+ for( u32 j=0; j<3; j++ )
verts[i][j] = i&(0x1<<j)? box[1][j]: box[0][j];
- }
- }
}
-void vg_line_mesh( v3f verts[], u32 indices[][2], u32 indice_count,u32 colour ){
- if( !vg_lines.enabled ) return;
+void vg_line_mesh( v3f verts[], u32 indices[][2], u32 indice_count,u32 colour )
+{
+ if( !vg_lines.enabled )
+ return;
- for( u32 i=0; i<indice_count; i++ ){
+ for( u32 i=0; i<indice_count; i++ )
vg_line( verts[indices[i][0]], verts[indices[i][1]], colour );
- }
}
void vg_line_boxf( boxf box, u32 colour )
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
v3f verts[8];
vg_line_box_verts( box, verts );
void vg_line_boxf_transformed( m4x3f m, boxf box, u32 colour )
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
v3f verts[8];
vg_line_box_verts( box, verts );
- for( u32 i=0; i<8; i++ ){
+ for( u32 i=0; i<8; i++ )
m4x3_mulv( m, verts[i], verts[i] );
- }
u32 indices[][2] = {{0,1},{1,3},{3,2},{2,0},
{4,5},{5,7},{7,6},{6,4},
vg_line_mesh( verts, indices, VG_ARRAY_LEN(indices), colour );
}
-void vg_line_cross(v3f pos,u32 colour, float scale)
+void vg_line_cross(v3f pos,u32 colour, f32 scale)
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
v3f p0, p1;
v3_add( (v3f){ scale,0.0f,0.0f}, pos, p0 );
vg_line( p0, p1, colour );
}
-void vg_line_point( v3f pt, float size, u32 colour )
+void vg_line_point( v3f pt, f32 size, u32 colour )
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
boxf box =
{
}
-void vg_line_sphere( m4x3f m, float radius, u32 colour )
+void vg_line_sphere( m4x3f m, f32 radius, u32 colour )
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
v3f ly = { 0.0f, 0.0f, radius },
lx = { 0.0f, radius, 0.0f },
lz = { 0.0f, 0.0f, radius };
for( int i=0; i<16; i++ ){
- float t = ((float)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
- s = sinf(t),
- c = cosf(t);
+ f32 t = ((f32)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
+ s = sinf(t),
+ c = cosf(t);
v3f py = { s*radius, 0.0f, c*radius },
px = { s*radius, c*radius, 0.0f },
}
}
-void vg_line_capsule( m4x3f m, float radius, float h, u32 colour )
+void vg_line_capsule( m4x3f m, f32 radius, f32 h, u32 colour )
{
- if( !vg_lines.enabled ) return;
+ if( !vg_lines.enabled )
+ return;
v3f ly = { 0.0f, 0.0f, radius },
lx = { 0.0f, radius, 0.0f },
lz = { 0.0f, 0.0f, radius };
- float s0 = sinf(0.0f)*radius,
- c0 = cosf(0.0f)*radius;
+ f32 s0 = sinf(0.0f)*radius,
+ c0 = cosf(0.0f)*radius;
v3f p0, p1, up, right, forward;
m3x3_mulv( m, (v3f){0.0f,1.0f,0.0f}, up );
vg_line( a0, a1, colour );
vg_line( b0, b1, colour );
- for( int i=0; i<16; i++ ){
- float t = ((float)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
- s1 = sinf(t)*radius,
- c1 = cosf(t)*radius;
+ for( int i=0; i<16; i++ )
+ {
+ f32 t = ((f32)(i+1) * (1.0f/16.0f)) * VG_PIf * 2.0f,
+ s1 = sinf(t)*radius,
+ c1 = cosf(t)*radius;
v3f e0 = { s0, 0.0f, c0 },
e1 = { s1, 0.0f, c1 },
vg_line( a0, a1, colour );
vg_line( b0, b1, colour );
- if( c0 < 0.0f ){
+ if( c0 < 0.0f )
+ {
v3_add( p0, e2, a0 );
v3_add( p0, e3, a1 );
v3_add( p0, e4, b0 );
v3_add( p0, e5, b1 );
}
- else{
+ else
+ {
v3_add( p1, e2, a0 );
v3_add( p1, e3, a1 );
v3_add( p1, e4, b0 );
u32 enabled,
render;
- struct vg_lines_vert{
+ struct vg_lines_vert
+ {
v3f co;
u32 colour;
}
*vertex_buffer;
+ u32 vertex_count;
GLuint vao, vbo;
}
#include <stdlib.h>
#include <malloc.h>
-struct vg_global_mem vg_mem;
+void *vg_malloc( u64 size )
+{
+ void *buf = malloc( size );
+ if( !buf )
+ vg_fatal_error( "Out of memory (OS)\n" );
+ return buf;
+}
+
+void vg_free( void *buf )
+{
+ free( buf );
+}
+
+void *vg_realloc( void *buf, u64 size )
+{
+ buf = realloc( buf, size );
+ if( !buf )
+ vg_fatal_error( "Out of memory (OS)\n" );
+ return buf;
+}
+
+void vg_zero_mem( void *buffer, u32 length )
+{
+ u8 *u8s = buffer;
+ for( u32 i=0; i<length; i++ )
+ u8s[i] = 0;
+}
+/* NOT USED IN THIS FILE */
u32 vg_align16( u32 s )
{
u32 m = (s + 15) >> 4;
return m << 2;
}
-/* Returns allocator structure from data pointer */
-vg_linear_allocator *vg_linear_header( void *data )
+void vg_stack_init( vg_stack_allocator *stack, void *buffer, u32 capacity, const char *debug_name )
{
- vg_linear_allocator *ptr = data;
- ptr --;
+ VG_ASSERT( sizeof( vg_allocation_meta ) == 24 );
+ VG_ASSERT( sizeof( vg_stack_allocator ) == 24 );
- return ptr;
+ vg_zero_mem( stack, sizeof(vg_stack_allocator) );
+ stack->data = buffer? buffer: vg_malloc( capacity );
+ stack->capacity = capacity;
+ stack->flags = buffer? 0: VG_STACK_ALLOCATOR_BUFFER_FROM_MALLOC;
}
-/* allocate something from a linear allocator */
-__attribute__((warn_unused_result))
-void *_vg_linear_alloc( void *buffer, u32 size, const char *constr_name )
+vg_stack_allocator *vg_stack_make_substack( vg_stack_allocator *parent, u32 capacity, const char *debug_name )
{
- if( size % 8 )
- size = vg_align8( size );
-
- if( ((u64)buffer) % 8 )
- vg_fatal_error( "Tried allocating to an unaligned buffer (%p)", buffer );
+ void *block = vg_stack_allocate( parent, sizeof(vg_stack_allocator) + capacity, 8, debug_name );
+ vg_stack_set_flags_last( parent, VG_ALLOCATION_FLAG_IS_STACK );
- vg_linear_allocator *alloc = vg_linear_header( buffer );
-
- if( (alloc->cur + size) > alloc->size )
- vg_fatal_error( "linear allocator overflow (%u + %u > %u)\n",
- alloc->cur, size, alloc->size );
+ vg_stack_allocator *stack = block;
+ vg_stack_init( stack, block + sizeof(vg_stack_allocator), capacity, debug_name );
+ return stack;
+}
- if( alloc->flags & VG_MEMORY_SYSTEM )
+static void vg_stack_growmaybe( vg_stack_allocator *stack, u32 new_usage )
+{
+ if( new_usage > stack->capacity )
{
- if( (alloc->allocation_count + 1) > VG_MAX_ALLOCATIONS )
+ if( stack->flags & VG_STACK_ALLOCATOR_DOUBLE_IF_FULL )
{
- vg_fatal_condition();
- vg_info( "Linear allocators marked as 'SYSTEMS', have a hard limit of "
- "%u allocations.\n\n"
- "The limit was exceeded by the following request:\n",
- VG_MAX_ALLOCATIONS );
- vg_info( " Name: %s\n", constr_name );
- vg_info( " Size: %u bytes\n", size );
- vg_fatal_exit();
- }
- }
-
- void *data;
+ u32 cap = stack->capacity * 2;
+ if( new_usage > cap )
+ cap = new_usage;
- if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
- {
- data = malloc( size );
-
- vg_allocation_meta *meta = &alloc->alloc_table[ alloc->allocation_count ];
- meta->type = k_allocation_type_block;
- meta->data = data;
- meta->size = size;
- meta->name = constr_name;
+ stack->data = vg_realloc( stack->data, cap );
+ stack->capacity = cap;
+ }
+ else
+ {
+ vg_fatal_error( "Stack allocator overflow (capacity: %u, used: %u, new_usage: %u)\n",
+ stack->capacity, stack->used, new_usage );
+ }
}
- else
- data = buffer + alloc->cur;
-
- u8 *bytes = data;
- for( u32 i=0; i<size; i++ )
- bytes[i] = 0xfe;
-
- alloc->allocation_count ++;
- alloc->last_alloc = data;
- alloc->last_alloc_size = size;
- alloc->cur += size;
-
- if( ((u64)data) % 8 )
- vg_fatal_error( "Resultant allocation was unaligned, most likely memory "
- "corruption or programmer error\n" );
- return data;
}
-/* resize latest block of memory from linear */
-__attribute__((warn_unused_result))
-void *vg_linear_resize( void *buffer, void *data, u32 newsize )
+void *vg_stack_allocate( vg_stack_allocator *stack, u32 size, u32 alignment, const char *debug_name )
{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
-
- if( newsize % 8 )
- newsize = vg_align8( newsize );
-
- if( alloc->last_alloc != data )
- vg_fatal_error( "Tried to resize allocation in linear allocator which "
- "has allocated other things after this block.\n" );
-
- if( (alloc->cur - alloc->last_alloc_size + newsize) > alloc->size )
- vg_fatal_error( "Tried to resize allocation to new size which would "
- "overflow the allocator\n" );
+ VG_ASSERT( (alignment >= 1) && (alignment <= 8) );
+ VG_ASSERT( ~stack->used & (0x1<<31) );
+ VG_ASSERT( ~size & (0x1<<31) );
- alloc->cur -= alloc->last_alloc_size;
- alloc->cur += newsize;
- alloc->last_alloc_size = newsize;
-
- if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
+ u32 block_size = size;
+ if( stack->flags & VG_STACK_ALLOCATOR_METADATA )
{
- data = realloc( data, newsize );
- if( !data )
- vg_fatal_error( "We are libc mode, and realloc failed" );
-
- alloc->alloc_table[ alloc->allocation_count-1 ].data = data;
- alloc->alloc_table[ alloc->allocation_count-1 ].size = newsize;
- alloc->last_alloc = data;
- return data;
+ block_size += sizeof( vg_allocation_meta );
+ alignment = 8;
}
- 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 );
- }
+ u32 previous_base_offset = stack->used - stack->last_allocation_totalsize;
+ stack->last_allocation_totalsize = block_size;
- free( alloc->alloc_table );
- free( alloc );
-}
+ u32 new_usage = stack->used + block_size + alignment;
+ vg_stack_growmaybe( stack, new_usage );
-/* its possible to delete just the last item */
-void vg_linear_del( void *buffer, void *data )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
+ while( stack->used & (alignment-1) )
+ stack->used ++;
- if( alloc->last_alloc != data )
- vg_fatal_error( "This block has been fixed and cannot be deleted.\n"
- "Last alloc: %p, this: %p\n", alloc->last_alloc, data );
+ void *block = (void *)stack->data + stack->used;
+ stack->used += block_size;
- if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
+ if( stack->flags & VG_STACK_ALLOCATOR_METADATA )
{
- vg_allocation_meta *meta = &alloc->alloc_table[alloc->allocation_count-1];
- if( meta->type == k_allocation_type_linear )
- vg_libc_del_recursive( meta->data );
- else
- free( data );
- }
+ vg_allocation_meta *meta = block;
+ memset( block, 0, sizeof(vg_allocation_meta) );
+ meta->name = debug_name;
+ meta->size = size;
+ meta->previous_offset = previous_base_offset;
+ meta->flags = 0;
- alloc->allocation_count --;
- alloc->cur -= alloc->last_alloc_size;
- alloc->last_alloc = NULL;
- alloc->last_alloc_size = 0;
+ return (void *)meta->data;
+ }
+ else return block;
}
-void vg_allocator_free( void *allocator )
+void vg_stack_clear( vg_stack_allocator *stack )
{
- if( vg_mem.use_libc_malloc )
- vg_libc_del_recursive( allocator );
- else
- free( vg_linear_header( allocator ) );
+ stack->used = 0;
+ stack->last_allocation_totalsize = 0;
}
-/* extend latest block of memory from linear */
-__attribute__((warn_unused_result))
-void *_vg_linear_extend( void *buffer, void *data, u32 extra,
- const char *constr_name )
+void vg_stack_free( vg_stack_allocator *stack )
{
- if( !data )
- return _vg_linear_alloc( buffer, vg_align8(extra), constr_name );
-
- vg_linear_allocator *alloc = vg_linear_header( buffer );
-
- if( alloc->last_alloc != data )
- vg_fatal_error( "This block has been fixed!" );
-
- u32 new_size = alloc->last_alloc_size + extra;
- return vg_linear_resize( buffer, data, vg_align8(new_size) );
+ if( stack->flags & VG_STACK_ALLOCATOR_BUFFER_FROM_MALLOC )
+ vg_free( stack->data );
+ vg_zero_mem( stack, sizeof(vg_stack_allocator) );
}
-/* get the current usage of allocator */
-u32 vg_linear_get_cur( void *buffer )
+void vg_stack_set_flags( vg_stack_allocator *stack, u16 append_flags )
{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
- return alloc->cur;
-}
+ if( append_flags & VG_STACK_ALLOCATOR_DOUBLE_IF_FULL )
+ if( !(stack->flags & VG_STACK_ALLOCATOR_BUFFER_FROM_MALLOC) )
+ vg_fatal_error( "Cannot append DOUBLE_IF_FULL to stack allocator, since buffer wasn't from malloc.\n" );
-/* get the capacity of allocator. */
-u32 vg_linear_get_capacity( void *buffer )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
- return alloc->size;
-}
+ if( append_flags & VG_STACK_ALLOCATOR_METADATA )
+ if( stack->used )
+ vg_fatal_error( "Cannot append METADATA to stack allocator after allocating something.\n" );
-/* get the remaining size of the allocator */
-u32 vg_linear_remaining( void *buffer )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
- return alloc->size - alloc->cur;
+ stack->flags |= append_flags;
}
-/* yeet all memory from linear allocator */
-void vg_linear_clear( void *buffer )
+void vg_stack_set_flags_last( vg_stack_allocator *stack, u16 append_flags )
{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
-
- /* libc mode we recursively free any allocations made */
- if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){
- for( u32 i=0; i<alloc->allocation_count; i++ ){
- vg_allocation_meta *meta = &alloc->alloc_table[i];
-
- if( meta->type == k_allocation_type_block ){
- free( meta->data );
- }
- else{
- vg_linear_clear( meta->data );
- vg_linear_allocator *sub = vg_linear_header( meta->data );
-
- free( sub->alloc_table );
- free( sub );
- }
- }
- }
+ if( !(stack->flags & VG_STACK_ALLOCATOR_METADATA) )
+ vg_fatal_error( "Stack allocator does not have the METADATA flag set.\n" );
- alloc->last_alloc = NULL;
- alloc->last_alloc_size = 0;
- alloc->allocation_count = 0;
- alloc->cur = 0;
+ vg_allocation_meta *meta = (void *)stack->data + (stack->used - stack->last_allocation_totalsize);
+ meta->flags |= append_flags;
}
-/* allocate a FIXED SIZE linear allocator
- *
- * FIXME: there was a bug in vg's code that caused a race condition between
- * two system allocations. make this IMPOSSIBLE by requiring a lock
- * on the allocater to be passed between threads.
- *
- * luckily that bug only exists when using development tools, but still!
- *
- * this should then only be checked and turned on in debugging.
- *
- */
-void *_vg_create_linear_allocator( void *lin_alloc, u32 size, u16 flags, const char *constr_name)
+void vg_stack_resize_last( vg_stack_allocator *stack, u32 new_size )
{
- VG_ASSERT( sizeof( vg_linear_allocator ) == 32 );
+ u32 base_offset = stack->used - stack->last_allocation_totalsize,
+ block_size = new_size;
- vg_linear_allocator *header;
- u32 block_size = size + sizeof(vg_linear_allocator);
-
- /* Creating it inside an existing one */
- if( lin_alloc )
+ if( stack->flags & VG_STACK_ALLOCATOR_METADATA )
{
- vg_linear_allocator *alloc = vg_linear_header( lin_alloc );
-
- if( alloc->cur + block_size > alloc->size )
- vg_fatal_error( "Out of memory (%u + %u > %u)\n", alloc->cur, block_size, alloc->size );
-
- if( alloc->allocation_count + 1 > VG_MAX_ALLOCATIONS )
- vg_fatal_error( "Exceeded max allocations in linear allocator (%u)\n", VG_MAX_ALLOCATIONS );
-
- if( (flags && VG_MEMORY_SYSTEM) && (alloc->flags & VG_MEMORY_REALTIME) )
- vg_fatal_error( "Cannot declare realtime allocator inside systems allocator");
-
- if( vg_mem.use_libc_malloc ){
- vg_allocation_meta *meta =
- &alloc->alloc_table[ alloc->allocation_count ];
-
- if( flags & VG_MEMORY_REALTIME )
- header = malloc( block_size );
- else
- header = malloc( sizeof(vg_linear_allocator) );
-
- meta->data = header+1;
- meta->type = k_allocation_type_linear;
- meta->size = size;
- meta->name = constr_name;
- }
- else header = lin_alloc + alloc->cur;
-
- alloc->cur += block_size;
- alloc->last_alloc = header;
- alloc->last_alloc_size = block_size;
- alloc->allocation_count ++;
- }
- else{
- if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) )
- header = malloc( sizeof(vg_linear_allocator) );
- else
- header = malloc( block_size );
+ vg_allocation_meta *meta = (void *)stack->data + base_offset;
+ meta->size = new_size;
+ block_size += sizeof( vg_allocation_meta );
}
- header->allocation_count = 0;
- header->cur = 0;
- header->last_alloc = NULL;
- header->last_alloc_size = 0;
- header->size = size;
- header->flags = flags;
-
- if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) )
- {
- u32 table_size = sizeof(vg_allocation_meta)*VG_MAX_ALLOCATIONS;
- header->alloc_table = malloc( table_size );
- }
- else header->alloc_table = NULL;
-
- return header+1;
+ u32 new_usage = base_offset + block_size;
+ vg_stack_growmaybe( stack, new_usage );
+ stack->used = new_usage;
+ stack->last_allocation_totalsize = block_size;
}
-/* request all the memory we need in advance */
-void vg_set_mem_quota( u32 size )
+void vg_stack_extend_last( vg_stack_allocator *stack, u32 extra_bytes )
{
- vg_mem.quota = size;
+ u32 current_size = stack->last_allocation_totalsize;
+ if( stack->flags & VG_STACK_ALLOCATOR_METADATA )
+ current_size -= sizeof(vg_allocation_meta);
+ vg_stack_resize_last( stack, current_size + extra_bytes );
}
-void vg_alloc_quota(void)
+void *vg_stack_pop_last( vg_stack_allocator *stack )
{
- u32 size_scratch = 10*1024*1024;
- u32 size = VG_MAX( vg_mem.quota, size_scratch );
-
- vg_mem.rtmemory = _vg_create_linear_allocator( NULL, size, VG_MEMORY_SYSTEM,
- "VG Root" );
- vg_mem.scratch = _vg_create_linear_allocator( vg_mem.rtmemory,
- size_scratch,
- VG_MEMORY_SYSTEM,
- "Scratch buffer" );
+ if( !(stack->flags & VG_STACK_ALLOCATOR_METADATA) )
+ vg_fatal_error( "Stack allocator does not have the METADATA flag set.\n" );
+
+ if( !stack->last_allocation_totalsize )
+ return NULL;
+
+ u32 base_offset = stack->used - stack->last_allocation_totalsize;
+ vg_allocation_meta *meta = (void *)stack->data + base_offset;
+
+ stack->last_allocation_totalsize = base_offset - meta->previous_offset;
+ stack->used = base_offset;
+ return (void *)meta->data;
}
static void vg_mem_print_size( u32 bytes, char buf[32] )
else
snprintf( buf, 32, "%ub", bytes );
}
-
-void vg_mem_log( void *lin_alloc, int depth, const char *name )
-{
- if( vg_mem.use_libc_malloc ){
- vg_linear_allocator *alloc = vg_linear_header( lin_alloc );
-
- u32 s = alloc->size;
- f32 p = ((float)alloc->cur / (float)s) * 100.0f;
-
- for( int i=0; i<depth; i++ ) printf( " " );
-
- char asize[32];
- vg_mem_print_size( s, asize );
- printf( "LA(%s): %s, %f%% used\n", name, asize, p );
-
- if( alloc->flags & VG_MEMORY_SYSTEM ){
- for( u32 i=0; i<alloc->allocation_count; i++ ){
- vg_allocation_meta *meta = &alloc->alloc_table[i];
-
- if( meta->type == k_allocation_type_block ){
- for( int i=0; i<depth+1; i++ ) printf( " " );
- vg_mem_print_size( meta->size, asize );
- printf( "B(%s): %s\n", meta->name, asize );
- }
- else{
- vg_mem_log( meta->data, depth +1, meta->name );
- }
- }
- }
- else{
- for( int i=0; i<depth+1; i++ ) printf( " " );
- printf( "<opaque memory> (UNTRACKED)\n" );
- }
- }
- else{
- vg_error( "allocations are not tracked (turn on libc mode)\n" );
- }
-}
#pragma once
+#include "vg_platform.h"
+#include <stdalign.h>
-#define VG_MAX_ALLOCATIONS 256
+#define VG_KB( X ) (X*1024)
+#define VG_MB( X ) (X*1024*1024)
+#define VG_GB( X ) (X*1024*1024*1024)
-typedef struct vg_linear_allocator vg_linear_allocator;
-typedef struct vg_allocation_meta vg_allocation_meta;
+void *vg_malloc( u64 size );
+void *vg_realloc( void *buf, u64 size );
+void vg_free( void *buf );
+void vg_zero_mem( void *buffer, u32 length );
-struct vg_global_mem
-{
- void *rtmemory,
- *scratch;
+typedef struct vg_stack_allocator vg_stack_allocator;
+typedef struct vg_allocation_meta vg_allocation_meta;
- int use_libc_malloc;
- u32 quota;
-}
-extern vg_mem;
+#define VG_ALLOCATION_FLAG_IS_STACK 0x1
+/* 24 bytes + size */
struct vg_allocation_meta
{
const char *name;
- void *data;
+
u32 size;
- enum allocation_type{
- k_allocation_type_block = 0,
- k_allocation_type_linear = 1
- }
- type;
+ u32 previous_offset;
+ u16 flags;
+ u16 unused0;
+ u32 unused1;
+
+ u64 data[];
};
-#define VG_MEMORY_SYSTEM 0x1 /* systems memory, slow and low counts */
-#define VG_MEMORY_REALTIME 0x2 /* per-frame. no max allocs, only size. fast */
+/* configuration flags */
+#define VG_STACK_ALLOCATOR_METADATA 0x1
+#define VG_STACK_ALLOCATOR_DOUBLE_IF_FULL 0x2
-/*
- * Stored just behind the array. 32 bytes.
- */
-#pragma pack(push,1)
-struct vg_linear_allocator
+/* system flags */
+#define VG_STACK_ALLOCATOR_BUFFER_FROM_MALLOC 0x4
+
+/* 24 bytes */
+struct vg_stack_allocator
{
- u32 size;
- u32 cur;
- u16 allocation_count;
+ u32 capacity; /* bytes */
+ u32 used;
+ u32 last_allocation_totalsize;
u16 flags;
- u32 last_alloc_size;
- void *last_alloc;
- vg_allocation_meta *alloc_table;
+ u16 unused0;
+
+ void *data;
};
-#pragma pack(pop)
+/* NOT USED IN THIS FILE */
u32 vg_align16( u32 s );
u32 vg_align8( u32 s );
u32 vg_align4( u32 s );
-/* allocate something from a linear allocator */
-__attribute__((warn_unused_result))
-void *_vg_linear_alloc( void *buffer, u32 size, const char *constr_name );
-
-/* resize latest block of memory from linear */
-__attribute__((warn_unused_result))
-void *vg_linear_resize( void *buffer, void *data, u32 newsize );
-
-/* its possible to delete just the last item */
-void vg_linear_del( void *buffer, void *data );
-
-/* extend latest block of memory from linear */
-__attribute__((warn_unused_result))
-void *_vg_linear_extend( void *buffer, void *data, u32 extra,
- const char *constr_name );
-
-/* get the current usage of allocator */
-u32 vg_linear_get_cur( void *buffer );
-
-/* get the capacity of allocator. */
-u32 vg_linear_get_capacity( void *buffer );
-
-/* get the remaining size of the allocator */
-u32 vg_linear_remaining( void *buffer );
-
-/* yeet all memory from linear allocator */
-void vg_linear_clear( void *buffer );
-
-/* request all the memory we need in advance */
-void vg_set_mem_quota( u32 size );
-
-/* essentially init() */
-void vg_alloc_quota(void);
-
-/* print out tree of current memory used. only works with libc mode */
-void vg_mem_log( void *lin_alloc, int depth, const char *name );
+/* If parent_stack is NULL, it will malloc a new stack of size
+ * If parent_stack is not NULL, it will allocate the new stack inside of this one. This allows it to be seen in the
+ * metadata as a tree structure.
+ */
+void vg_stack_init( vg_stack_allocator *stack, void *buffer, u32 capacity, const char *debug_name );
+void *vg_stack_allocate( vg_stack_allocator *stack, u32 size, u32 alignment, const char *debug_name );
+void vg_stack_clear( vg_stack_allocator *stack );
+void vg_stack_free( vg_stack_allocator *stack );
+void vg_stack_set_flags( vg_stack_allocator *stack, u16 append_flags );
+vg_stack_allocator *vg_stack_make_substack( vg_stack_allocator *parent, u32 capacity, const char *debug_name );
-#define VG_MEM_MCSTR(S) VG_MEM_MCSTR2(S)
-#define VG_MEM_MCSTR2(S) #S
+#define VG_STACK_ALLOCATE_STRUCT( STACK, STRUCT ) vg_stack_allocate( STACK, sizeof(STRUCT), alignof(STRUCT), NULL )
-#define vg_linear_alloc(...) \
- _vg_linear_alloc( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) )
-#define vg_linear_extend(...) \
- _vg_linear_extend( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) )
-#define vg_create_linear_allocator(...) \
- _vg_create_linear_allocator( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) )
+void vg_stack_resize_last( vg_stack_allocator *stack, u32 new_size );
+void vg_stack_extend_last( vg_stack_allocator *stack, u32 extra_bytes );
-void *_vg_create_linear_allocator( void *lin_alloc, u32 size,
- u16 flags, const char *constr_name);
-vg_linear_allocator *vg_linear_header( void *data );
-void vg_allocator_free( void *allocator );
+/*
+ * The following are availible if allocator has the flag METADATA set
+ */
+void vg_stack_set_flags_last( vg_stack_allocator *stack, u16 append_flags );
+void *vg_stack_pop_last( vg_stack_allocator *stack );
#include "vg_ui/imgui.h"
-int vg_mem_view = 0;
+struct mem_view_data
+{
+ void *base_buffer;
+ u32 route[8];
+ u32 route_depth;
+
+ bool vis_dirty;
+ u32 vis_offset;
+ v4f vis_colour;
+ f32 vis_inv_max;
+ GLuint vis_tex;
+ u32 vis_i, vis_size;
+
+ struct mem_view_info
+ {
+ const char *display_name;
+ u32 buffer_offset, buffer_size; /* offset + size into route[0]->data */
-void squarey_layout( ui_rect rect, f32 *areas, u32 area_count,
- void (*cb)( u32, ui_rect, void* ), void *cb_user )
+ bool is_stack;
+ u32 stack_used_bytes,
+ stack_children_start, stack_children_count; /* offset + count into this array (infos), children are sorted
+ by capacity / size */
+ }
+ infos[ 4096 ];
+ u32 info_count;
+ f32 sizes[ 4096 ];
+
+ f32 vis_data[256*256];
+};
+
+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 ++ )
goto L_LOOP_ADJUST;
}
-struct vg_mem_view_result
-{
- vg_allocation_meta *target;
- ui_rect target_rect;
- u32 colour;
-};
-
-struct vg_mem_draw_inf
+struct vg_mem_draw_blocks_context
{
ui_context *ui_ctx;
- vg_linear_allocator *alloc;
- i32 *indices;
+ struct mem_view_data *mv;
u32 root_colour;
+ u32 root_id;
+ u32 depth;
- struct vg_mem_view_result *result;
+ u32 highlight_id;
+ u32 highlight_colour;
+ ui_rect highlight_rect;
};
-static void vg_mem_view_ui( ui_context *ctx, ui_rect rect,
- void *lin_alloc, const char *name, u32 root_colour,
- struct vg_mem_view_result *result );
+static void vg_mem_view_stack( struct vg_mem_draw_blocks_context *context, ui_rect rect );
-static void vg_mem_draw_cb( u32 idx, ui_rect rect, void *user )
+static void vg_mem_draw_block_cb( u32 idx, ui_rect rect, void *user )
{
- struct vg_mem_draw_inf *inf = user;
+ struct vg_mem_draw_blocks_context *context = 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];
+ struct mem_view_info *root_info = &context->mv->infos[ context->root_id ],
+ *this_info = &context->mv->infos[ root_info->stack_children_start + idx ];
u32 colour;
- if( inf->root_colour ) colour = inf->root_colour;
- else colour = ~0xff000000&((idx+5)*0x45d9f3b);
+ if( context->root_colour ) colour = context->root_colour;
+ else colour = ~0xff000000&((idx+5)*0x45d9f3b);
- if( meta->type == k_allocation_type_block )
+ if( this_info->is_stack )
{
- ui_fill( inf->ui_ctx, tmp, 0x80000000 | colour );
- ui_outline( inf->ui_ctx, tmp, -1, 0xff000000 | colour, 0 );
+ struct vg_mem_draw_blocks_context next_level = *context;
+ next_level.depth ++;
+ next_level.root_colour = colour;
+ next_level.root_id = root_info->stack_children_start + idx;
+
+ ui_rect subrect;
+ rect_copy( rect, subrect );
+ vg_mem_view_stack( &next_level, subrect );
}
else
- vg_mem_view_ui( inf->ui_ctx, tmp, meta->data, meta->name, colour, NULL );
+ {
+ ui_fill( context->ui_ctx, tmp, 0x80000000 | colour );
+ ui_outline( context->ui_ctx, tmp, -1, 0xff000000 | colour, 0 );
+ }
- if( inf->result )
+ if( context->depth == 0 )
{
- if( ui_inside_rect( rect, inf->ui_ctx->mouse ) )
+ if( ui_inside_rect( rect, context->ui_ctx->mouse ) )
{
- inf->result->target = meta;
- inf->result->colour = colour;
- rect_copy( rect, inf->result->target_rect );
+ context->highlight_colour = colour;
+ context->highlight_id = root_info->stack_children_start + idx;
+ rect_copy( rect, context->highlight_rect );
}
}
}
-vg_linear_allocator *_CB_values;
-int _CB_vg_mem_sort( const void *a, const void *b )
+static void vg_mem_view_stack( struct vg_mem_draw_blocks_context *context, ui_rect rect )
{
- 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);
-}
+ struct mem_view_info *info = &context->mv->infos[ context->root_id ];
+ VG_ASSERT( info->is_stack );
-static void vg_mem_view_ui( ui_context *ctx, ui_rect rect,
- void *lin_alloc, const char *name, u32 root_colour,
- struct vg_mem_view_result *result )
-{
- f32 sizes[ VG_MAX_ALLOCATIONS ];
- i32 indices[ VG_MAX_ALLOCATIONS ];
-
- if( vg_mem.use_libc_malloc )
+ if( info->stack_used_bytes )
{
- vg_linear_allocator *alloc = vg_linear_header( lin_alloc );
- struct vg_mem_draw_inf inf =
+ /* draw unused stack space as dark black */
+ if( info->stack_used_bytes < info->buffer_size )
{
- .ui_ctx = ctx,
- .alloc = alloc,
- .indices = indices,
- .result = result,
- .root_colour = root_colour
- };
+ u32 short_side = rect[3] < rect[2]? 1: 0;
+ f32 p = 1.0f-((f32)info->stack_used_bytes / (f32)info->buffer_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 ];
- 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, 0x80000000 );
-
- char asize[32];
- vg_mem_print_size( alloc->size-alloc->cur, asize );
- ui_text( ctx, out_box, asize, 1, k_ui_align_middle_center, 0 );
+ ui_fill( context->ui_ctx, out_box, 0x80000000 );
- 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;
+ char asize[32];
+ vg_mem_print_size( info->buffer_size - info->stack_used_bytes, asize );
+ ui_text( context->ui_ctx, out_box, asize, 1, k_ui_align_middle_center, 0 );
- 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" );
- }
+ rect[ short_side^0x1 ] += h;
+ rect[ 2+short_side^0x1 ] -= h;
}
- else
+
+ if( info->stack_children_count )
{
- ui_fill( ctx, rect, 0x80101010 );
- //ui_text( ctx, rect, name, 1, k_ui_align_left, 0 );
+ squarey_layout( rect, &context->mv->sizes[ info->stack_children_start ], info->stack_children_count,
+ vg_mem_draw_block_cb, context );
}
+ else
+ ui_fill( context->ui_ctx, rect, 0x80101010 );
}
else
- {
- //vg_error( "allocations are not tracked (turn on libc mode)\n" );
- }
+ ui_fill( context->ui_ctx, rect, 0x80000000 );
}
-struct mem_view_data
-{
- void *main_buffer[8],
- *inspecting;
- v4f inspect_colour;
-
- const char *walk[8];
-
- u32 depth;
-
- f32 vis_data[256*256];
- GLuint tex;
-};
-
-static void cb_vg_mem_view( ui_context *ctx, ui_rect rect,
- struct vg_magi_panel *magi )
+static void cb_vg_mem_view( ui_context *ctx, ui_rect rect, struct vg_magi_panel *magi )
{
struct mem_view_data *mv = magi->data;
- struct vg_mem_view_result result = { .target=NULL };
ui_rect left;
ui_split( rect, k_ui_axis_v, 256+16, 2, left, rect );
/* Tree back-tracker */
{
- ui_rect bib = { left[0],left[1],left[2],24 };
- u32 new_depth = mv->depth;
- for( u32 i=0; i<mv->depth+1; i ++ )
+ ui_rect box = { left[0],left[1],left[2],24 };
+ u32 new_depth = mv->route_depth;
+ for( u32 i=0; i<mv->route_depth+1; i ++ )
{
- if( i != mv->depth )
+ struct mem_view_info *info = &mv->infos[ mv->route[i] ];
+ if( i != mv->route_depth )
{
- if( ui_button_text( ctx, bib, mv->walk[ i ], 1 ) == 1 )
+ if( ui_button_text( ctx, box, info->display_name, 1 ) == 1 )
{
new_depth = i;
}
}
else
{
- ui_fill( ctx, bib, ui_colour( ctx, k_ui_bg ) );
- ui_text( ctx, bib, mv->walk[i], 1, k_ui_align_middle_center, 0 );
+ ui_fill( ctx, box, ui_colour( ctx, k_ui_bg ) );
+ ui_text( ctx, box, info->display_name, 1, k_ui_align_middle_center, 0 );
}
- bib[0] += 8;
- bib[2] -= 8;
- bib[1] += 24;
+ box[0] += 8;
+ box[2] -= 8;
+ box[1] += 24;
}
- mv->depth = new_depth;
- ui_px v = (mv->depth+1)*24;
+ mv->route_depth = new_depth;
+ ui_px v = (mv->route_depth+1)*24;
left[1] += v;
left[3] -= v;
}
- if( vg_mem.use_libc_malloc == 0 )
+ struct vg_mem_draw_blocks_context context =
{
- ui_text( ctx, rect, "Run with --use-libc-malloc to view memory",
- 1, k_ui_align_middle_center, 0 );
- return;
- }
-
- vg_mem_view_ui( ctx, rect, mv->main_buffer[ mv->depth ], "", 0, &result );
-
- if( result.target )
+ .ui_ctx = ctx,
+ .mv = mv,
+ .root_colour = 0,
+ .root_id = mv->route[ mv->route_depth ],
+ .highlight_id = 0xffffffff,
+ .depth = 0
+ };
+ vg_mem_view_stack( &context, rect );
+
+ if( context.highlight_id != 0xffffffff )
{
- ui_outline( ctx, result.target_rect, 1, ui_colour( ctx,k_ui_bg+7 ), 0 );
- ui_info( ctx, left, result.target->name );
+ struct mem_view_info *highlight_info = &mv->infos[ context.highlight_id ];
+
+ ui_outline( ctx, context.highlight_rect, 1, ui_colour( ctx,k_ui_bg+7 ), 0 );
+ ui_info( ctx, left, highlight_info->display_name );
char buf[32];
- vg_mem_print_size( result.target->size, buf );
+ vg_mem_print_size( highlight_info->buffer_size, buf );
ui_info( ctx, left, buf );
- if( mv->inspecting != result.target->data )
+ if( mv->vis_offset != highlight_info->buffer_offset )
{
- if( result.target->type == k_allocation_type_block )
- {
- for( u32 i=0; i<256*256; i++ ) mv->vis_data[i] = 0.0f;
- f32 max_freq = 0.0f;
-
- const u8 *src = result.target->data;
- for( u32 i=0; i<result.target->size-1; i ++ )
- {
- u8 x = src[i], y = src[i+1];
- u32 offset = y*256 + x;
-
- mv->vis_data[ offset ] += 1.0f;
- max_freq = vg_maxf( mv->vis_data[ offset ], max_freq );
- }
-
- f32 median = 0.0f;
- for( u32 i=0; i<256*256; i++ ) median += mv->vis_data[i];
- median /= 256.0f*256.0f;
-
- f32 inv_max = 1.0f/logf(1.0f+median*2.0f);
- for( u32 i=0; i<256*256; i++ )
- {
- f32 v = logf(mv->vis_data[i]) * inv_max;
- mv->vis_data[i] = v;
- }
+ mv->vis_offset = highlight_info->buffer_offset;
+ mv->vis_i = 0;
+ mv->vis_size = highlight_info->buffer_size;
+ mv->vis_dirty = 1;
+ mv->vis_inv_max = 1.0f;
+
+ f32 nrm = 2.6f / 255.0f;
+ mv->vis_colour[0] = (f32)((context.highlight_colour ) & 0xff) * nrm;
+ mv->vis_colour[1] = (f32)((context.highlight_colour>>8 ) & 0xff) * nrm;
+ mv->vis_colour[2] = (f32)((context.highlight_colour>>16) & 0xff) * nrm;
+ mv->vis_colour[3] = 1.0f;
+
+ for( u32 i=0; i<256*256; i++ )
+ mv->vis_data[i] = 0.0f;
+ }
- glBindTexture( GL_TEXTURE_2D, mv->tex );
- glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 256,
- GL_RED, GL_FLOAT, mv->vis_data );
+ if( mv->vis_i+1 < mv->vis_size )
+ {
+ const u8 *src = mv->base_buffer + mv->vis_offset;
+ for( u32 it=0; it<VG_KB(20) && (mv->vis_i+1 < mv->vis_size); it ++ )
+ {
+ u8 x = src[mv->vis_i], y = src[mv->vis_i+1];
+ u32 coord = y*256 + x;
+ mv->vis_data[ coord ] += 1.0f;
+ mv->vis_i ++;
}
- mv->inspecting = result.target->data;
+ f32 median = (f32)mv->vis_i;
+ mv->vis_inv_max = 1.0f/logf(1.0f+median*2.0f);
+ mv->vis_dirty = 1;
+ }
- f32 nrm = 1.6f / 255.0f;
- mv->inspect_colour[0] = (f32)((result.colour ) & 0xff) * nrm;
- mv->inspect_colour[1] = (f32)((result.colour>>8 ) & 0xff) * nrm;
- mv->inspect_colour[2] = (f32)((result.colour>>16) & 0xff) * nrm;
- mv->inspect_colour[3] = 1.0f;
+ if( mv->vis_dirty )
+ {
+ glBindTexture( GL_TEXTURE_2D, mv->vis_tex );
+ glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 256, GL_RED, GL_FLOAT, mv->vis_data );
}
- if( result.target->type == k_allocation_type_block )
- ui_info( ctx, left, "Leaf" );
- else
+ if( highlight_info->is_stack )
ui_info( ctx, left, "Linear Allocator (expand)" );
+ else
+ ui_info( ctx, left, "Leaf" );
- if( result.target->type == k_allocation_type_block )
- {
- ui_rect freq_box = { left[0]+8, left[1], 256,256 };
-
- ui_flush( ctx, k_ui_shader_colour, NULL );
- ui_fill_rect( ctx, freq_box, 0xffffffff, (ui_px[4]){ 0,256,256,0 } );
- struct ui_batch_shader_data_image inf = { .resource = &mv->tex };
- v4_copy( mv->inspect_colour, vg_ui.colour );
- ui_flush( ctx, k_ui_shader_grad, &inf );
- v4_copy( (v4f){1,1,1,1}, vg_ui.colour );
- }
+ ui_rect freq_box = { left[0]+8, left[1], 256,256 };
- if( result.target->type == k_allocation_type_linear )
+ ui_flush( ctx, k_ui_shader_colour, NULL );
+ ui_fill_rect( ctx, freq_box, 0xffffffff, (ui_px[4]){ 0,256,256,0 } );
+ struct ui_batch_shader_data_image_gradient inf = {
+ .resource = &mv->vis_tex,
+ .log = 1,
+ .scale = mv->vis_inv_max
+ };
+ v4_copy( mv->vis_colour, vg_ui.colour );
+ ui_flush( ctx, k_ui_shader_grad, &inf );
+ v4_copy( (v4f){1,1,1,1}, vg_ui.colour );
+
+ if( highlight_info->is_stack )
{
if( ui_click_down( ctx, UI_MOUSE_LEFT ) )
{
- mv->main_buffer[ mv->depth+1 ] = result.target->data;
- mv->walk[ mv->depth+1 ] = result.target->name;
- mv->inspecting = NULL;
- mv->depth ++;
+ mv->route_depth ++;
+ mv->route[ mv->route_depth ] = context.highlight_id;
}
}
}
static void cb_mem_view_close( struct vg_magi_panel *me )
{
struct mem_view_data *mv = me->data;
- glDeleteTextures( 1, &mv->tex );
- free( me->data );
+ glDeleteTextures( 1, &mv->vis_tex );
+ vg_free( me->data );
}
static struct
{
const char *name;
- void **buffer;
+ vg_stack_allocator *stack;
}
_vg_mem_named_buffers[] =
{
- { "rtmemory", &vg_mem.rtmemory },
- { "scratch", &vg_mem.scratch }
+ { "rtmem", &vg.rtmem },
};
+int _CB_vg_mem_infosort( const void *a, const void *b )
+{
+ const struct mem_view_info *info_a = a,
+ *info_b = b;
+ return (i32)(info_a->buffer_size < info_b->buffer_size) - (i32)(info_a->buffer_size > info_b->buffer_size);
+}
+
static int cmd_vg_mem_view( int argc, const char *argv[] )
{
- if( argc == 1 )
+ if( argc != 1 )
{
- for( u32 i=0; i<VG_ARRAY_LEN( _vg_mem_named_buffers ); i ++ )
+ vg_error( "Usage: vg_mem_view <named_buffer>\n" );
+ return 0;
+ }
+
+ for( u32 i=0; i<VG_ARRAY_LEN( _vg_mem_named_buffers ); i ++ )
+ {
+ if( !strcmp( _vg_mem_named_buffers[i].name, argv[0] ) )
{
- if( !strcmp( _vg_mem_named_buffers[i].name, argv[0] ) )
+ struct vg_magi_panel *magi = _vg_magi_open( 512+16, 512, VG_MAGI_ALL );
+ magi->title = "Memory outliner";
+
+ struct mem_view_data *mv = vg_malloc(sizeof(struct mem_view_data));
+ mv->route[0] = 0;
+ mv->route_depth = 0;
+ mv->vis_offset = 0xffffffff;
+ mv->info_count = 1;
+
+ /* cache all allocations in full tree */
+ struct route_frame
{
- ui_px w = 512+16,
- h = 512;
- struct vg_magi_panel *magi = _vg_magi_open( w,h, VG_MAGI_ALL );
- magi->title = "Memory outliner";
-
- struct mem_view_data *mv = malloc(sizeof(struct mem_view_data));
- mv->main_buffer[0] = *_vg_mem_named_buffers[i].buffer;
- mv->walk[0] = _vg_mem_named_buffers[i].name;
- mv->depth = 0;
- mv->inspecting = NULL;
-
- glGenTextures( 1, &mv->tex );
- glBindTexture( GL_TEXTURE_2D, mv->tex );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 256,256, 0,
- GL_RED, GL_FLOAT, NULL );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-
- magi->data = mv;
- magi->ui_cb = cb_vg_mem_view;
- magi->close_cb = cb_mem_view_close;
- return 1;
+ bool init;
+ vg_stack_allocator *stack;
+ struct mem_view_info *info;
+ u32 buffer_base_offset;
+
+ u32 descend_i;
}
- }
+ route[8];
+ u32 route_depth = 0;
+
+ route[0].init = 0;
+ route[0].stack = _vg_mem_named_buffers[i].stack;
+ route[0].info = &mv->infos[ 0 ];
+ route[0].buffer_base_offset = 0;
+ route[0].descend_i = 0;
+
+ mv->infos[0].display_name = _vg_mem_named_buffers[i].name;
+ mv->infos[0].buffer_offset = 0;
+ mv->infos[0].buffer_size = _vg_mem_named_buffers[i].stack->capacity;
+ mv->infos[0].is_stack = 1;
+ mv->infos[0].stack_used_bytes = _vg_mem_named_buffers[i].stack->used;
+ mv->sizes[0] = sqrtf(mv->infos[0].buffer_size);
+
+ mv->base_buffer = _vg_mem_named_buffers[i].stack->data;
+
+ l0:{
+ struct route_frame *frame = &route[ route_depth ];
+
+ if( !frame->init )
+ {
+ frame->init = 1;
+ frame->info->stack_children_start = mv->info_count;
+ frame->info->stack_children_count = 0;
+
+ /* create array of all immediate child allocations */
+ u32 offset = frame->stack->used - frame->stack->last_allocation_totalsize;
+
+ if( (frame->stack->used == 0) || !(frame->stack->flags & VG_STACK_ALLOCATOR_METADATA) )
+ goto l1;
+
+ l2:{
+ vg_allocation_meta *meta = frame->stack->data + offset;
+
+ if( mv->info_count == VG_ARRAY_LEN(mv->infos) )
+ {
+ vg_error( "Reached maximum allocation infos! (%u)\n", mv->info_count );
+ goto e1;
+ }
+
+ struct mem_view_info *info = &mv->infos[ mv->info_count ];
+ info->display_name = meta->name;
+ info->buffer_offset = frame->buffer_base_offset + offset + sizeof(vg_allocation_meta);
+ info->buffer_size = meta->size;
+
+ mv->info_count ++;
+ frame->info->stack_children_count ++;
+
+ if( meta->flags & VG_ALLOCATION_FLAG_IS_STACK )
+ {
+ info->is_stack = 1;
+ vg_stack_allocator *substack = mv->base_buffer + info->buffer_offset;
+
+ info->stack_used_bytes = substack->used;
+ info->stack_children_start = 0; /* deferred to !frame->init */
+ info->stack_children_count = 0;
+ }
+ else
+ info->is_stack = 0;
+
+ if( offset )
+ {
+ offset = meta->previous_offset;
+ goto l2;
+ }
+ }
+ }
+
+ l1: if( frame->descend_i < frame->info->stack_children_count )
+ {
+ struct mem_view_info *info = &mv->infos[ frame->info->stack_children_start + frame->descend_i ];
+ frame->descend_i ++;
+
+ if( info->is_stack )
+ {
+ route_depth ++;
+
+ struct route_frame *next_frame = &route[ route_depth ];
+ next_frame->init = 0;
+ next_frame->stack = mv->base_buffer + info->buffer_offset;
+ next_frame->info = info;
+ next_frame->buffer_base_offset = info->buffer_offset + sizeof(vg_stack_allocator);
+ next_frame->descend_i = 0;
+
+ goto l0;
+ }
+ else goto l1;
+ }
+ else
+ {
+ /* Sort children by size, calculate sqrt f32 sizes, and step down */
+ qsort( &mv->infos[ frame->info->stack_children_start ], frame->info->stack_children_count,
+ sizeof(struct mem_view_info), _CB_vg_mem_infosort );
+
+ for( u32 i=0; i<frame->info->stack_children_count; i ++ )
+ {
+ u32 index = frame->info->stack_children_start + i;
+ struct mem_view_info *info = &mv->infos[ index ];
+ mv->sizes[ index ] = sqrtf(info->buffer_size);
+ }
+
+ if( route_depth )
+ {
+ route_depth --;
+ goto l0;
+ }
+ }
+ }
+
+ vg_success( "Cached %u allocations.\n", mv->info_count );
+
+ e1: glGenTextures( 1, &mv->vis_tex );
+ glBindTexture( GL_TEXTURE_2D, mv->vis_tex );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 256,256, 0, GL_RED, GL_FLOAT, NULL );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- vg_error( "No named buffer '%s'\n", argv[0] );
+ magi->data = mv;
+ magi->ui_cb = cb_vg_mem_view;
+ magi->close_cb = cb_mem_view_close;
+ return 1;
+ }
}
- else
- vg_error( "Usage: vg_mem_view <named_buffer>\n" );
+ vg_error( "No named buffer '%s'\n", argv[0] );
return 0;
}
#ifdef VG_3D
vg_console_reg_var( "blur_strength", &_vg_postprocess.blur_strength, k_var_dtype_f32, 0 );
vg_console_reg_var( "blur_effect", &_vg_postprocess.blur_effect, k_var_dtype_i32, VG_VAR_PERSISTENT );
-
- void *alloc = vg_mem.rtmemory;
/*
* Main framebuffer
*/
- _vg_render.fb_main = vg_framebuffer_allocate( alloc, 3, 1 );
+ _vg_render.fb_main = vg_framebuffer_allocate( &vg.rtmem, 3, 1 );
_vg_render.fb_main->display_name = "main";
_vg_render.fb_main->resolution_div = 1;
_vg_render.fb_main->attachments[0] = (vg_framebuffer_attachment)
/*
* Water reflection
*/
- _vg_render.fb_water_reflection = vg_framebuffer_allocate( alloc, 2, 1 );
+ _vg_render.fb_water_reflection = vg_framebuffer_allocate( &vg.rtmem, 2, 1 );
_vg_render.fb_water_reflection->display_name = "water_reflection";
_vg_render.fb_water_reflection->resolution_div = 2;
_vg_render.fb_water_reflection->attachments[0] = (vg_framebuffer_attachment)
* Thid rendered view from the perspective of the camera, but just
* captures stuff thats under the water
*/
- _vg_render.fb_water_beneath = vg_framebuffer_allocate( alloc, 2, 1 );
+ _vg_render.fb_water_beneath = vg_framebuffer_allocate( &vg.rtmem, 2, 1 );
_vg_render.fb_water_beneath->display_name = "water_beneath";
_vg_render.fb_water_beneath->resolution_div = 2;
_vg_render.fb_water_beneath->attachments[0] = (vg_framebuffer_attachment)
int cbMaxTicket, u32 *pcbTicket );
u64_steamid SteamAPI_ISteamUser_GetSteamID( ISteamUser *self );
-
-
-/*
- * Application symetric-key ticket method (Server)
- */
-
-enum { k_nSteamEncryptedAppTicketSymmetricKeyLen = 32 };
-
-steamapi_bool SteamEncryptedAppTicket_BDecryptTicket( u8 *rgubTicketEncrypted,
- u32 cubTicketEncrypted, u8 *rgubTicketDecrypted,
- u32 *pcubTicketDecrypted,
- u8 rgubKey[k_nSteamEncryptedAppTicketSymmetricKeyLen],
- int cubKey );
-
-steamapi_bool SteamEncryptedAppTicket_BIsTicketForApp( u8 *rgubTicketDecrypted,
- u32 cubTicketDecrypted, AppId_t nAppID );
-
-RTime32 SteamEncryptedAppTicket_GetTicketIssueTime( u8 *rgubTicketDecrypted,
- u32 cubTicketDecrypted );
-
-void SteamEncryptedAppTicket_GetTicketSteamID(
- u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, CSteamID *psteamID );
-
-AppId_t SteamEncryptedAppTicket_GetTicketAppID( u8 *rgubTicketDecrypted,
- u32 cubTicketDecrypted );
-
-steamapi_bool SteamEncryptedAppTicket_BUserOwnsAppInTicket(
- u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, AppId_t nAppID );
-
-steamapi_bool SteamEncryptedAppTicket_BUserIsVacBanned(
- u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
-
-steamapi_bool SteamEncryptedAppTicket_BGetAppDefinedValue(
- u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, u32 *pValue );
-
-u8 *SteamEncryptedAppTicket_GetUserVariableData( u8 *rgubTicketDecrypted,
- u32 cubTicketDecrypted, u32 *pcubUserData );
-
-steamapi_bool SteamEncryptedAppTicket_BIsTicketSigned( u8 *rgubTicketDecrypted,
- u32 cubTicketDecrypted, u8 *pubRSAKey, u32 cubRSAKey );
-
-steamapi_bool SteamEncryptedAppTicket_BIsLicenseBorrowed(
- u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
-
-steamapi_bool SteamEncryptedAppTicket_BIsLicenseTemporary(
- u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
-
-static inline u8 vg_char_base16( char c )
-{
- if( c >= '0' && c <= '9' )
- return c-'0';
- if( c >= 'a' && c <= 'f' )
- return (c-'a') + 10;
-
- return 0;
-}
-
-static inline int vg_load_steam_symetric_key( const char *path, u8 *buf )
-{
- vg_linear_clear( vg_mem.scratch );
- u32 size;
- char *src = vg_file_read( vg_mem.scratch, path, &size );
-
- if( src )
- {
- if( size < k_nSteamEncryptedAppTicketSymmetricKeyLen )
- {
- vg_error( "Application key was invalid size\n" );
- return 0;
- }
-
- for( int i=0; i<k_nSteamEncryptedAppTicketSymmetricKeyLen; i++ )
- {
- buf[i] = (vg_char_base16( src[i*2+0] ) << 4) |
- vg_char_base16( src[i*2+1] );
- }
-
- return 1;
- }
- else
- {
- vg_error( "Application key path was invalid\n" );
- return 0;
- }
-}
--- /dev/null
+#pragma once
+#include "vg/vg_platform.h"
+#include "vg/vg_io.h"
+#include "vg_steam.h"
+
+/*
+ * Application symetric-key ticket method (Server)
+ */
+
+enum { k_nSteamEncryptedAppTicketSymmetricKeyLen = 32 };
+
+steamapi_bool SteamEncryptedAppTicket_BDecryptTicket( u8 *rgubTicketEncrypted,
+ u32 cubTicketEncrypted, u8 *rgubTicketDecrypted,
+ u32 *pcubTicketDecrypted,
+ u8 rgubKey[k_nSteamEncryptedAppTicketSymmetricKeyLen],
+ int cubKey );
+
+steamapi_bool SteamEncryptedAppTicket_BIsTicketForApp( u8 *rgubTicketDecrypted,
+ u32 cubTicketDecrypted, AppId_t nAppID );
+
+RTime32 SteamEncryptedAppTicket_GetTicketIssueTime( u8 *rgubTicketDecrypted,
+ u32 cubTicketDecrypted );
+
+void SteamEncryptedAppTicket_GetTicketSteamID(
+ u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, CSteamID *psteamID );
+
+AppId_t SteamEncryptedAppTicket_GetTicketAppID( u8 *rgubTicketDecrypted,
+ u32 cubTicketDecrypted );
+
+steamapi_bool SteamEncryptedAppTicket_BUserOwnsAppInTicket(
+ u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, AppId_t nAppID );
+
+steamapi_bool SteamEncryptedAppTicket_BUserIsVacBanned(
+ u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
+
+steamapi_bool SteamEncryptedAppTicket_BGetAppDefinedValue(
+ u8 *rgubTicketDecrypted, u32 cubTicketDecrypted, u32 *pValue );
+
+u8 *SteamEncryptedAppTicket_GetUserVariableData( u8 *rgubTicketDecrypted,
+ u32 cubTicketDecrypted, u32 *pcubUserData );
+
+steamapi_bool SteamEncryptedAppTicket_BIsTicketSigned( u8 *rgubTicketDecrypted,
+ u32 cubTicketDecrypted, u8 *pubRSAKey, u32 cubRSAKey );
+
+steamapi_bool SteamEncryptedAppTicket_BIsLicenseBorrowed(
+ u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
+
+steamapi_bool SteamEncryptedAppTicket_BIsLicenseTemporary(
+ u8 *rgubTicketDecrypted, u32 cubTicketDecrypted );
+
+static inline u8 vg_char_base16( char c )
+{
+ if( c >= '0' && c <= '9' )
+ return c-'0';
+ if( c >= 'a' && c <= 'f' )
+ return (c-'a') + 10;
+
+ return 0;
+}
+
+static inline int vg_load_steam_symetric_key( const char *path, u8 *buf )
+{
+ vg_stack_allocator stack;
+ vg_stack_init( &stack, NULL, VG_KB(256), NULL );
+
+ u32 size;
+ char *src = vg_file_read( &stack, path, &size, 0 );
+
+ if( src )
+ {
+ if( size < k_nSteamEncryptedAppTicketSymmetricKeyLen )
+ {
+ vg_error( "Application key was invalid size\n" );
+ return 0;
+ }
+
+ for( int i=0; i<k_nSteamEncryptedAppTicketSymmetricKeyLen; i++ )
+ buf[i] = (vg_char_base16( src[i*2+0] ) << 4) | vg_char_base16( src[i*2+1] );
+
+ return 1;
+ }
+ else
+ {
+ vg_error( "Application key path was invalid\n" );
+ return 0;
+ }
+}
void vg_tex2d_load_qoi_async_file( const char *path, u32 flags, GLuint *dest )
{
THREAD_1;
- vg_linear_clear( vg_mem.scratch );
+ vg_stack_clear( &vg.scratch );
u32 size;
- const void *data = vg_file_read( vg_mem.scratch, path, &size );
+ const void *data = vg_file_read( &vg.scratch, path, &size, 0 );
vg_tex2d_load_qoi_async( data, size, flags, dest );
}
return r | (g<<8) | (b<<16) | (a<<24);
}
-static void ui_text_glyph( const struct vg_font_face *ff,
- u8 glyph, ui_rect out_texcoords )
+static void ui_text_glyph( const struct vg_font_face *ff, u8 glyph, ui_rect out_texcoords )
{
const vg_font_char *ch = &ff->map[ glyph ];
ui_rect rect, const char *str, u32 len, ui_px scale,
enum ui_align align, u32 colour )
{
+ if( str == NULL )
+ str = "NULL";
+
ui_px glow_text = 0;
ui_rect text_cursor;
return printed_chars;
}
-u32 ui_text( ui_context *ctx,
- ui_rect rect, const char *str, ui_px scale,
- enum ui_align align, u32 colour )
+u32 ui_text( ui_context *ctx, ui_rect rect, const char *str, ui_px scale, enum ui_align align, u32 colour )
{
return ui_ntext( ctx, rect, str, 1024, scale, align, colour );
}
if( names[i] )
{
- ui_text( ctx, swatch, names[i], 1,
- k_ui_align_middle_left, ui_colourcont(ctx,i));
+ ui_text( ctx, swatch, names[i], 1, k_ui_align_middle_left, ui_colourcont(ctx,i));
}
}
}
void *resource;
};
+struct ui_batch_shader_data_image_gradient
+{
+ void *resource;
+ bool log;
+ f32 scale;
+};
+
struct ui_batch
{
ui_vert *vert_buf; /* base vertex array + [vert_offset] */
.static_src =
"uniform sampler2D uTexImage;"
"uniform vec4 uColour;"
+ "uniform int uLog;"
+ "uniform float uScale;"
+
"out vec4 FragColor;"
"in vec2 aTexCoords;"
"void main()"
"{"
"vec4 colour = texture( uTexImage, aTexCoords );"
- "FragColor = vec4(vec3(colour.r)*uColour.rgb,1.0);"
+ "float v = colour.r;"
+ "if( uLog == 1 ){"
+ "v = log(v);"
+ "}"
+ "v *= uScale;"
+ "FragColor = vec4(vec3(v)*uColour.rgb,1.0);"
"}"
}
};
else if( shader == k_ui_shader_grad )
{
glUseProgram( _shader_ui_image_grad.id );
- glUniformMatrix3fv(
- glGetUniformLocation( _shader_ui_image_grad.id, "uPv" ), 1,
- GL_FALSE, (float *)vg_ui.pv );
- glUniform1i(
- glGetUniformLocation(_shader_ui_image_grad.id,"uTexImage"), 0 );
- glUniform4fv( glGetUniformLocation( _shader_ui_image.id, "uColour" ), 1,
- vg_ui.colour );
+ glUniformMatrix3fv( glGetUniformLocation( _shader_ui_image_grad.id, "uPv" ), 1, GL_FALSE, (float *)vg_ui.pv );
+ glUniform1i( glGetUniformLocation(_shader_ui_image_grad.id,"uTexImage"), 0 );
+ glUniform4fv( glGetUniformLocation( _shader_ui_image.id, "uColour" ), 1, vg_ui.colour );
+
+ struct ui_batch_shader_data_image_gradient *inf = shader_data;
+ glUniform1i( glGetUniformLocation(_shader_ui_image_grad.id,"uLog"), inf->log );
+ glUniform1f( glGetUniformLocation(_shader_ui_image_grad.id,"uScale"), inf->scale );
- struct ui_batch_shader_data_image *inf = shader_data;
GLuint *image = inf->resource;
glActiveTexture( GL_TEXTURE0 );
{
struct ui_batch_shader_data_hsv *inf = shader_data;
glUseProgram( _shader_ui_hsv.id );
- glUniformMatrix3fv( glGetUniformLocation( _shader_ui_hsv.id, "uPv" ), 1,
- GL_FALSE, (float *)vg_ui.pv );
+ glUniformMatrix3fv( glGetUniformLocation( _shader_ui_hsv.id, "uPv" ), 1, GL_FALSE, (float *)vg_ui.pv );
glUniform1f( glGetUniformLocation(_shader_ui_hsv.id,"uHue"), inf->hue );
}
else
total = sheet->w*sheet->h,
data = 0;
- vg_linear_clear( vg_mem.scratch );
- u8 *image = vg_linear_alloc( vg_mem.scratch, total );
+ vg_stack_clear( &vg.scratch );
+ u8 *image = vg_stack_allocate( &vg.scratch, total, 8, NULL );
while( pixels < total )
{