stuff
authorhgn <hgodden00@gmail.com>
Tue, 15 Apr 2025 20:42:26 +0000 (21:42 +0100)
committerhgn <hgodden00@gmail.com>
Tue, 15 Apr 2025 20:42:26 +0000 (21:42 +0100)
20 files changed:
vg_async.c [deleted file]
vg_async.h [deleted file]
vg_async2.c
vg_async2.h
vg_audio_dsp.c
vg_build.h
vg_engine.c
vg_engine.h
vg_framebuffer.c
vg_input.c
vg_input.h
vg_lines.c
vg_loader.c
vg_loader.h
vg_mutex.h [new file with mode: 0644]
vg_render.c
vg_rigidbody_view.c
vg_shader.c
vg_shader.h
vg_tex.c

diff --git a/vg_async.c b/vg_async.c
deleted file mode 100644 (file)
index c071641..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-#include "vg_async.h"
-
-struct vg_async vg_async;
-
-u32 vg_thread_purpose(void);
-
-vg_async_item *vg_async_alloc( u32 size )
-{
-   /* ditch out here if engine crashed. this serves as the 'quit checking' */
-   if( SDL_AtomicGet( &vg.engine_status ) == k_engine_status_crashed )
-      longjmp( vg.env_loader_exit, 1 );
-
-   SDL_LockMutex( vg_async.lock );
-
-   u32 total_allocation = vg_align8(size) + vg_align8(sizeof(vg_async_item)),
-       remaining        = vg_linear_remaining( vg_async.buffer ),
-       capacity         = vg_linear_get_capacity( vg_async.buffer );
-
-   if( total_allocation > capacity )
-   {
-      SDL_UnlockMutex( vg_async.lock );
-      vg_fatal_condition();
-      vg_info( "async alloc invalid size\n" );
-      vg_info( "Requested: %umb. Buffer size: %umb\n",
-                  (total_allocation/1024)/1024,
-                  (capacity/1024)/1024 );
-      vg_fatal_exit();
-   }
-
-   if( total_allocation > remaining )
-   {
-      SDL_UnlockMutex( vg_async.lock );
-      SDL_SemWait( vg_async.sem_wait_for_flush );
-      SDL_LockMutex( vg_async.lock );
-
-      remaining = vg_linear_remaining( vg_async.buffer );
-      capacity = vg_linear_get_capacity( vg_async.buffer );
-   }
-
-   void *block = vg_linear_alloc( vg_async.buffer, total_allocation );
-
-   vg_async_item *entry = block;
-   entry->next = NULL;
-
-   if( size ) entry->payload = ((u8*)block) + vg_align8(sizeof(vg_async_item)); 
-   else entry->payload = NULL;
-
-   entry->size = size;
-   entry->fn_runner = NULL;
-
-   if( vg_async.end ){
-      vg_async.end->next = entry;
-      vg_async.end = entry;
-   }else{
-      vg_async.start = entry;
-      vg_async.end = entry;
-   }
-
-   SDL_UnlockMutex( vg_async.lock );
-
-   return entry;
-}
-
-/*
- * Wait until the current stack of async calls is completely flushed out 
- */
-void vg_async_stall(void)
-{
-   VG_ASSERT( vg_thread_purpose() == k_thread_purpose_loader );
-   SDL_SemWait( vg_async.sem_wait_for_flush );
-}
-
-void vg_async_dispatch( vg_async_item *item, 
-                        void (*runner)( void *payload, u32 size ) )
-{
-   VG_ASSERT( vg_thread_purpose() == k_thread_purpose_loader );
-   if( SDL_SemValue(vg_async.sem_wait_for_flush) )
-      SDL_SemWait(vg_async.sem_wait_for_flush);
-
-   SDL_LockMutex( vg_async.lock );
-   item->fn_runner = runner;
-   SDL_UnlockMutex( vg_async.lock );
-}
-
-void vg_async_call( void (*runner)( void *payload, u32 size ), 
-                    void *payload, u32 size )
-{
-   VG_ASSERT( vg_thread_purpose() == k_thread_purpose_loader );
-   vg_async_item *call = vg_async_alloc(0);
-   call->payload = payload;
-   call->size = size;
-   vg_async_dispatch( call, runner );
-}
-
-void vg_run_async_checked(void)
-{
-   SDL_LockMutex( vg_async.lock );
-
-   while( vg_async.start )
-   {
-      vg_async_item *entry = vg_async.start;
-
-      if( entry->fn_runner )
-      {
-         entry->fn_runner( entry->payload, entry->size );
-         vg_async.start = entry->next;
-
-         if( vg_async.start == NULL )
-         {
-            vg_async.end = NULL;
-
-            vg_linear_clear( vg_async.buffer );
-
-            if( !SDL_SemValue( vg_async.sem_wait_for_flush ) )
-            {
-               SDL_SemPost( vg_async.sem_wait_for_flush );
-            }
-         }
-      }
-      else
-      {
-         SDL_UnlockMutex( vg_async.lock );
-         return;
-      }
-   }
-
-   if( !SDL_SemValue( vg_async.sem_wait_for_flush ) )
-   {
-      SDL_SemPost( vg_async.sem_wait_for_flush );
-   }
-
-   SDL_UnlockMutex( vg_async.lock );
-}
-
-void vg_async_init(void)
-{
-   vg_async.lock = SDL_CreateMutex();
-   VG_ASSERT( vg_async.lock );
-
-   vg_async.sem_wait_for_flush = SDL_CreateSemaphore(0);
-   VG_ASSERT( vg_async.sem_wait_for_flush );
-
-   vg_async.buffer = vg_create_linear_allocator( NULL, 50*1024*1024, VG_MEMORY_SYSTEM );
-}
diff --git a/vg_async.h b/vg_async.h
deleted file mode 100644 (file)
index d20cccf..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (C) 2021-2025 Harry Godden (hgn) - All Rights Reserved 
- *
- * primateves that you use when you need to run something from another thread 
- * back in the main loop of vg, at the start of each frame
- *
- * TODO: Replace this with async2 in the future.
- */
-
-#pragma once
-#include "vg_engine.h"
-
-static void vg_assert_thread( u32 required );
-
-typedef struct vg_async_item vg_async_item;
-struct vg_async_item
-{
-   vg_async_item *next;
-
-   void *payload;
-   u32 size;
-
-   void (*fn_runner)( void *payload, u32 size );
-};
-
-struct vg_async
-{
-   void *buffer;
-   
-   vg_async_item *start, *end;
-
-   SDL_sem *sem_wait_for_flush;
-   SDL_mutex *lock;
-}
-extern vg_async;
-
-void vg_async_init(void);
-
-/*
- * Make a simple async call without allocating extra.
- */
-void vg_async_call( void (*runner)( void *payload, u32 size ), void *payload, u32 size );
-
-/*
- * Run as much of the async buffer as possible
- */
-void vg_run_async_checked(void);
-
-/*
- * Allocate an asynchronous call with a bit of memory
- */
-vg_async_item *vg_async_alloc( u32 size );
-
-/*
- * Mark the call as being filled and ready to go
- */
-void vg_async_dispatch( vg_async_item *item, void (*runner)( void *payload, u32 size ) );
-
-/*
- * Wait until the current stack of async calls is completely flushed out 
- */
-void vg_async_stall(void);
index 925166ccb9cc73fc951abdd875025da6c28c7010..926cce6ea6b155b88e919f4cc88a3a4da23543d2 100644 (file)
@@ -2,16 +2,16 @@
 
 bool vg_init_async_queue( vg_async_queue *queue )
 {
-   if( pthread_mutex_init( &queue->lock, NULL ) )
+   if( !VG_MUTEX_INIT( queue->lock ) )
       goto e0;
 
-   if( pthread_mutex_init( &queue->data_lock, NULL ) )
+   if( !VG_MUTEX_INIT( queue->data_lock ) )
       goto e1;
 
-   if( sem_init( &queue->blocking_memory_signal, 0, 0 ) )
+   if( !VG_SEMAPHORE_INIT( queue->blocking_signal, 0 ) )
       goto e2;
 
-   if( sem_init( &queue->work_semaphore, 0, 0 ) )
+   if( !VG_SEMAPHORE_INIT( queue->work_semaphore, 0 ) )
       goto e3;
 
    queue->queue.buffer = malloc( queue->buffer_size );
@@ -20,100 +20,132 @@ bool vg_init_async_queue( vg_async_queue *queue )
       goto e2;
 
    return 1;
-e3: sem_destroy( &queue->blocking_memory_signal );
-e2: pthread_mutex_destroy( &queue->data_lock );
-e1: pthread_mutex_destroy( &queue->lock );
+e3: VG_SEMAPHORE_FREE( queue->blocking_signal );
+e2: VG_MUTEX_FREE( queue->data_lock );
+e1: VG_MUTEX_FREE( queue->lock );
 e0: return 0;
 }
 
 void vg_free_async_queue( vg_async_queue *queue )
 {
-   pthread_mutex_destroy( &queue->data_lock );
-   pthread_mutex_destroy( &queue->lock );
-   sem_destroy( &queue->blocking_memory_signal );
+   VG_MUTEX_FREE( queue->data_lock );
+   VG_MUTEX_FREE( queue->lock );
+   VG_SEMAPHORE_FREE( queue->work_semaphore );
+   VG_SEMAPHORE_FREE( queue->blocking_signal );
 }
 
