double buffer sys events and pass into present job

This commit is contained in:
jacob 2025-07-10 21:59:41 -05:00
parent 66bae61b1a
commit 7e81231639
12 changed files with 72 additions and 104 deletions

View File

@ -279,16 +279,14 @@ void sys_app_entry(struct string args_str)
#endif
/* Startup systems */
struct resource_startup_receipt resource_sr = resource_startup();
gp_startup();
struct sock_startup_receipt sock_sr = sock_startup();
struct host_startup_receipt host_sr = host_startup(&sock_sr);
struct asset_cache_startup_receipt asset_cache_sr = asset_cache_startup();
struct ttf_startup_receipt ttf_sr = ttf_startup();
struct font_startup_receipt font_sr = font_startup(&asset_cache_sr, &ttf_sr, &resource_sr);
struct sprite_startup_receipt sprite_sr = sprite_startup(&resource_sr);
struct font_startup_receipt font_sr = font_startup(&asset_cache_sr, &ttf_sr);
struct sprite_startup_receipt sprite_sr = sprite_startup();
struct mixer_startup_receipt mixer_sr = mixer_startup();
struct sound_startup_receipt sound_sr = sound_startup(&asset_cache_sr, &resource_sr);
struct sound_startup_receipt sound_sr = sound_startup(&asset_cache_sr);
struct draw_startup_receipt draw_sr = draw_startup(&font_sr);
struct sim_startup_receipt sim_sr = sim_startup();
struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr);

View File

@ -1,14 +1,6 @@
#ifndef APP_H
#define APP_H
enum app_dedicated_worker_id {
APP_DEDICATED_WORKER_ID_USER = 0,
APP_DEDICATED_WORKER_ID_SIM = 1,
APP_DEDICATED_WORKER_ID_AUDIO = 2,
NUM_APP_DEDICATED_WORKERS
};
struct string app_write_path_cat(struct arena *arena, struct string filename);
void app_exit(void);

View File

