use work system for sprite loading

This commit is contained in:
jacob 2024-06-21 14:27:35 -05:00
parent afea5ea512
commit 0b3e191bb2

View File

@ -35,10 +35,8 @@
* Loader cmd structs
* ========================== */
struct loader_cmd {
struct loader_cmd *next;
struct loader_cmd *next_free;
struct load_cmd {
struct load_cmd *next_free;
struct cache_node *cache_node;
struct sprite_tag tag;
u8 tag_path_buff[512];
@ -129,16 +127,10 @@ GLOBAL struct {
/* Cache */
struct cache cache;
/* Loader threads */
b32 loaders_shutdown;
struct sys_mutex loaders_mutex;
struct sys_condition_variable loaders_cv;
struct arena loader_cmd_arena;
struct loader_cmd *first_free_loader_cmd;
struct loader_cmd *first_loader_cmd;
struct loader_cmd *last_loader_cmd;
u64 loader_threads_count;
struct sys_thread loader_threads[MAX_LOADER_THREADS];
/* Load cmds */
struct sys_mutex load_cmds_mutex;
struct arena load_cmds_arena;
struct load_cmd *first_free_load_cmd;
/* Evictor thread */
struct atomic_u32 evictor_cycle;
@ -216,7 +208,7 @@ INTERNAL struct image_rgba generate_purple_black_image(struct arena *arena, u32
* ========================== */
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sprite_shutdown);
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_loader_thread_entry_point, arg);
INTERNAL WORK_TASK_FUNC_DEF(sprite_load_task, arg);
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg);
struct sprite_startup_receipt sprite_startup(struct renderer_startup_receipt *renderer_sr,
@ -253,24 +245,12 @@ struct sprite_startup_receipt sprite_startup(struct renderer_startup_receipt *re
G.cache.buckets[i].rw_mutex = sys_rw_mutex_alloc();
}
G.loader_cmd_arena = arena_alloc(GIGABYTE(64));
G.loaders_mutex = sys_mutex_alloc();
G.loaders_cv = sys_condition_variable_alloc();
G.load_cmds_arena = arena_alloc(GIGABYTE(64));
G.load_cmds_mutex = sys_mutex_alloc();
G.evictor_mutex = sys_mutex_alloc();
G.evictor_cv = sys_condition_variable_alloc();
{
struct temp_arena scratch = scratch_begin_no_conflict();
G.loader_threads_count = clamp_i64(1, MAX_LOADER_THREADS, sys_num_logical_processors() - 1);
for (u64 i = 0; i < G.loader_threads_count; ++i) {
struct string thread_name = string_format(scratch.arena,
STR("[P0] Sprite loader %F"),
FMT_UINT(i));
G.loader_threads[i] = sys_thread_alloc(sprite_loader_thread_entry_point, NULL, thread_name);
}
scratch_end(scratch);
}
G.evictor_thread = sys_thread_alloc(sprite_evictor_thread_entry_point, NULL, STR("[P0] Sprite evictor"));
app_register_exit_callback(&sprite_shutdown);
@ -282,14 +262,6 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sprite_shutdown)
{
__prof;
/* Signal loaders shutdown */
sys_mutex_lock(&G.loaders_mutex);
{
G.loaders_shutdown = true;
sys_condition_variable_broadcast(&G.loaders_cv);
}
sys_mutex_unlock(&G.loaders_mutex);
/* Signal evictor shutdown */
sys_mutex_lock(&G.evictor_mutex);
{
@ -297,12 +269,6 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sprite_shutdown)
sys_condition_variable_broadcast(&G.evictor_cv);
}
sys_mutex_unlock(&G.evictor_mutex);
/* Wait on threads */
for (u64 i = 0; i < G.loader_threads_count; ++i) {
sys_thread_wait_release(&G.loader_threads[i]);
}
sys_thread_wait_release(&G.evictor_thread);
}
@ -691,16 +657,16 @@ INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_
} break;
}
} else {
sys_mutex_lock(&G.loaders_mutex);
sys_mutex_lock(&G.load_cmds_mutex);
{
/* Allocate cmd */
struct loader_cmd *cmd = NULL;
if (G.first_free_loader_cmd) {
cmd = G.first_free_loader_cmd;
G.first_free_loader_cmd = cmd->next_free;
struct load_cmd *cmd = NULL;
if (G.first_free_load_cmd) {
cmd = G.first_free_load_cmd;
G.first_free_load_cmd = cmd->next_free;
MEMZERO_STRUCT(cmd);
} else {
cmd = arena_push_zero(&G.loader_cmd_arena, struct loader_cmd);
cmd = arena_push_zero(&G.load_cmds_arena, struct load_cmd);
}
/* Initialize cmd */
@ -712,17 +678,13 @@ INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_
MEMCPY(cmd->tag.path.text, tag.path.text, copy_len);
}
/* Add cmd to queue */
*(G.last_loader_cmd ? &G.last_loader_cmd->next : &G.first_loader_cmd) = cmd;
G.last_loader_cmd = cmd;
/* Cmd holds reference to node */
node_refcount_add(n, 1);
/* Signal work ready */
sys_condition_variable_signal(&G.loaders_cv);
/* Push work */
work_push_task(&sprite_load_task, cmd, WORK_PRIORITY_NORMAL);
}
sys_mutex_unlock(&G.loaders_mutex);
sys_mutex_unlock(&G.load_cmds_mutex);
}
}
@ -792,28 +754,14 @@ struct sprite_sheet_frame sprite_sheet_get_frame(struct sprite_sheet *sheet, u32
}
/* ========================== *
* Loader thread
* Load task
* ========================== */
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_loader_thread_entry_point, arg)
INTERNAL WORK_TASK_FUNC_DEF(sprite_load_task, arg)
{
__prof;
(UNUSED)arg;
struct load_cmd *cmd = (struct load_cmd *)arg;
sys_mutex_lock(&G.loaders_mutex);
{
while (!G.loaders_shutdown) {
struct loader_cmd *cmd = G.first_loader_cmd;
if (cmd) {
/* Pop cmd from queue */
G.first_loader_cmd = cmd->next;
if (G.last_loader_cmd == cmd) {
G.last_loader_cmd = NULL;
}
/* Do work (temporarily unlock) */
sys_mutex_unlock(&G.loaders_mutex);
{
struct cache_node *n = cmd->cache_node;
switch (n->kind) {
case CACHE_NODE_KIND_TEXTURE: {
@ -823,22 +771,15 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_loader_thread_entry_point, arg)
cache_node_load_sheet(n, cmd->tag);
} break;
}
}
sys_mutex_lock(&G.loaders_mutex);
/* Free cmd */
cmd->next_free = G.first_free_loader_cmd;
G.first_free_loader_cmd = cmd;
/* Cmd no longer references node */
node_refcount_add(cmd->cache_node, -1);
} else {
/* Wait for work */
sys_condition_variable_wait(&G.loaders_cv, &G.loaders_mutex);
node_refcount_add(n, -1);
sys_mutex_lock(&G.load_cmds_mutex);
{
cmd->next_free = G.first_free_load_cmd;
G.first_free_load_cmd = cmd;
}
}
}
sys_mutex_unlock(&G.loaders_mutex);
sys_mutex_unlock(&G.load_cmds_mutex);
}
/* ========================== *