use work system for sprite loading
This commit is contained in:
parent
afea5ea512
commit
0b3e191bb2
113
src/sprite.c
113
src/sprite.c
@ -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);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
|
||||
Loading…
Reference in New Issue
Block a user