From 0ab3fe912f415b666ed22e9e20bf4f3f2befd989 Mon Sep 17 00:00:00 2001 From: hgn Date: Thu, 27 Oct 2022 16:36:55 +0100 Subject: [PATCH] heisenbug --- src/vg/vg_audio.h | 42 +++-- src/vg/vg_lines.h | 2 +- src/vg/vg_loader.h | 3 + src/vg/vg_mem.h | 400 ++++++++++++++++++++++++++++++++++++++++++++- src/vg/vg_stdint.h | 8 +- src/vg/vg_ui.h | 7 +- 6 files changed, 439 insertions(+), 23 deletions(-) diff --git a/src/vg/vg_audio.h b/src/vg/vg_audio.h index 5b8def2..0b4fc3e 100644 --- a/src/vg/vg_audio.h +++ b/src/vg/vg_audio.h @@ -72,8 +72,8 @@ struct audio_clip const char *path; enum audio_source_mode source_mode; - void *data; u32 size; + void *data; }; typedef struct audio_mix_info audio_mix_info; @@ -232,7 +232,8 @@ VG_STATIC void vg_audio_init(void) /* 32mb fixed */ vg_audio.audio_pool = - vg_create_linear_allocator( vg_mem.rtmemory, 1024*1024*32 ); + vg_create_linear_allocator( vg_mem.rtmemory, 1024*1024*32, + VG_MEMORY_SYSTEM ); /* fixed */ u32 decode_size = AUDIO_DECODE_SIZE * SFX_MAX_SYSTEMS; @@ -519,8 +520,8 @@ VG_STATIC void audio_decode_uncompressed_mono( i16 *src, u32 count, float *dst ) { for( u32 i=0; ichannels - 1 ); @@ -621,7 +621,9 @@ VG_STATIC void audio_entity_get_samples( aatree_ptr id, u32 count, float *buf ) if( source_mode == k_audio_source_mono ) { - i16 *src = &((i16 *)ent->info.source->data)[ cursor ]; + i16 *src_buffer = ent->info.source->data, + *src = &src_buffer[cursor]; + audio_decode_uncompressed_mono( src, samples_this_run, dst ); } else if( source_mode == k_audio_source_compressed ) @@ -668,7 +670,7 @@ VG_STATIC void audio_entity_get_samples( aatree_ptr id, u32 count, float *buf ) } VG_STATIC void audio_entity_mix( aatree_ptr id, float *buffer, - u32 frame_count ) + u32 frame_count ) { audio_entity *ent = &vg_audio.active_players[id].ent; @@ -769,13 +771,14 @@ VG_STATIC void audio_clip_load( audio_clip *clip ) { vg_linear_clear( vg_mem.scratch ); u32 fsize; - void *filedata = vg_file_read( vg_mem.scratch, clip->path, &fsize ); stb_vorbis_alloc alloc = { .alloc_buffer = vg_linear_alloc( vg_mem.scratch, AUDIO_DECODE_SIZE ), .alloc_buffer_length_in_bytes = AUDIO_DECODE_SIZE }; + void *filedata = vg_file_read( vg_mem.scratch, clip->path, &fsize ); + int err; stb_vorbis *decoder = stb_vorbis_open_memory( filedata, fsize, &err, &alloc ); @@ -791,20 +794,28 @@ VG_STATIC void audio_clip_load( audio_clip *clip ) u32 length_samples = stb_vorbis_stream_length_in_samples( decoder ), data_size = length_samples * sizeof(i16); + audio_lock(); clip->data = vg_linear_alloc( vg_audio.audio_pool, data_size ); clip->size = length_samples; + audio_unlock(); - int read_samples = stb_vorbis_get_samples_i16_interleaved_mono( + int read_samples = stb_vorbis_get_samples_i16_downmixed( decoder, clip->data, length_samples ); + if( read_samples != length_samples ) + vg_fatal_exit_loop( "Decode error" ); + float mb = (float)(data_size) / (1024.0f*1024.0f); - vg_info( "Loaded audio clip '%s' (%.1fmb)\n", clip->path, mb ); + vg_info( "Loaded audio clip '%s' (%.1fmb) %u samples\n", clip->path, mb, + length_samples ); } /* load in directly */ else if( clip->source_mode == k_audio_source_compressed ) { + audio_lock(); clip->data = vg_file_read( vg_audio.audio_pool, clip->path, &clip->size ); + audio_unlock(); if( !clip->data ) vg_fatal_exit_loop( "Audio failed to load" ); @@ -833,7 +844,7 @@ VG_STATIC void audio_player_commit( audio_player *sys ) if( sys->enqued ) { - vg_warn( "Audio commit spamming; already enqued (%s)\n", sys->name ); + vg_warn( "[2] Audio commit spamming; already enqued (%s)\n", sys->name ); return; } @@ -873,6 +884,13 @@ VG_STATIC void audio_player_playclip( audio_player *player, audio_clip *clip ) return; } + if( player->enqued ) + { + vg_warn( "[1] Audio commit spamming; already enqued (%s)\n", + player->name ); + return; + } + player->info.source = clip; audio_player_commit( player ); } diff --git a/src/vg/vg_lines.h b/src/vg/vg_lines.h index 58e0e14..c0da5b3 100644 --- a/src/vg/vg_lines.h +++ b/src/vg/vg_lines.h @@ -85,7 +85,7 @@ VG_STATIC void vg_lines_init(void) u32 size = 50000 * sizeof( struct vg_lines_vert ); vg_lines.vertex_buffer = - vg_create_linear_allocator( vg_mem.rtmemory, size ); + vg_create_linear_allocator(vg_mem.rtmemory, size, VG_MEMORY_REALTIME); glBufferData( GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW ); glBindVertexArray( vg_lines.vao ); diff --git a/src/vg/vg_loader.h b/src/vg/vg_loader.h index 23d35b9..72e4c3c 100644 --- a/src/vg/vg_loader.h +++ b/src/vg/vg_loader.h @@ -116,6 +116,7 @@ VG_STATIC float hue_to_rgb( float p, float q, float t ) VG_STATIC void vg_render_log(void) { ui_begin( vg.window_x, vg.window_y ); + vg_mutex_lock( &log_print_mutex ); int const fh = 14; int lines_screen_max = ((vg.window_y/fh)-2), @@ -140,6 +141,8 @@ VG_STATIC void vg_render_log(void) vg_uictx.cursor[1] -= fh; } + vg_mutex_unlock( &log_print_mutex ); + ui_resolve(); ui_draw( NULL ); } diff --git a/src/vg/vg_mem.h b/src/vg/vg_mem.h index 4f293c2..a5d1832 100644 --- a/src/vg/vg_mem.h +++ b/src/vg/vg_mem.h @@ -7,6 +7,378 @@ #include #include +#define VG_MAX_ALLOCATIONS 64 +#define VG_FUZZ_ALLOCATIONS +#define VG_DEBUG_ALLOCATIONS + +typedef struct vg_linear_allocator vg_linear_allocator; +typedef struct vg_allocation_meta vg_allocation_meta; + +struct +{ + void *rtmemory, + *scratch; + + int use_libc_malloc; +} +static vg_mem; + +struct vg_allocation_meta +{ + void *data; + enum allocation_type + { + k_allocation_type_block = 0, + k_allocation_type_linear = 1 + } + type; +}; + +#define VG_MEMORY_SYSTEM 0x1 /* systems memory, slow and low counts */ +#define VG_MEMORY_REALTIME 0x2 /* per-frame. no max allocs, only size. fast */ + +/* systems memory cannot be declared inside realtime memory regions */ + +/* + * Stored just behind the array. 32 bytes. + */ +#pragma pack(push,1) +struct vg_linear_allocator +{ + u32 size; + /* */ + /* */ + /* */ + u32 cur; + /* */ + /* */ + /* */ + u16 allocation_count; + /* */ + u16 flags; + /* */ + u32 last_alloc_size; + /* */ + /* */ + /* */ + void *last_alloc; + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + vg_allocation_meta *alloc_table; + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ + /* */ +}; +#pragma pack(pop) + +VG_STATIC void vg_error(const char *fmt, ...); +VG_STATIC void vg_info(const char *fmt, ...); + +/* Returns allocator structure from data pointer */ +static vg_linear_allocator *vg_linear_header( void *data ) +{ + vg_linear_allocator *ptr = data; + ptr --; + + return ptr; +} + +/* allocate something from a linear allocator */ +__attribute__((warn_unused_result)) +VG_STATIC void *vg_linear_alloc( void *buffer, u32 size ) +{ + vg_linear_allocator *alloc = vg_linear_header( buffer ); + + if( (alloc->cur + size) > alloc->size ) + { + vg_error( "%u + %u > %u\n", alloc->cur, size, alloc->size ); + vg_fatal_exit_loop( "linear allocator overflow" ); + } + + if( alloc->flags & VG_MEMORY_SYSTEM ) + if( (alloc->allocation_count + 1) > VG_MAX_ALLOCATIONS ) + vg_fatal_exit_loop( "Max linear allocations reached" ); + + void *data; + + if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ) + { + data = malloc( size ); + +#ifdef VG_DEBUG_ALLOCATIONS + vg_info( "malloc: %p[%u]\n", data, size ); +#endif + + vg_allocation_meta *meta = &alloc->alloc_table[ alloc->allocation_count ]; + meta->type = k_allocation_type_block; + meta->data = data; + } + else + { + data = buffer + alloc->cur; + } + + alloc->allocation_count ++; + alloc->last_alloc = data; + alloc->last_alloc_size = size; + alloc->cur += size; + + return data; +} + + +/* resize latest block of memory from linear */ +__attribute__((warn_unused_result)) +VG_STATIC void *vg_linear_resize( void *buffer, void *data, u32 newsize ) +{ + vg_linear_allocator *alloc = vg_linear_header( buffer ); + + if( alloc->last_alloc != data ) + vg_fatal_exit_loop( "This block has been fixed!" ); + + if( (alloc->cur - alloc->last_alloc_size + newsize) > alloc->size ) + vg_fatal_exit_loop( "Cannot resize, overflow" ); + + 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) ) + { + data = realloc( data, newsize ); + if( !data ) + vg_fatal_exit_loop( "realloc failed" ); + + alloc->alloc_table[ alloc->allocation_count-1 ].data = data; + alloc->last_alloc = data; + +#ifdef VG_DEBUG_ALLOCATIONS + vg_info( "realloc: %p (->%u)\n", data, newsize ); +#endif + return data; + } + else + { + return data; + } +} + +/* its possible to delete just the last item */ +VG_STATIC void vg_linear_del( void *buffer, void *data ) +{ + vg_linear_allocator *alloc = vg_linear_header( buffer ); + + if( alloc->last_alloc != data ) + vg_fatal_exit_loop( "This block has been fixed!" ); + + if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ) + { + vg_allocation_meta *meta = &alloc->alloc_table[alloc->allocation_count-1]; + if( meta->type == k_allocation_type_linear ) + vg_fatal_exit_loop( "Cannot free a linear allocator in this conext" ); + + free( data ); + } + + alloc->allocation_count --; + alloc->cur -= alloc->last_alloc_size; + alloc->last_alloc = NULL; + alloc->last_alloc_size = 0; +} + +/* extend latest block of memory from linear */ +__attribute__((warn_unused_result)) +VG_STATIC void *vg_linear_extend( void *buffer, void *data, u32 extra ) +{ + vg_linear_allocator *alloc = vg_linear_header( buffer ); + + if( alloc->last_alloc != data ) + vg_fatal_exit_loop( "This block has been fixed!" ); + + u32 new_size = alloc->last_alloc_size + extra; + return vg_linear_resize( buffer, data, new_size ); +} + +/* get the current usage of allocator */ +VG_STATIC u32 vg_linear_get_cur( void *buffer ) +{ + vg_linear_allocator *alloc = vg_linear_header( buffer ); + return alloc->cur; +} + +/* get the capacity of allocator. TODO, should return free space? */ +VG_STATIC u32 vg_linear_get_capacity( void *buffer ) +{ + vg_linear_allocator *alloc = vg_linear_header( buffer ); + return alloc->size; +} + +/* yeet all memory from linear allocator */ +VG_STATIC void vg_linear_clear( void *buffer ) +{ + vg_linear_allocator *alloc = vg_linear_header( buffer ); + +#ifdef VG_DEBUG_ALLOCATIONS + if( alloc->flags & VG_MEMORY_SYSTEM ) + vg_info( "linear_clear on %p\n", alloc ); +#endif + + /* libc mode we recursively free any allocations made */ + if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ) + { + for( u32 i=0; iallocation_count; i++ ) + { + vg_allocation_meta *meta = &alloc->alloc_table[i]; + + if( meta->type == k_allocation_type_block ) + { + free( meta->data ); + +#ifdef VG_DEBUG_ALLOCATIONS + vg_info( "free(%p) [%d]\n", meta->data, meta->type ); +#endif + } + else + { + vg_linear_clear( meta->data ); + vg_linear_allocator *sub = vg_linear_header( meta->data ); + +#ifdef VG_DEBUG_ALLOCATIONS + vg_info( "free(%p) [alloc_table]\n", sub->alloc_table ); + vg_info( "free(%p) [%d]\n", sub, meta->type ); +#endif + + free( sub->alloc_table ); + free( sub ); + } + } + } + + alloc->last_alloc = NULL; + alloc->last_alloc_size = 0; + alloc->allocation_count = 0; + alloc->cur = 0; +} + +/* allocate a FIXED SIZE linear allocator */ +VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size, + u16 flags ) +{ + assert( sizeof( vg_linear_allocator ) == 32 ); + + vg_linear_allocator *header; + u32 block_size = size + sizeof(vg_linear_allocator); + + /* Creating it inside an existing one */ + if( lin_alloc ) + { + vg_linear_allocator *alloc = vg_linear_header( lin_alloc ); + + if( alloc->cur + block_size > alloc->size ) + vg_fatal_exit_loop( "Out of memory" ); + + if( alloc->allocation_count + 1 > VG_MAX_ALLOCATIONS ) + vg_fatal_exit_loop( "Max allocations in linear allocator" ); + + if( (flags && VG_MEMORY_SYSTEM) && (alloc->flags & VG_MEMORY_REALTIME) ) + vg_fatal_exit_loop( "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) ); + +#ifdef VG_DEBUG_ALLOCATIONS + vg_info( "linear_create(sub) malloc(%p)\n", header ); +#endif + + meta->data = header+1; + meta->type = k_allocation_type_linear; + } + else + { + header = lin_alloc + alloc->cur; + } + + alloc->cur += block_size; + alloc->last_alloc = NULL; /* cant resize this block! */ + 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 ); + +#ifdef VG_DEBUG_ALLOCATIONS + vg_info( "linear_create malloc(%p)\n", header ); +#endif + } + + 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 ); +#ifdef VG_DEBUG_ALLOCATIONS + vg_info( "linear_create(%p) [alloc_table]\n", header->alloc_table ); +#endif + } + else + header->alloc_table = NULL; + + return header+1; +} + +/* request all the memory we need in advance */ +VG_STATIC void vg_prealloc_quota( u32 size ) +{ + u32 size_scratch = 10*1024*1024; + size = VG_MAX( size, size_scratch ); + + vg_mem.rtmemory = vg_create_linear_allocator( NULL, size, VG_MEMORY_SYSTEM ); + vg_mem.scratch = vg_create_linear_allocator( vg_mem.rtmemory, + size_scratch, + VG_MEMORY_SYSTEM ); +} + +#endif /* VG_MEM_H */ + +#if 0 + +#ifndef VG_MEM_H +#define VG_MEM_H + +#include "vg_stdint.h" +#include "vg_platform.h" + +#include +#include + typedef struct vg_linear_allocator vg_linear_allocator; struct @@ -29,6 +401,8 @@ struct vg_linear_allocator * TODO: Fallback on libc */ +//#define VG_USE_MALLOC + VG_STATIC void vg_error(const char *fmt, ...); /* allocate something from a linear allocator */ @@ -53,10 +427,15 @@ VG_STATIC void *vg_linear_alloc( void *allocator, u32 size ) vg_fatal_exit_loop( "Linear allocator out of memory" ); } +#ifdef VG_USE_MALLOC + void *data = malloc(size); +#else void *data = allocator + allocptr->cur; +#endif + allocptr->cur += size; - allocptr->last_alloc = data; allocptr->last_alloc_size = size; + allocptr->last_alloc = data; return data; } @@ -71,10 +450,21 @@ VG_STATIC void *vg_linear_resize( void *allocator, void *data, u32 newsize ) if( allocptr->last_alloc == data ) { allocptr->cur -= allocptr->last_alloc_size; + +#ifdef VG_USE_MALLOC + allocptr->cur += newsize; + void *newdata = realloc( data, newsize ); + allocptr->last_alloc = newdata; + allocptr->last_alloc_size = newsize; + + return newdata; +#else return vg_linear_alloc( allocator, newsize ); +#endif } else { + vg_error( "%p != %p\n", allocptr->last_alloc, data ); vg_fatal_exit_loop( "Cannot resize this buffer anymore" ); } @@ -83,7 +473,11 @@ VG_STATIC void *vg_linear_resize( void *allocator, void *data, u32 newsize ) VG_STATIC void vg_linear_del( void *allocator, void *data ) { +#ifdef VG_USE_MALLOC + free(data); +#else void *ignore = vg_linear_resize( allocator, data, 0 ); +#endif vg_linear_allocator *allocptr = allocator; allocptr --; @@ -120,6 +514,7 @@ VG_STATIC u32 vg_linear_get_capacity( void *allocator ) return allocptr->size; } +#if 0 /* get the size of the last allocated thing */ VG_STATIC u32 vg_linear_last_size( void *allocator ) { @@ -128,6 +523,7 @@ VG_STATIC u32 vg_linear_last_size( void *allocator ) return allocptr->last_alloc_size; } +#endif /* yeet all memory from linear allocator */ VG_STATIC void vg_linear_clear( void *allocator ) @@ -187,3 +583,5 @@ VG_STATIC void vg_prealloc_quota( u32 size ) } #endif /* VG_MEM_H */ + +#endif diff --git a/src/vg/vg_stdint.h b/src/vg/vg_stdint.h index 7f9928a..fb1a62d 100644 --- a/src/vg/vg_stdint.h +++ b/src/vg/vg_stdint.h @@ -7,9 +7,9 @@ typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef int64_t i64; +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; #endif /* VG_STDINT_H */ diff --git a/src/vg/vg_ui.h b/src/vg/vg_ui.h index 0dc4eba..6c970af 100644 --- a/src/vg/vg_ui.h +++ b/src/vg/vg_ui.h @@ -227,11 +227,8 @@ VG_STATIC void ui_init_context(void) u32 vert_size = vertex_buffer_size*sizeof(struct ui_vert), inds_size = index_buffer_size *sizeof(u16); - vg_uictx.vertex_buffer = - vg_create_linear_allocator(vg_mem.rtmemory,vert_size); - - vg_uictx.indice_buffer = - vg_create_linear_allocator(vg_mem.rtmemory,inds_size); + vg_uictx.vertex_buffer = vg_linear_alloc( vg_mem.rtmemory, vert_size ); + vg_uictx.indice_buffer = vg_linear_alloc( vg_mem.rtmemory, inds_size ); /* font * ----------------------------------------------------- -- 2.25.1