-vg_async_task *vg_allocate_async_task( vg_async_queue *queue, u32 bytes, bool blocking )
+vg_async_task *_vg_allocate_async_task( vg_async_queue *queue, u32 bytes, bool blocking, const char *debug_info )
 {
    VG_ASSERT( bytes <= queue->queue.size );
    u32 total_size = sizeof(vg_async_task) + bytes;
-   pthread_mutex_lock( &queue->data_lock );
-   pthread_mutex_lock( &queue->lock );
+   VG_MUTEX_LOCK( queue->data_lock );
+   if( queue->allocating_task )
+   {
+      vg_fatal_error( "Overlapping async allocations. \n"
+                      "  Previous allocation began at: %s\n" 
+                      "  Overlapping call at: %s\n", queue->allocating_task->alloc_debug_info, debug_info );
+   }
+   VG_MUTEX_LOCK( queue->lock );
    vg_queue *ring = &queue->queue;
    vg_async_task *task = vg_queue_alloc( ring, total_size, NULL );
 
    while( blocking && !task )
    {
-      pthread_mutex_unlock( &queue->lock );
-      sem_wait( &queue->blocking_memory_signal );
-      pthread_mutex_lock( &queue->lock );
+      VG_MUTEX_UNLOCK( queue->lock );
+      VG_SEMAPHORE_WAIT( queue->blocking_signal );
+      VG_MUTEX_LOCK( queue->lock );
       task = vg_queue_alloc( ring, total_size, NULL );
    }
 
    if( task )
+   {
       task->handler = NULL;
+      task->queue = queue;
+      task->alloc_debug_info = debug_info;
+      queue->allocating_task = task;
+   }
 
-   pthread_mutex_unlock( &queue->lock );
+   VG_MUTEX_UNLOCK( queue->lock );
    return task;
 }
 
-void vg_async_task_dispatch( vg_async_queue *queue, vg_async_task *task, void (*handler)( vg_async_task *task ) )
+void _vg_async_task_dispatch( vg_async_task *task, void (*handler)( vg_async_task *task ), const char *debug_info )
 {
-   pthread_mutex_unlock( &queue->data_lock );
-
+   task->queue->allocating_task = NULL;
+   VG_MUTEX_UNLOCK( task->queue->data_lock );
    task->handler = handler;
-   sem_post( &queue->work_semaphore );
+   task->alloc_debug_info = debug_info;
+   VG_SEMAPHORE_POST( task->queue->work_semaphore );
 }
 
 bool vg_async_has_work( vg_async_queue *queue )
 {
-   int work_count = 0;
-   sem_getvalue( &queue->work_semaphore, &work_count );
-   return work_count > 0? 1: 0;
+   return VG_SEMAPHORE_VALUE( queue->work_semaphore ) > 0? 1: 0;
 }
 
 bool vg_async_process_next_task( vg_async_queue *queue )
 {
-   sem_wait( &queue->work_semaphore );
-
-   pthread_mutex_lock( &queue->lock );
+   VG_SEMAPHORE_WAIT( queue->work_semaphore );
+   VG_MUTEX_LOCK( queue->lock );
    if( queue->quit == k_async_quit_immediate )
    {
-      pthread_mutex_unlock( &queue->lock );
+      VG_MUTEX_UNLOCK( queue->lock );
       return 0;
    }
    else if( queue->quit == k_async_quit_when_empty )
    {
       if( queue->queue.allocation_count == 0 )
       {
-         pthread_mutex_unlock( &queue->lock );
+         VG_MUTEX_UNLOCK( queue->lock );
          return 0;
       }
    }
    vg_async_task *task = vg_queue_tail_data( &queue->queue );
-   pthread_mutex_unlock( &queue->lock );
+   VG_MUTEX_UNLOCK( queue->lock );
 
    if( task )
    {
+      if( !task->handler )
+         vg_fatal_error( "NO HANDLER ALLOCATED FROM %s\n", task->alloc_debug_info );
+
       task->handler( task );
 
-      pthread_mutex_lock( &queue->lock );
+      VG_MUTEX_LOCK( queue->lock );
       vg_queue_pop( &queue->queue );
-      pthread_mutex_unlock( &queue->lock );
+      VG_MUTEX_UNLOCK( queue->lock );
    }
 
-   int status = 1;
-   sem_getvalue( &queue->blocking_memory_signal, &status );
-   if( status <= 0 )
-      sem_post( &queue->blocking_memory_signal );
+   if( VG_SEMAPHORE_VALUE( queue->blocking_signal ) <= 0 )
+      VG_SEMAPHORE_POST( queue->blocking_signal );
 
    return 1;
 }
 
 void vg_async_queue_end( vg_async_queue *queue, enum async_quit quit )
 {
-   pthread_mutex_lock( &queue->lock );
+   VG_MUTEX_LOCK( queue->lock );
    queue->quit = quit;
-   pthread_mutex_unlock( &queue->lock );
-   sem_post( &queue->work_semaphore );
+   VG_MUTEX_UNLOCK( queue->lock );
+   VG_SEMAPHORE_POST( queue->work_semaphore );
+}
+
+struct simple_function_info
+{
+   void (*fn)(void *userdata);
+   void *userdata;
+};
+
+static void simple_function_call( vg_async_task *task )
+{
+   struct simple_function_info *info = (void *)task->data;
+   info->fn( info->userdata );
+}
+
+void vg_async_call( vg_async_queue *queue, void(*fn)(void *userdata), void *userdata )
+{
+   vg_async_task *task = vg_allocate_async_task( queue, sizeof(struct simple_function_info), 1 );
+   struct simple_function_info *info = (void *)task->data;
+   info->fn = fn;
+   info->userdata = userdata;
+   vg_async_task_dispatch( task, simple_function_call );
 }
