heisenbug
authorhgn <hgodden00@gmail.com>
Thu, 27 Oct 2022 15:36:55 +0000 (16:36 +0100)
committerhgn <hgodden00@gmail.com>
Thu, 27 Oct 2022 15:36:55 +0000 (16:36 +0100)
src/vg/vg_audio.h
src/vg/vg_lines.h
src/vg/vg_loader.h
src/vg/vg_mem.h
src/vg/vg_stdint.h
src/vg/vg_ui.h

index 5b8def23ae2634f1939caa4023ea70b618853df2..0b4fc3ea87264e22b1a3980f0e714c7fadce92d0 100644 (file)
@@ -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; i<count; i++ )
    {
-      dst[ i*2 + 0 ] = (float)src[i] * (1.0f/32767.0f);
-      dst[ i*2 + 1 ] = (float)src[i] * (1.0f/32767.0f);
+      dst[ i*2 + 0 ] = ((float)src[i]) * (1.0f/32767.0f);
+      dst[ i*2 + 1 ] = ((float)src[i]) * (1.0f/32767.0f);
    }
 }
 
@@ -564,8 +565,7 @@ stb_vorbis_get_samples_float_interleaved_stereo( stb_vorbis *f, float *buffer,
  * ........ more wrecked code sorry!
  */
 VG_STATIC int 
-stb_vorbis_get_samples_i16_interleaved_mono( stb_vorbis *f, i16 *buffer, 
-                                             int len )
+stb_vorbis_get_samples_i16_downmixed( stb_vorbis *f, i16 *buffer, int len )
 {
    int n = 0,
        c = VG_MIN( 1, f->channels - 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 );
 }
index 58e0e142d84f20e937d4cbc6e0ce8f6365404ec4..c0da5b308dd3d313da4b6bb4eeb8912bbb873d35 100644 (file)
@@ -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 );
index 23d35b9a455fec7a4806c29e7ca043ffb3fc74a7..72e4c3cad37fe8fb24309669df887197fb8ae0bd 100644 (file)
@@ -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 );
 }
index 4f293c2190b99f9f433bf8feb977a339fade0538..a5d183235ec4ee555436fba9cafb4ba3c2b5d816 100644 (file)
@@ -7,6 +7,378 @@
 #include <stdlib.h>
 #include <malloc.h>
 
+#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; i<alloc->allocation_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 <stdlib.h>
+#include <malloc.h>
+
 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
index 7f9928ade0c9106dd366f6534d53c42bfe733f51..fb1a62dde270f12d53a39e8f53a27bf4e4f56dfa 100644 (file)
@@ -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 */
index 0dc4eba33c3fb3eecfa605ad7f3a67fba1692e26..6c970aff29698fbabbfeed343a8395c11081aecc 100644 (file)
@@ -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
     * -----------------------------------------------------