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
|
* Loader cmd structs
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct loader_cmd {
|
struct load_cmd {
|
||||||
struct loader_cmd *next;
|
struct load_cmd *next_free;
|
||||||
struct loader_cmd *next_free;
|
|
||||||
|
|
||||||
struct cache_node *cache_node;
|
struct cache_node *cache_node;
|
||||||
struct sprite_tag tag;
|
struct sprite_tag tag;
|
||||||
u8 tag_path_buff[512];
|
u8 tag_path_buff[512];
|
||||||
@ -129,16 +127,10 @@ GLOBAL struct {
|
|||||||
/* Cache */
|
/* Cache */
|
||||||
struct cache cache;
|
struct cache cache;
|
||||||
|
|
||||||
/* Loader threads */
|
/* Load cmds */
|
||||||
b32 loaders_shutdown;
|
struct sys_mutex load_cmds_mutex;
|
||||||
struct sys_mutex loaders_mutex;
|
struct arena load_cmds_arena;
|
||||||
struct sys_condition_variable loaders_cv;
|
struct load_cmd *first_free_load_cmd;
|
||||||
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];
|
|
||||||
|
|
||||||
/* Evictor thread */
|
/* Evictor thread */
|
||||||
struct atomic_u32 evictor_cycle;
|
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 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);
|
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,
|
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.cache.buckets[i].rw_mutex = sys_rw_mutex_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
G.loader_cmd_arena = arena_alloc(GIGABYTE(64));
|
G.load_cmds_arena = arena_alloc(GIGABYTE(64));
|
||||||
G.loaders_mutex = sys_mutex_alloc();
|
G.load_cmds_mutex = sys_mutex_alloc();
|
||||||
G.loaders_cv = sys_condition_variable_alloc();
|
|
||||||
|
|
||||||
G.evictor_mutex = sys_mutex_alloc();
|
G.evictor_mutex = sys_mutex_alloc();
|
||||||
G.evictor_cv = sys_condition_variable_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"));
|
G.evictor_thread = sys_thread_alloc(sprite_evictor_thread_entry_point, NULL, STR("[P0] Sprite evictor"));
|
||||||
|
|
||||||
app_register_exit_callback(&sprite_shutdown);
|
app_register_exit_callback(&sprite_shutdown);
|
||||||
@ -282,14 +262,6 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sprite_shutdown)
|
|||||||
{
|
{
|
||||||
__prof;
|
__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 */
|
/* Signal evictor shutdown */
|
||||||
sys_mutex_lock(&G.evictor_mutex);
|
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_condition_variable_broadcast(&G.evictor_cv);
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&G.evictor_mutex);
|
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);
|
sys_thread_wait_release(&G.evictor_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,16 +657,16 @@ INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_
|
|||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sys_mutex_lock(&G.loaders_mutex);
|
sys_mutex_lock(&G.load_cmds_mutex);
|
||||||
{
|
{
|
||||||
/* Allocate cmd */
|
/* Allocate cmd */
|
||||||
struct loader_cmd *cmd = NULL;
|
struct load_cmd *cmd = NULL;
|
||||||
if (G.first_free_loader_cmd) {
|
if (G.first_free_load_cmd) {
|
||||||
cmd = G.first_free_loader_cmd;
|
cmd = G.first_free_load_cmd;
|
||||||
G.first_free_loader_cmd = cmd->next_free;
|
G.first_free_load_cmd = cmd->next_free;
|
||||||
MEMZERO_STRUCT(cmd);
|
MEMZERO_STRUCT(cmd);
|
||||||
} else {
|
} 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 */
|
/* 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);
|
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 */
|
/* Cmd holds reference to node */
|
||||||
node_refcount_add(n, 1);
|
node_refcount_add(n, 1);
|
||||||
|
|
||||||
/* Signal work ready */
|
/* Push work */
|
||||||
sys_condition_variable_signal(&G.loaders_cv);
|
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;
|
__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;
|
struct cache_node *n = cmd->cache_node;
|
||||||
switch (n->kind) {
|
switch (n->kind) {
|
||||||
case CACHE_NODE_KIND_TEXTURE: {
|
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);
|
cache_node_load_sheet(n, cmd->tag);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
sys_mutex_lock(&G.loaders_mutex);
|
|
||||||
|
|
||||||
/* Free cmd */
|
/* Free cmd */
|
||||||
cmd->next_free = G.first_free_loader_cmd;
|
node_refcount_add(n, -1);
|
||||||
G.first_free_loader_cmd = cmd;
|
sys_mutex_lock(&G.load_cmds_mutex);
|
||||||
|
{
|
||||||
/* Cmd no longer references node */
|
cmd->next_free = G.first_free_load_cmd;
|
||||||
node_refcount_add(cmd->cache_node, -1);
|
G.first_free_load_cmd = cmd;
|
||||||
} else {
|
|
||||||
/* Wait for work */
|
|
||||||
sys_condition_variable_wait(&G.loaders_cv, &G.loaders_mutex);
|
|
||||||
}
|
}
|
||||||
}
|
sys_mutex_unlock(&G.load_cmds_mutex);
|
||||||
}
|
|
||||||
sys_mutex_unlock(&G.loaders_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user