index 1e6f2d0478c54e667e61b01b5e984f535f2fb0e6..22c0e6c527b2cbe41a8a3bb62cf3e3ecbd1fa24c 100644 (file)
@@ -1,9 +1,7 @@
 #pragma once
 #include "vg/vg_mem.h"
 #include "vg/vg_mem_queue.h"
-
-#include <pthread.h>
-#include <semaphore.h>
+#include "vg/vg_mutex.h"
 
 typedef struct vg_async_queue vg_async_queue;
 typedef struct vg_async_task vg_async_task;
@@ -13,10 +11,12 @@ struct vg_async_queue
    u32 buffer_size;
    u32 requested_bytes;
 
-   sem_t blocking_memory_signal;
-   sem_t work_semaphore;
-   pthread_mutex_t lock, data_lock;
+   vg_semaphore blocking_signal;
+   vg_semaphore work_semaphore;
+   vg_mutex lock;
+   vg_mutex data_lock;
    vg_queue queue;
+   vg_async_task *allocating_task;
 
    enum async_quit
    {
@@ -29,6 +29,8 @@ struct vg_async_queue
 
 struct vg_async_task
 {
+   vg_async_queue *queue;
+   const char *alloc_debug_info;
    void (*handler)( vg_async_task *task );
    u8 data[];
 };
@@ -37,10 +39,13 @@ bool vg_init_async_queue( vg_async_queue *queue );
 void vg_free_async_queue( vg_async_queue *queue );
 
 /* returns NULL if out of memory, or if blocking is set, wait for memory to become availible */
-vg_async_task *vg_allocate_async_task( vg_async_queue *queue, u32 bytes, bool blocking );
-void vg_async_task_dispatch( vg_async_queue *queue, vg_async_task *task, void (*handler)( vg_async_task *task ) );
-void vg_async_call_function( vg_async_queue *queue, void (*function)(void *, u32), void *userdata, u32 usersize );
+#define vg_allocate_async_task( Q,B,BL ) _vg_allocate_async_task( Q,B,BL, VG_LOG_WHERE )
+vg_async_task *_vg_allocate_async_task( vg_async_queue *queue, u32 bytes, bool blocking, const char *debug_info );
+
+#define vg_async_task_dispatch( T,H ) _vg_async_task_dispatch( T,H, VG_LOG_WHERE )
+void _vg_async_task_dispatch( vg_async_task *task, void (*handler)( vg_async_task *task ), const char *debug_info );
 void vg_async_queue_end( vg_async_queue *queue, enum async_quit quit );
 
 bool vg_async_has_work( vg_async_queue *queue );
 bool vg_async_process_next_task( vg_async_queue *queue );
+void vg_async_call( vg_async_queue *queue, void(*fn)(void *userdata), void *userdata );
index cd4988399af96ac973291c11cb936829f5a58781..4a3536eac611ab79e324f96134a91a42e4a79bcc 100644 (file)
@@ -1,6 +1,5 @@
 #include "vg_audio_dsp.h"
 #include "vg_mem.h"
-#include "vg_async.h"
 
 struct vg_dsp vg_dsp;
 
index 9a1d861ab45f12c05ccc57c7809d86eb5cdf7529..754b2d400bb42932ce29de5991a52d2ef60b8415 100644 (file)
@@ -278,7 +278,7 @@ vg_compiler_run( struct vg_project *project,
    vg_strcat( &cmd, " -flto \\\n" );
 
    /* want a lot of warnings but not useless ones */
-   vg_strcat( &cmd, "  -Wall -ferror-limit=8\\\n"
+   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"
    );
index 82cea76b87cfbfbe19309eb59f10c7a3ab2b35b3..af6f137c36f862893d71a75fb193e768c5a5222c 100644 (file)
@@ -1,10 +1,19 @@
 #include "vg_engine.h"
-#include "vg_async.h"
+#include "vg_async2.h"
 
 struct vg_engine vg = 
 { 
    .time_rate = 1.0, 
    .time_fixed_delta = VG_TIMESTEP_FIXED,
+
+   .main_tasks = 
+   {
+      .buffer_size = 20*1024*1024
+   },
+   .loader_tasks = 
+   {
+      .buffer_size = 20*1024*1024
+   }
 };
 
 const u32 k_thread_purpose_nothing = 0x00;
@@ -62,35 +71,24 @@ struct vg_profile_set static _vg_prof_gameloop =
    }
 };
 
-static void async_vg_bake_shaders( void *payload, u32 size )
-{
-   vg_shaders_compile();
-}
-
 void vg_bake_shaders(void)
 {
    vg_console_reg_cmd( "reload_shaders", vg_shaders_live_recompile, NULL );
-   vg_async_call( async_vg_bake_shaders, NULL, 0 );
-}
-
-void async_internal_complete( void *payload, u32 size )
-{
-   vg_success( "Internal async setup complete\n" );
-
-   if( SDL_AtomicGet( &vg.engine_status ) == k_engine_status_crashed )
-      return;
-   else
-      SDL_AtomicSet( &vg.engine_status, k_engine_status_running );
-
-   vg_magi_restore();
+   vg_async_call( &vg.main_tasks, vg_shaders_compile, NULL );
 }
 
 #ifdef VG_CUSTOM_SHADERS
 void vg_auto_shader_register(void); /* created from codegen */
 #endif
 