@ -40,12 +40,10 @@ GLOBAL struct {
* ========================== */
struct font_startup_receipt font_startup(struct asset_cache_startup_receipt *asset_cache_sr,
struct ttf_startup_receipt *ttf_sr,
struct resource_startup_receipt *resource_sr)
struct ttf_startup_receipt *ttf_sr)
{
(UNUSED)asset_cache_sr;
(UNUSED)ttf_sr;
(UNUSED)resource_sr;
G.params.arena = arena_alloc(GIBI(64));

View File

@ -6,7 +6,6 @@
struct asset;
struct asset_cache_startup_receipt;
struct ttf_startup_receipt;
struct resource_startup_receipt;
struct font_glyph {
f32 off_x;
@ -29,8 +28,7 @@ struct font {
struct font_startup_receipt { i32 _; };
struct font_startup_receipt font_startup(struct asset_cache_startup_receipt *asset_cache_sr,
struct ttf_startup_receipt *ttf_sr,
struct resource_startup_receipt *resource_sr);
struct ttf_startup_receipt *ttf_sr);
struct asset *font_load_asset(struct string path, f32 point_size, b32 wait);
struct font *font_load_async(struct string path, f32 point_size);

View File

@ -33,11 +33,9 @@ GLOBAL struct {
* Startup
* ========================== */
struct sound_startup_receipt sound_startup(struct asset_cache_startup_receipt *asset_cache_sr,
struct resource_startup_receipt *resource_sr)
struct sound_startup_receipt sound_startup(struct asset_cache_startup_receipt *asset_cache_sr)
{
(UNUSED)asset_cache_sr;
(UNUSED)resource_sr;
G.params.arena = arena_alloc(GIBI(64));

View File

@ -6,7 +6,6 @@
struct asset;
struct asset_cache_startup_receipt;
struct resource_startup_receipt;
struct sound {
u32 flags;
@ -14,8 +13,7 @@ struct sound {
};
struct sound_startup_receipt { i32 _; };
struct sound_startup_receipt sound_startup(struct asset_cache_startup_receipt *asset_cache_sr,
struct resource_startup_receipt *resource_sr);
struct sound_startup_receipt sound_startup(struct asset_cache_startup_receipt *asset_cache_sr);
struct asset *sound_load_asset(struct string path, u32 flags, b32 wait);
struct sound *sound_load_async(struct string path, u32 flags);

View File

@ -208,10 +208,8 @@ INTERNAL SYS_JOB_DEF(sprite_evictor_job, _);
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(sprite_resource_watch_callback, info);
#endif
struct sprite_startup_receipt sprite_startup(struct resource_startup_receipt *resource_sr)
struct sprite_startup_receipt sprite_startup(void)
{
(UNUSED)resource_sr;
G.perm_arena = arena_alloc(MEBI(1));
{
/* Init loading texture */

View File

@ -3,7 +3,6 @@
#include "util.h"
struct resource_startup_receipt;
struct sprite_sheet_span;
struct sprite_sheet_slice_group;
@ -12,7 +11,7 @@ struct sprite_sheet_slice_group;
* ========================== */
struct sprite_startup_receipt { i32 _; };
struct sprite_startup_receipt sprite_startup(struct resource_startup_receipt *resource_sr);
struct sprite_startup_receipt sprite_startup(void);
/* ========================== *
* Tag

View File

@ -434,16 +434,12 @@ struct sys_window_settings {
i32 floating_height;
};
struct sys_window_event_job_sig {
struct sys_window *window;
struct sys_event event;
};
struct sys_window_present_job_sig {
struct sys_window *window;
struct sys_event_array events;
};
struct sys_window *sys_window_alloc(sys_job_func *event_job, sys_job_func *present_job);
struct sys_window *sys_window_alloc(sys_job_func *present_job);
void sys_window_release(struct sys_window *sys_window);
void sys_window_update_settings(struct sys_window *sys_window, struct sys_window_settings *settings);

View File

@ -9,6 +9,7 @@
#include "util.h"
#include "uni.h"
#include "gp.h"
#include "resource.h"
#pragma warning(push, 0)
# define UNICODE
@ -48,7 +49,6 @@
#define MAX_EXIT_FUNCS 1024
/* Arbitrary threshold for determining when to fall back from a looped WakeByAddressSingle to WakeByAddressAll */
#define WAKE_ALL_THRESHOLD 8
@ -105,7 +105,10 @@ struct win32_window {
struct gp_swapchain *swapchain;
sys_job_func *event_job;
struct snc_mutex event_arena_swp_mutex;
i32 current_event_arena_index;
struct arena *event_arenas[2];
sys_job_func *present_job;
struct sys_thread *event_thread;
@ -887,7 +890,7 @@ INTERNAL SYS_THREAD_DEF(job_worker_entry, worker_ctx_arg)
void *job_sig = 0;
struct snc_counter *job_counter = 0;
{
__profnc("Pull job", RGB32_F(0.75, 0.75, 0));
//__profnc("Pull job", RGB32_F(0.75, 0.75, 0));
for (u32 queue_index = 0; queue_index < countof(queues) && !job_func; ++queue_index) {
struct job_queue *queue = queues[queue_index];
if (queue) {
@ -1121,7 +1124,7 @@ INTERNAL SYS_THREAD_DEF(job_worker_entry, worker_ctx_arg)
{
shutdown = atomic_i32_fetch(&G.workers_shutdown.v);
while (atomic_i64_fetch(&G.num_jobs_in_queue.v) <= 0 && !shutdown) {
__profnc("Wait for job", RGB32_F(0.75, 0.75, 0));
//__profnc("Wait for job", RGB32_F(0.75, 0.75, 0));
snc_cv_wait(&G.workers_wake_cv, &wake_lock);
shutdown = atomic_i32_fetch(&G.workers_shutdown.v);
}
@ -2203,14 +2206,13 @@ INTERNAL void win32_window_wake(struct win32_window *window);
INTERNAL void win32_window_process_event(struct win32_window *window, struct sys_event event)
{
if (window->event_job) {
__prof;
struct snc_counter counter = ZI;
struct sys_window_event_job_sig sig = ZI;
sig.window = (struct sys_window *)window;
sig.event = event;
sys_run(1, window->event_job, &sig, SYS_PRIORITY_NORMAL, &counter);
snc_counter_wait(&counter);
if (window->present_job) {
struct snc_lock lock = snc_lock_e(&window->event_arena_swp_mutex);
{
*arena_push(window->event_arenas[window->current_event_arena_index], struct sys_event) = event;
}
snc_unlock(&lock);
}
}
@ -2349,17 +2351,32 @@ INTERNAL SYS_THREAD_DEF(window_present_thread_entry_point, arg)
__profn("Swapchain wait");
gp_swapchain_wait(window->swapchain);
}
{
i32 event_arena_index = 0;
{
struct snc_lock lock = snc_lock_e(&window->event_arena_swp_mutex);
event_arena_index = window->current_event_arena_index;
window->current_event_arena_index = 1 - window->current_event_arena_index;
snc_unlock(&lock);
}
struct arena *events_arena = window->event_arenas[event_arena_index];
struct sys_event_array events = ZI;
events.count = events_arena->pos / sizeof(struct sys_event);
events.events = (struct sys_event *)arena_base(events_arena);
{
struct snc_counter counter = ZI;
struct sys_window_present_job_sig sig = ZI;
sig.window = (struct sys_window *)window;
sig.events = events;
sys_run(1, window->present_job, &sig, SYS_PRIORITY_HIGH, &counter);
snc_counter_wait(&counter);
}
arena_reset(events_arena);
}
}
}
INTERNAL struct win32_window *win32_window_alloc(sys_job_func *event_job, sys_job_func *present_job)
INTERNAL struct win32_window *win32_window_alloc(sys_job_func *present_job)
{
struct win32_window *window = 0;
{
@ -2373,10 +2390,17 @@ INTERNAL struct win32_window *win32_window_alloc(sys_job_func *event_job, sys_jo
snc_unlock(&lock);
}
MEMZERO_STRUCT(window);
window->event_job = event_job;
window->present_job = present_job;
if (present_job) {
window->event_arenas[0] = arena_alloc(GIBI(64));
window->event_arenas[1] = arena_alloc(GIBI(64));
}
/* Start window event thread */
/* NOTE: This thread must finish building for the window to actually be
* created and receive a HWND, because on Windows a the event proc must run on
* the same thread that created the window. */
snc_counter_add(&window->ready_fence, 1);
window->event_thread = sys_thread_alloc(&window_event_thread_entry_point, window, LIT("Window event thread"), PROF_THREAD_GROUP_WINDOW);
snc_counter_wait(&window->ready_fence);
@ -2387,25 +2411,25 @@ INTERNAL struct win32_window *win32_window_alloc(sys_job_func *event_job, sys_jo
window->present_thread = sys_thread_alloc(&window_present_thread_entry_point, window, LIT("Window present thread"), PROF_THREAD_GROUP_WINDOW);
}
/* Release swapchain */
gp_swapchain_release(window->swapchain);
return window;
}
INTERNAL void win32_window_release(struct win32_window *window)
{
struct snc_lock lock = snc_lock_e(&G.windows_mutex);
window->next_free = G.first_free_window;
G.first_free_window = window;
/* Stop window threads */
atomic_i32_fetch_set(&window->shutdown, 1);
win32_window_wake(window);
sys_thread_wait_release(window->present_thread);
sys_thread_wait_release(window->event_thread);
/* Release swapchain */
gp_swapchain_release(window->swapchain);
struct snc_lock lock = snc_lock_e(&G.windows_mutex);
{
window->next_free = G.first_free_window;
G.first_free_window = window;
}
snc_unlock(&lock);
}
@ -2769,10 +2793,10 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
return result;
}
struct sys_window *sys_window_alloc(sys_job_func *event_job, sys_job_func *present_job)
struct sys_window *sys_window_alloc(sys_job_func *present_job)
{
__prof;
return (struct sys_window *)win32_window_alloc(event_job, present_job);
return (struct sys_window *)win32_window_alloc(present_job);
}
void sys_window_release(struct sys_window *sys_window)
@ -3364,6 +3388,10 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
/* Start test thread */
struct sys_thread *test_thread = sys_thread_alloc(test_entry, 0, LIT("Test thread"), PROF_THREAD_GROUP_APP);
/* Startup systems */
resource_startup();
gp_startup();
/* ========================== *
* App thread setup
* ========================== */

View File

@ -192,6 +192,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
INTERNAL SYS_EXIT_FUNC(user_shutdown);
INTERNAL LOG_EVENT_CALLBACK_FUNC_DEF(debug_console_log_callback, log);
INTERNAL SYS_JOB_DEF(user_update_job, _);
INTERNAL SYS_JOB_DEF(local_sim_job , _);
struct user_startup_receipt user_startup(struct font_startup_receipt *font_sr,
@ -222,9 +223,6 @@ struct user_startup_receipt user_startup(struct font_startup_receipt *font_sr,
/* Initialize average dt to a reasonable value */
G.average_local_to_user_snapshot_publish_dt_ns = NS_FROM_SECONDS(1) / SIM_TICKS_PER_SECOND;
/* Sys events */
G.sys_events_arena = arena_alloc(GIBI(64));
/* User blend clients */
G.user_client_store = sim_client_store_alloc();
G.user_unblended_client = sim_client_alloc(G.user_client_store);
@ -248,7 +246,7 @@ struct user_startup_receipt user_startup(struct font_startup_receipt *font_sr,
sys_run(1, local_sim_job, 0, SYS_PRIORITY_HIGH, &G.shutdown_job_counters);
sys_on_exit(&user_shutdown);
G.window = sys_window_alloc(user_event_job, user_present_job);
G.window = sys_window_alloc(user_update_job);
return (struct user_startup_receipt) { 0 };
}
@ -263,36 +261,6 @@ INTERNAL SYS_EXIT_FUNC(user_shutdown)
snc_counter_wait(&G.shutdown_job_counters);
}
/* ========================== *
* Window -> user communication
* ========================== */
INTERNAL struct sys_event_array pop_sys_events(struct arena *arena)
{
struct sys_event_array array = ZI;
struct snc_lock lock = snc_lock_e(&G.sys_events_mutex);
{
struct sys_event *src_events = (struct sys_event *)arena_base(G.sys_events_arena);
array.count = G.sys_events_arena->pos / sizeof(*src_events);
array.events = arena_push_array_no_zero(arena, struct sys_event, array.count);
MEMCPY(array.events, src_events, array.count * sizeof(*src_events));
arena_reset(G.sys_events_arena);
}
snc_unlock(&lock);
return array;
}
SYS_JOB_DEF(user_event_job, job)
{
__prof;
struct sys_window_event_job_sig *sig = job.sig;
struct snc_lock lock = snc_lock_e(&G.sys_events_mutex);
{
*arena_push_no_zero(G.sys_events_arena, struct sys_event) = sig->event;
}
snc_unlock(&lock);
}
/* ========================== *
* Debug draw
* ========================== */
@ -593,11 +561,12 @@ INTERNAL SORT_COMPARE_FUNC_DEF(ent_draw_order_cmp, arg_a, arg_b, udata)
* Update
* ========================== */
SYS_JOB_DEF(user_present_job, job)
SYS_JOB_DEF(user_update_job, job)
{
__prof;
struct sys_window_present_job_sig *sig = job.sig;
struct sys_window *window = sig->window;
struct sys_event_array events = sig->events;
struct arena_temp scratch = scratch_begin_no_conflict();
@ -731,7 +700,6 @@ SYS_JOB_DEF(user_present_job, job)
{
__profn("Process sys events");
struct sys_event_array events = pop_sys_events(scratch.arena);
/* Reset bind pressed / released states */
for (u32 i = 0; i < countof(G.bind_states); ++i) {

View File

@ -70,7 +70,4 @@ struct user_startup_receipt user_startup(struct font_startup_receipt *font_sr,
struct sim_startup_receipt *sim_sr,
struct string connect_address_str);
SYS_JOB_DEF(user_event_job, job);
SYS_JOB_DEF(user_present_job, job);
#endif