-static void _vg_load_full( void *data )
+static void _vg_load_step0(void *_);
+static void _vg_load_step1(void *_);
+static void _vg_load_step2(void *_);
+static void _vg_load_step_complete(void *_);
+
+static void _vg_load_step0(void *_)
 {
+   THREAD_1;
 vg_info(" Copyright  .        . .       -----, ,----- ,---.   .---.  \n" );
 vg_info(" 2021-2025  |\\      /| |           /  |      |    | |    /| \n" );
 vg_info("            | \\    / | +--        /   +----- +---'  |   / | \n" );
@@ -101,7 +99,18 @@ vg_info("            '        ' '--' [] '----- '----- '     ' '---'  "
 
    vg_preload();
    vg_tex2d_replace_with_error_async( 0, &vg.tex_missing );
-   vg_async_stall();
+   vg_async_call( &vg.main_tasks, _vg_load_step1, NULL );
+}
+
+static void _vg_load_step1(void *_)
+{
+   THREAD_0;
+   vg_async_call( &vg.loader_tasks, _vg_load_step2, NULL );
+}
+
+static void _vg_load_step2(void *_)
+{
+   THREAD_1;
    vg_ui.tex_bg = vg.tex_missing;
 
    /* internal */
@@ -123,12 +132,26 @@ vg_info("            '        ' '--' [] '----- '----- '     ' '---'  "
    vg_auto_shader_register();
 #endif
    vg_load();
+}
 
-   vg_async_call( async_internal_complete, NULL, 0 );
-
+void _vg_load_temp_end(void)
+{
+   vg_async_call( &vg.main_tasks, _vg_load_step_complete, NULL );
    vg_success( "Client loaded in %fs\n", vg.time_real );
 }
 
+static void _vg_load_step_complete(void *_)
+{
+   vg_success( "Internal async setup complete\n" );
+
+   if( SDL_AtomicGet( &vg.engine_status ) == k_engine_status_crashed )
+      return;
+   else
+      SDL_AtomicSet( &vg.engine_status, k_engine_status_running );
+
+   vg_magi_restore();
+}
+
 static void _vg_process_events(void)
 {
    v2_zero( vg.mouse_wheel );
@@ -140,22 +163,18 @@ static void _vg_process_events(void)
    {
       if( event.type == SDL_KEYDOWN )
       {
-         if( vg_console.enabled && 
-               (vg_ui.ctx.focused_control_type != k_ui_control_modal) )
+         if( vg_console.enabled && (vg_ui.ctx.focused_control_type != k_ui_control_modal) )
          {
-            if( event.key.keysym.sym == SDLK_ESCAPE ||
-                event.key.keysym.scancode == SDL_SCANCODE_GRAVE )
+            if( (event.key.keysym.sym == SDLK_ESCAPE) || (event.key.keysym.scancode == SDL_SCANCODE_GRAVE) )
             {
                vg_console.enabled = 0;
                ui_defocus_all( &vg_ui.ctx );
             }
-            else if( (event.key.keysym.mod & KMOD_CTRL) && 
-                      event.key.keysym.sym == SDLK_n )
+            else if( (event.key.keysym.mod & KMOD_CTRL) && (event.key.keysym.sym == SDLK_n) )
             {
                console_suggest_next( &vg_ui.ctx );
             }
-            else if( (event.key.keysym.mod & KMOD_CTRL ) &&
-                      event.key.keysym.sym == SDLK_p )
+            else if( (event.key.keysym.mod & KMOD_CTRL ) && (event.key.keysym.sym == SDLK_p) )
             {
                console_suggest_prev( &vg_ui.ctx );
             }
@@ -182,8 +201,7 @@ static void _vg_process_events(void)
          vg.mouse_wheel[0] += event.wheel.preciseX;
          vg.mouse_wheel[1] += event.wheel.preciseY;
       }
-      else if( event.type == SDL_CONTROLLERDEVICEADDED ||
-               event.type == SDL_CONTROLLERDEVICEREMOVED )
+      else if( (event.type == SDL_CONTROLLERDEVICEADDED) || (event.type == SDL_CONTROLLERDEVICEREMOVED) )
       {
          vg_input_device_event( &event );
       }
@@ -250,15 +268,15 @@ static void _vg_gameloop_update(void)
    vg_lines.enabled = vg_lines.render;
    vg.time_fixed_accumulator += vg.time_delta;
 
-   while( vg.time_fixed_accumulator >= vg.time_fixed_delta ){
+   while( vg.time_fixed_accumulator >= vg.time_fixed_delta )
+   {
       vg_fixed_update();
       vg_lines.enabled = 0;
       vg.time_fixed_accumulator -= vg.time_fixed_delta;
 
       vg.fixed_iterations ++;
-      if( vg.fixed_iterations == 8 ){
+      if( vg.fixed_iterations == 8 )
          break;
-      }
    }
    vg_lines.enabled = vg_lines.render;
    vg.time_fixed_extrapolate = vg.time_fixed_accumulator / vg.time_fixed_delta;
@@ -361,25 +379,25 @@ static void vg_changevsync(void)
    }
 }
 
-static int vg_framefilter( double dt ){
-   if( vg.fps_limit < 24 ) vg.fps_limit = 24;
-   if( vg.fps_limit > 300 ) vg.fps_limit = 300;
+static int vg_framefilter( f64 dt )
+{
+   if( vg.fps_limit < 24 ) 
+      vg.fps_limit = 24;
+
+   if( vg.fps_limit > 300 ) 
+      vg.fps_limit = 300;
 
    double min_frametime = 1.0/(double)vg.fps_limit;
-   if( vg.time_frame_delta < min_frametime ){
+   if( vg.time_frame_delta < min_frametime )
+   {
       /* TODO: we can use high res nanosleep on Linux here */
       double sleep_ms = (min_frametime-vg.time_frame_delta) * 1000.0;
       u32 ms = (u32)floor( sleep_ms );
 
-      if( ms ){
-         if( !vg_loader_availible() )
-            SDL_Delay(1);
-         else
-            SDL_Delay(ms);
-      }
-      else{
+      if( ms )
+         SDL_Delay(ms);
+      else
          vg.time_spinning ++;
-      }
 
       return 1;
    }
@@ -430,9 +448,13 @@ static void _vg_gameloop(void)
       vg.time_hp_last = vg.time_hp;
 
       double dt = (double)udt / (double)SDL_GetPerformanceFrequency();
-
       vg.time_frame_delta += dt;
-      vg_run_async_checked();
+
+      while( vg_async_has_work( &vg.main_tasks ) )
+      {
+         if( vg_async_process_next_task( &vg.main_tasks ) == 0 )
+            return;
+      }
 
       if( vg_framefilter( dt ) )
          continue;
@@ -455,7 +477,7 @@ static void _vg_gameloop(void)
       _vg_process_events();
 
       if( vg.window_should_close )
-         break;
+         return;
          
       if( status == k_engine_status_crashed )
       {
@@ -691,12 +713,30 @@ static int cmd_log_memory( int argc, const char *argv[] )
    return 0;
 }
 
+static int _vg_loader_thread( void *pfn )
+{
+   SDL_TLSSet( vg.thread_purpose, &k_thread_purpose_loader, NULL );
+
+   if( setjmp( vg.env_loader_exit ) )
+      return 0;
+
+   while( vg_async_process_next_task( &vg.loader_tasks ) ) {}
+   return 0;
+}
+
 static int cmd_vg_settings_toggle( int argc, const char *argv[] );
 void vg_enter( int argc, char *argv[], const char *window_name )
 {
+   if( !vg_init_async_queue( &vg.main_tasks ) )
+      return;
+   if( !vg_init_async_queue( &vg.loader_tasks ) )
+      return;
+
    vg.thread_purpose = SDL_TLSCreate();
    VG_ASSERT( vg.thread_purpose );
-   SDL_TLSSet( vg.thread_purpose, &k_thread_purpose_nothing, NULL );
+
+   /* we pretend to be loader thread while it doesn't exist */
+   SDL_TLSSet( vg.thread_purpose, &k_thread_purpose_loader, NULL );
 
    vg_rand_seed( &vg.rand, 461 );
    _vg_process_launch_opts_internal( argc, argv );
@@ -718,21 +758,18 @@ void vg_enter( int argc, char *argv[], const char *window_name )
    vg_console_reg_cmd( "vg_rtmemory", cmd_log_memory, NULL );
    _vg_init_window( window_name );
 
-   vg_async_init();
    SDL_SetRelativeMouseMode(1);
 
    /* multi-threaded loading phase */
-   vg.sem_loader = SDL_CreateSemaphore(1);
-   VG_ASSERT( vg.sem_loader );
    SDL_AtomicSet( &vg.engine_status, k_engine_status_load_internal );
-   SDL_TLSSet( vg.thread_purpose, &k_thread_purpose_main, NULL );
    
    /* Opengl-required systems */
    vg_ui_init();
-
    vg_loader_step( vg_loader_init, vg_loader_free );
 
-    vg_loader_start( _vg_load_full, NULL );  
+   vg_async_call( &vg.loader_tasks, _vg_load_step0, NULL );
+   SDL_TLSSet( vg.thread_purpose, &k_thread_purpose_main, NULL );
+   SDL_CreateThread( _vg_loader_thread, "vg: loader", NULL );
    _vg_gameloop();
    _vg_terminate();
 }
@@ -1267,7 +1304,7 @@ static int cmd_vg_settings_toggle( int argc, const char *argv[] )
 __attribute__((used)) u32 NvOptimusEnablement = 0x00000001;
 __attribute__((used)) int AmdPowerXpressRequestHighPerformance = 1;
 
-#include "vg_async.c"
+#include "vg_async2.c"
 #include "vg_audio.c"
 #include "vg_audio_dsp.c"
 #include "vg_audio_synth_bird.c"
index 15ea85e06a8b67cbfcf90668e613672dce4cd734..1b977cac358afa3a55285197b734fd6c92db7956 100644 (file)
@@ -80,6 +80,7 @@
 #include "vg_font.h"
 #include "vg_string.h"
 #include "vg_ui/imgui.h"
+#include "vg_async2.h"
 
 #include <setjmp.h>
 
@@ -124,15 +125,11 @@ struct vg_engine
    /* Engine sync */
    SDL_Window     *window;
    SDL_GLContext  gl_context;
-   SDL_sem        *sem_loader; /* allows only one loader at a time */
 
    SDL_TLSID      thread_purpose;
 
-   //SDL_threadID  thread_id_main,
-   //              thread_id_loader;
-
-   jmp_buf env_loader_exit;
-   void    *thread_data;
+   vg_async_queue main_tasks, loader_tasks;
+   jmp_buf env_loader_exit; /* for deep fatal error handling */
 
    SDL_atomic_t engine_status;
 
@@ -174,12 +171,12 @@ struct vg_engine
           time_frame_delta;
 
    f32 time_fixed_delta;
-
    u64 time_hp, time_hp_last, time_spinning;
 
    int fixed_iterations;
 
-   enum engine_stage{
+   enum engine_stage
+   {
       k_engine_stage_none,
       k_engine_stage_update,
       k_engine_stage_update_fixed,
@@ -259,6 +256,10 @@ extern const u32 k_thread_purpose_nothing;
 extern const u32 k_thread_purpose_main;
 extern const u32 k_thread_purpose_loader;
 u32 vg_thread_purpose(void);
+void _vg_load_temp_end(void);
+
+#define THREAD_0 VG_ASSERT( vg_thread_purpose() == k_thread_purpose_main )
+#define THREAD_1 VG_ASSERT( vg_thread_purpose() == k_thread_purpose_loader )
 
 void vg_checkgl( const char *src_info );
 #define VG_STRINGIT( X ) #X
index 2f4a68fb2deecddacd9d0a8397fbd8adc5c1af1e..9cc045c8e489b93473fff2f21179960f212dd579 100644 (file)
@@ -1,6 +1,5 @@
 #include "vg_framebuffer.h"
 #include "vg_platform.h"
-#include "vg_async.h"
 
 struct
 {
@@ -249,9 +248,9 @@ vg_framebuffer *vg_framebuffer_allocate( void *alloc, u32 attachment_count, bool
    return fb;
 }
 
-static void async_framebuffer_create( void *payload, u32 size )
+static void async_framebuffer_create( void *_fb )
 {
-   vg_framebuffer *fb = payload;
+   vg_framebuffer *fb = _fb;
    glGenFramebuffers( 1, &fb->id );
    glBindFramebuffer( GL_FRAMEBUFFER, fb->id );
 
@@ -331,7 +330,8 @@ static void async_framebuffer_create( void *payload, u32 size )
 
 void vg_framebuffer_create( vg_framebuffer *fb )
 {
-   vg_async_call( async_framebuffer_create, fb, 0 );
+   THREAD_1;
+   vg_async_call( &vg.main_tasks, async_framebuffer_create, fb );
 }
 
 void vg_framebuffer_free( vg_framebuffer *fb )
index 9ca03a41b7f582f37cb5f0c0c4d5cf8894602475..3a1aa2774a9bce1a8085d1586d22663c621edf19 100644 (file)
@@ -3,7 +3,6 @@
 #include "vg_input.h"
 #include "vg_loader.h"
 #include "vg_engine.h"
-#include "vg_async.h"
 #include "vg_string.h"
 
 f32 controller_deadzone = 0.05f;
@@ -257,13 +256,14 @@ void vg_process_inputs(void)
       vg_input.hidden_mouse_travel = 0.0f;
 }
 
-void async_vg_input_init( void *payload, u32 size )
+static void async_vg_input_init( void *_ )
 {
    vg_info( "Checking for controllers\n" );
    SDL_GameControllerAddMappingsFromFile( "gamecontrollerdb.txt" );
    
    int joy_count = SDL_NumJoysticks();
-   for( int i=0; i<joy_count; i++ ) {
+   for( int i=0; i<joy_count; i++ ) 
+   {
       const char *name = SDL_JoystickNameForIndex( i );
       int is_controller = SDL_IsGameController(i);
 
@@ -276,8 +276,9 @@ void async_vg_input_init( void *payload, u32 size )
 
 void vg_input_init(void)
 {
+   THREAD_1;
    VG_VAR_F32( controller_deadzone, flags=VG_VAR_PERSISTENT );
-   vg_async_call( async_vg_input_init, NULL, 0 );
+   vg_async_call( &vg.main_tasks, async_vg_input_init, NULL );
 }
 
 void vg_input_free(void)
index 1636e07458db2da4b5d1cbe512eb7886112c4cfb..5c17d7e83354594f2a35003f717e936195d5193d 100644 (file)
@@ -74,7 +74,6 @@ extern vg_input;
 
 u8 vg_getkey( SDL_Keycode kc );
 void vg_process_inputs(void);
-void async_vg_input_init( void *payload, u32 size );
 void vg_input_init(void);
 void vg_input_free(void);
 struct vg_controller *vg_active_controller(void);
index 94f8b687b1f81523e76226db64f189d325ec7e32..364bd1aba151f991038c0d5cc47a5f40b41659c4 100644 (file)
@@ -4,7 +4,6 @@
 #include "vg_lines.h"
 #include "vg_shader.h"
 #include "vg_engine.h"
-#include "vg_async.h"
 
 struct vg_lines vg_lines;
 
@@ -48,8 +47,10 @@ static struct vg_shader _shader_lines = {
 
 #define VG_LINES_BUFFER_SIZE 50000 * sizeof( struct vg_lines_vert )
 
-static void async_vg_lines_init( void *payload, u32 payload_size )
+static void async_vg_lines_init( void *_ )
 {
+   THREAD_0;
+
    glGenVertexArrays( 1, &vg_lines.vao );
    glGenBuffers( 1, &vg_lines.vbo );
    glBindVertexArray( vg_lines.vao );
@@ -82,14 +83,11 @@ static void async_vg_lines_init( void *payload, u32 payload_size )
 
 void vg_lines_init(void)
 {
-   vg_lines.vertex_buffer = 
-      vg_create_linear_allocator( vg_mem.rtmemory, 
-                                  VG_LINES_BUFFER_SIZE, VG_MEMORY_REALTIME);
-
-   vg_async_call( async_vg_lines_init, NULL, 0 );
+   THREAD_1;
 
-   vg_console_reg_var( "vg_lines", &vg_lines.render, k_var_dtype_i32, 
-                       VG_VAR_CHEAT );
+   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 );
 }
 
index 8bbffd3279d812ef12d4358189b23554e12790d6..f22a826b238e17cbf1669fd82e38fadee311f805 100644 (file)
@@ -1,7 +1,6 @@
 #include "vg_engine.h"
 #include "vg_loader.h"
 #include "vg_shader.h"
-#include "vg_async.h"
 
 struct vg_loader vg_loader;
 
@@ -89,13 +88,9 @@ void vg_loader_free(void)
 
 void vg_loader_atexit(void)
 {
-   vg_info( "Shutdown steps\n" );
    for( int i=0; i<vg_loader.step_count; i++ )
    {
-      struct loader_free_step *step = 
-         &vg_loader.step_buffer[vg_loader.step_count -1 -i];
-
-      vg_info( " -> %p\n", step->fn_free );
+      struct loader_free_step *step = &vg_loader.step_buffer[vg_loader.step_count -1 -i];
       step->fn_free();
    }
 }
@@ -105,9 +100,9 @@ struct async_set_information_args
    const char *string;
 };
 
-void async_loader_set_user_information( void *payload, u32 size )
+void async_loader_set_user_information( vg_async_task *task )
 {
-   struct async_set_information_args *args = payload;
+   struct async_set_information_args *args = (void *)task->data;
    vg_loader.information_for_user = args->string;
 }
 
@@ -115,13 +110,10 @@ void vg_loader_set_user_information( const char *information )
 {
    if( vg_thread_purpose() == k_thread_purpose_loader )
    {
-      vg_async_item *call = 
-         vg_async_alloc( sizeof(struct async_set_information_args) );
-
-      struct async_set_information_args *args = call->payload;
+      vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct async_set_information_args), 1 );
+      struct async_set_information_args *args = (void *)task->data;
       args->string = information;
-
-      vg_async_dispatch( call,  async_loader_set_user_information );
+      vg_async_task_dispatch( task, async_loader_set_user_information );
 
       if( vg.load_step_delay )
          SDL_Delay( vg.load_step_delay );
@@ -173,55 +165,22 @@ void vg_loader_render(void)
    vg.loader_ring = 1.0f;
 }
 
-static int _vg_loader_thread( void *pfn )
-{
-   SDL_TLSSet( vg.thread_purpose, &k_thread_purpose_loader, NULL );
-
-   if( setjmp( vg.env_loader_exit ) )
-      return 0;
-
-   /* Run client loader */
-   void (*call_func)(void *data) = pfn;
-   call_func( vg.thread_data );
-
-   SDL_SemPost( vg.sem_loader );
-   return 0;
-}
-
-int vg_loader_availible(void)
-{
-   if( SDL_SemValue( vg.sem_loader ) )
-   {
-      if( !(vg_async.start) )
-         return 1;
-   }
-
-   return 0;
-}
-
-void vg_loader_start( void(*pfn)(void *data), void *data )
-{
-   SDL_SemWait( vg.sem_loader );
-
-   vg.thread_data = data;
-   SDL_CreateThread( _vg_loader_thread, "vg: loader", pfn );
-}
-
 /*
  * Schedule something to be ran now, freed later. Checks in with engine status
  */
-void _vg_loader_step( void( *fn_load )(void), void( *fn_free )(void),
-                      const char *alias )
+void _vg_loader_step( void( *fn_load )(void), void( *fn_free )(void), const char *alias )
 {
+   THREAD_1;
+
    u64 t0 = SDL_GetPerformanceCounter();
-   vg.time_hp_last = vg.time_hp;
+   vg.time_hp_last = vg.time_hp; // ???
 
    if( fn_load )
       fn_load();
 
    u64 udt = SDL_GetPerformanceCounter() - t0;
    double dt = (double)udt / (double)SDL_GetPerformanceFrequency();
-   vg_info( "ltime [%p] %s: %fs\n", fn_load, alias, dt );
+   vg_info( "%s: %fs\n", alias, dt );
 
    if( fn_free )
    {
index 3d0cbef6bf742434d6b4a0183c433c4e7a015bf3..8f43b3afe2f7f514ec07912b86e901088a1b1a80 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright 2021-2024 (C) Mount0 Software, Harry Godden - All Rights Reserved
+ * Copyright 2021-2025 (C) Mount0 Software, Harry Godden - All Rights Reserved
  * -----------------------------------------------------------------------------
  *
  * Splash / load screen
@@ -16,7 +16,8 @@
 struct vg_loader
 {
    /* Shutdown steps */
-   struct loader_free_step{
+   struct loader_free_step
+   {
       void (*fn_free)(void);
    }
    step_buffer[16];
@@ -28,16 +29,15 @@ struct vg_loader
 }
 extern vg_loader;
 
-void vg_loader_start( void(*pfn)(void *data), void *data );
-void _vg_loader_step( void( *fn_load )(void), void( *fn_free )(void),
-                      const char *alias );
+//void vg_loader_start( void(*pfn)(void *data), void *data );
+void _vg_loader_step( void( *fn_load )(void), void( *fn_free )(void), const char *alias );
 void vg_loader_set_user_information( const char *information );
-int vg_loader_availible(void);
 void vg_loader_render(void);
 void vg_loader_render_ring( f32 opacity );
 void vg_loader_free(void);
 void vg_loader_atexit(void);
 void vg_loader_init(void);
 
+//int vg_loader_availible(void);
 #define vg_loader_step( FN, FN_FREE )\
    _vg_loader_step( FN, FN_FREE, #FN )
diff --git a/vg_mutex.h b/vg_mutex.h
new file mode 100644 (file)
index 0000000..7e9974c
--- /dev/null
@@ -0,0 +1,34 @@
+#ifdef VG_ENGINE
+#define vg_semaphore SDL_sem *
+#define vg_mutex SDL_mutex *
+#define VG_SEMAPHORE_INIT( SEMAPHORE, VALUE ) (SEMAPHORE = SDL_CreateSemaphore( VALUE ))
+#define VG_SEMAPHORE_FREE( SEMAPHORE ) SDL_DestroySemaphore( SEMAPHORE ); SEMAPHORE = NULL;
+#define VG_MUTEX_INIT( MUTEX ) (MUTEX = SDL_CreateMutex())
+#define VG_MUTEX_FREE( MUTEX ) SDL_DestroyMutex( MUTEX ); MUTEX = NULL;
+#define VG_MUTEX_LOCK( MUTEX ) SDL_LockMutex( MUTEX )
+#define VG_MUTEX_UNLOCK( MUTEX ) SDL_UnlockMutex( MUTEX )
+#define VG_SEMAPHORE_WAIT( SEMAPHORE ) SDL_SemWait( SEMAPHORE )
+#define VG_SEMAPHORE_POST( SEMAPHORE ) SDL_SemPost( SEMAPHORE )
+#define VG_SEMAPHORE_VALUE( SEMAPHORE ) SDL_SemValue( SEMAPHORE )
+#else
+#include <pthread.h>
+#include <semaphore.h>
+#define vg_semaphore sem_t
+#define vg_mutex pthread_mutex_t
+#define VG_SEMAPHORE_INIT( SEMAPHORE, VALUE ) (sem_init( &SEMAPHORE, 0, VALUE )==0)
+#define VG_SEMAPHORE_FREE( SEMAPHORE ) sem_destroy( &SEMAPHORE )
+#define VG_SEMAPHORE_WAIT( SEMAPHORE ) sem_wait( &SEMAPHORE )
+#define VG_SEMAPHORE_POST( SEMAPHORE ) sem_post( &SEMAPHORE )
+static inline i32 get_semaphore_value( sem_t *sem )
+{
+   int value = 0;
+   sem_getvalue( sem, &value );
+   return value;
+}
+#define VG_SEMAPHORE_VALUE( SEMAPHORE ) get_semaphore_value( &SEMAPHORE )
+#define VG_MUTEX_INIT( MUTEX ) (pthread_mutex_init( &MUTEX, NULL )==0)
+#define VG_MUTEX_FREE( MUTEX ) pthread_mutex_destroy( &MUTEX )
+#define VG_MUTEX_LOCK( MUTEX ) pthread_mutex_lock( &MUTEX )
+#define VG_MUTEX_UNLOCK( MUTEX ) pthread_mutex_unlock( &MUTEX )
+#endif
+
index 477d47061102541fb5b2bdcc992cad9c275d0487..7c63978c39c9f9fa7d815912dceebdd101870b9a 100644 (file)
@@ -47,8 +47,10 @@ struct vg_render _vg_render =
    .scale = 1.0f
 };
 
-static void vg_async_postprocess_init( void *payload, u32 size )
+static void vg_async_postprocess_init( void *userdata )
 {
+   THREAD_0;
+
    f32 quad[] = 
    { 
       0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f,
@@ -68,8 +70,9 @@ static void vg_async_postprocess_init( void *payload, u32 size )
 
 void vg_render_init(void)
 {
-   vg_async_call( vg_async_postprocess_init, NULL, 0 );
+   THREAD_1;
 
+   vg_async_call( &vg.main_tasks, vg_async_postprocess_init, NULL );
    vg_console_reg_var( "render_scale", &_vg_render.scale, k_var_dtype_f32, VG_VAR_PERSISTENT );
 
 #ifdef VG_3D
index f16f3c66e8d460fa1161e288db259b6b3bd58ca9..f03f1c499faac4212a26edafee52fb64e25efc22 100644 (file)
@@ -3,7 +3,6 @@
 #include "vg_rigidbody.h"
 #include "vg_shader.h"
 #include "vg_engine.h"
-#include "vg_async.h"
 
 static struct vg_shader _shader_rigidbody = 
 {
@@ -109,9 +108,9 @@ struct vg_rb_mesh_init {
    u16 *tris;
 };
 
-static void async_vg_rb_view_init( void *payload, u32 payload_size )
+static void async_vg_rb_view_init( vg_async_task *task )
 {
-   struct vg_rb_mesh_init *inf = payload;
+   struct vg_rb_mesh_init *inf = (void *)task->data;
 
    glGenVertexArrays( 1, &vg_rb_view.vao );
    glGenBuffers( 1, &vg_rb_view.vbo );
@@ -138,6 +137,8 @@ static void async_vg_rb_view_init( void *payload, u32 payload_size )
 
 void vg_rb_view_init(void)
 {
+   THREAD_1;
+
    vg_shader_register( &_shader_rigidbody );
 
    u32 H = 20,
@@ -160,9 +161,8 @@ void vg_rb_view_init(void)
        vert_size = vg_align8( verts_count * sizeof(rb_view_vert) ),
        tris_size = vg_align8( tris_count * 3 * sizeof(u16) );
 
-   vg_async_item *call = vg_async_alloc( hdr_size + vert_size + tris_size );
-
-   struct vg_rb_mesh_init *inf = call->payload;
+   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, hdr_size + vert_size + tris_size, 1 );
+   struct vg_rb_mesh_init *inf = (void *)task->data;
    rb_view_vert *verts = ((void *)inf) + hdr_size;
    u16 *tris = ((void *)inf) + hdr_size + vert_size;
 
@@ -247,7 +247,7 @@ void vg_rb_view_init(void)
       tri_index += 1;
    }
 
-   vg_async_dispatch( call, async_vg_rb_view_init );
+   vg_async_task_dispatch( task, async_vg_rb_view_init );
 }
 
 void vg_rb_view_bind(void)
index 344120794af70c2e2c47847f3688ef159ba225fc..b36818367d938266c43d122522f083876ac52aa2 100644 (file)
@@ -197,10 +197,11 @@ void vg_free_shader( struct vg_shader *shader )
 void vg_auto_shader_link(void);
 #endif 
 
-void vg_shaders_compile(void)
+void vg_shaders_compile(void *_)
 {
-       vg_info( "Compiling shaders\n" );
+   THREAD_0;
 
+       vg_info( "Compiling shaders\n" );
        for( int i=0; i<vg_shaders.count; i ++ )
                vg_compile_shader( vg_shaders.shaders[i] );
 
@@ -221,7 +222,6 @@ int vg_shaders_live_recompile( int argc, const char *argv[] )
 #ifdef VG_CUSTOM_SHADERS
    vg_auto_shader_link();
 #endif
-
    return 0;
 }
 
index 9fff67ddc6f692ed65d06cf56643fbc07d960a72..afcdc819526ac904e32e88f878e399ae59e45fec 100644 (file)
@@ -15,7 +15,7 @@ struct vg_shader
    int compiled;
 };
 
-void vg_shaders_compile(void);
+void vg_shaders_compile(void *_);
 int vg_shaders_live_recompile(int argc, const char *argv[]);
 void vg_shader_register( struct vg_shader *shader );
 void vg_compile_shader( struct vg_shader *shader );
index 7f1c1b7bb99092110f7c3701a6dc6e12c2350c77..7db6171c8cab41034147974fe3fa82fe40dc833a 100644 (file)
--- a/vg_tex.c
+++ b/vg_tex.c
@@ -1,6 +1,5 @@
 #include "vg_tex.h"
 #include "vg_engine.h"
-#include "vg_async.h"
 #include "vg_io.h"
 #include <string.h>
 
@@ -72,17 +71,17 @@ static void qoi_write_32(unsigned char *bytes, int *p, unsigned int v) {
    bytes[(*p)++] = (0x000000ff & v);
 }
 
-struct texture_load_info{
+struct texture_load_info
+{
    GLuint *dest;
    u32 width, height, flags;
    u8 *rgba;
 };
 
-static void async_vg_tex2d_upload( void *payload, u32 size )
+static void async_vg_tex2d_upload( vg_async_task *task )
 {
-   VG_ASSERT( vg_thread_purpose() == k_thread_purpose_main );
-
-   struct texture_load_info *info = payload;
+   THREAD_0;
+   struct texture_load_info *info = (void *)task->data;
 
    glGenTextures( 1, info->dest );
 
@@ -148,11 +147,10 @@ static void async_vg_tex2d_upload( void *payload, u32 size )
 
 void vg_tex2d_replace_with_error_async( u32 original_flags, GLuint *dest )
 {
-   u32 hdr_size = vg_align8(sizeof(struct texture_load_info));
+   THREAD_1;
 
-   vg_async_item *call = vg_async_alloc( hdr_size );
-   struct texture_load_info *info = call->payload;
-   
+   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, sizeof(struct texture_load_info), 1 );
+   struct texture_load_info *info = (void *)task->data;
    info->dest = dest;
    info->flags = VG_TEX2D_ERROR|VG_TEX2D_NEAREST|VG_TEX2D_REPEAT|VG_TEX2D_NOMIP;
 
@@ -162,12 +160,13 @@ void vg_tex2d_replace_with_error_async( u32 original_flags, GLuint *dest )
    info->width = 4;
    info->height = 4;
    info->rgba = const_vg_tex2d_err;
-
-   vg_async_dispatch( call, async_vg_tex2d_upload );
+   vg_async_task_dispatch( task, async_vg_tex2d_upload );
 }
 
 void vg_tex2d_load_qoi_async( const u8 *bytes, u32 size, u32 flags, GLuint *dest )
 {
+   THREAD_1;
+
    u32 header_magic;
    qoi_rgba_t index[64];
    qoi_rgba_t px;
@@ -218,14 +217,13 @@ void vg_tex2d_load_qoi_async( const u8 *bytes, u32 size, u32 flags, GLuint *dest
    u32 hdr_size = vg_align8(sizeof(struct texture_load_info)),
        tex_size = vg_align8(px_len);
 
-   vg_async_item *call = vg_async_alloc( hdr_size + tex_size );
-   struct texture_load_info *info = call->payload;
-   
+   vg_async_task *task = vg_allocate_async_task( &vg.main_tasks, hdr_size + tex_size, 1 );
+   struct texture_load_info *info = (void *)task->data;
    info->dest = dest;
    info->flags = flags;
    info->width = desc.width;
    info->height = desc.height;
-   info->rgba = ((u8*)call->payload) + hdr_size;
+   info->rgba = task->data + hdr_size;
 
    /*
     * Decode 
@@ -295,7 +293,7 @@ void vg_tex2d_load_qoi_async( const u8 *bytes, u32 size, u32 flags, GLuint *dest
     * --------------------------
     */
 
-   vg_async_dispatch( call, async_vg_tex2d_upload );
+   vg_async_task_dispatch( task, async_vg_tex2d_upload );
 }
 
 void vg_tex2d_load_qoi_async_file( const char *path, u32 flags, GLuint *dest )