From d8f1d646da0338b8c203ae6a35e5391febf9e9a6 Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 13 May 2025 06:49:33 -0500 Subject: [PATCH] fix resource watch list merging & deduplication --- res/graphics/tim.ase | 4 ++-- src/renderer_d3d11.c | 3 +-- src/resource.c | 26 ++++++++++++++++---------- src/resource.h | 4 ++-- src/sprite.c | 16 ++++++---------- src/sys_win32.c | 2 ++ 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/res/graphics/tim.ase b/res/graphics/tim.ase index c01f80d8..f975bd8d 100644 --- a/res/graphics/tim.ase +++ b/res/graphics/tim.ase @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e515b2d3f37e14b647f231aea4884ff52944020198818234f0a02829aea07aa -size 6180 +oid sha256:cd0019692bfc14d9c0ad8b9140145ff81e49b26615a3636007d9b5fc01566aa8 +size 6087 diff --git a/src/renderer_d3d11.c b/src/renderer_d3d11.c index 04d4d1c9..5d0e46af 100644 --- a/src/renderer_d3d11.c +++ b/src/renderer_d3d11.c @@ -369,9 +369,8 @@ INTERNAL void reload_shader(struct dx11_shader *old_shader, struct dx11_shader_d } #if RESOURCE_RELOADING -INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, info) +INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name) { - struct string name = info->name; struct dx11_shader_desc *desc = (struct dx11_shader_desc *)fixed_dict_get(&G.shader_info_lookup, name); if (desc) { logf_info("Shader source file \"%F\" has changed", FMT_STR(name)); diff --git a/src/resource.c b/src/resource.c index b567d605..4d882890 100644 --- a/src/resource.c +++ b/src/resource.c @@ -183,7 +183,14 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(resource_watch_monitor_thread_entry_poi struct sys_watch_info_list res = sys_watch_wait(temp.arena, &watch); struct sys_lock lock = sys_mutex_lock_e(&G.watch_dispatcher_mutex); { - G.watch_dispatcher_info_list = sys_watch_info_copy(&G.watch_dispatcher_info_arena, res); + struct sys_watch_info_list list_part = sys_watch_info_copy(&G.watch_dispatcher_info_arena, res); + if (G.watch_dispatcher_info_list.last) { + G.watch_dispatcher_info_list.last->next = list_part.first; + list_part.first->prev = G.watch_dispatcher_info_list.last; + G.watch_dispatcher_info_list.last = list_part.last; + } else { + G.watch_dispatcher_info_list = list_part; + } } sys_mutex_unlock(&lock); sys_condition_variable_broadcast(&G.watch_dispatcher_cv); @@ -199,7 +206,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(resource_watch_monitor_thread_entry_poi * the dispatch of these callbacks, allowing for deduplication of file * modification notifications. */ -#define WATCH_DISPATCHER_DELAY_SECONDS 0.100 +#define WATCH_DISPATCHER_DELAY_SECONDS 0.050 #define WATCH_DISPATCHER_DEDUP_DICT_BINS 128 INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(resource_watch_dispatcher_thread_entry_point, _) @@ -221,6 +228,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(resource_watch_dispatcher_thread_entry_ /* Pull watch info from queue */ struct sys_watch_info_list watch_info_list = sys_watch_info_copy(temp.arena, G.watch_dispatcher_info_list); + MEMZERO_STRUCT(&G.watch_dispatcher_info_list); arena_reset(&G.watch_dispatcher_info_arena); /* Unlock and run callbacks */ @@ -228,20 +236,18 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(resource_watch_dispatcher_thread_entry_ { struct fixed_dict dedup_dict = fixed_dict_init(temp.arena, WATCH_DISPATCHER_DEDUP_DICT_BINS); for (struct sys_watch_info *info = watch_info_list.first; info; info = info->next) { + /* Do not run callbacks for the same file more than once */ b32 skip = false; - if (info->kind == SYS_WATCH_INFO_KIND_MODIFIED) { - /* Skip modified notifications for the same file */ - if ((u64)fixed_dict_get(&dedup_dict, info->name) != 1) { - fixed_dict_set(temp.arena, &dedup_dict, info->name, (void *)1); - } else { - skip = true; - } + if ((u64)fixed_dict_get(&dedup_dict, info->name) == 1) { + skip = true; + } else { + fixed_dict_set(temp.arena, &dedup_dict, info->name, (void *)1); } if (!skip) { struct sys_lock callbacks_lock = sys_mutex_lock_s(&G.watch_callbacks_mutex); for (u64 i = 0; i < G.num_watch_callbacks; ++i) { resource_watch_callback *callback = G.watch_callbacks[i]; - callback(info); + callback(info->name); } sys_mutex_unlock(&callbacks_lock); } diff --git a/src/resource.h b/src/resource.h index b5b8dfed..9461d0bf 100644 --- a/src/resource.h +++ b/src/resource.h @@ -39,8 +39,8 @@ b32 resource_exists(struct string path); #define resource_get_name(res_ptr) STRING((res_ptr)->_file_name_len, (res_ptr)->_file_name_text) #endif -#define RESOURCE_WATCH_CALLBACK_FUNC_DEF(func_name, arg_info) void func_name(struct sys_watch_info *arg_info) -typedef RESOURCE_WATCH_CALLBACK_FUNC_DEF(resource_watch_callback, info); +#define RESOURCE_WATCH_CALLBACK_FUNC_DEF(func_name, arg_name) void func_name(struct string arg_name) +typedef RESOURCE_WATCH_CALLBACK_FUNC_DEF(resource_watch_callback, name); #if RESOURCE_RELOADING void resource_register_watch_callback(resource_watch_callback *callback); diff --git a/src/sprite.c b/src/sprite.c index b825af14..d2283ada 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -655,7 +655,6 @@ INTERNAL void cache_node_load_sheet(struct cache_node *n, struct sprite_tag tag) logf_info("Loading sprite sheet [%F] \"%F\"", FMT_HEX(n->hash.v), FMT_STR(path)); i64 start_ns = sys_time_ns(); - //ASSERT(string_ends_with(path, LIT(".ase"))); ASSERT(n->kind == CACHE_NODE_KIND_SHEET); /* TODO: Replace arena allocs w/ buddy allocator */ @@ -1076,9 +1075,8 @@ INTERNAL WORK_TASK_FUNC_DEF(sprite_load_task, arg) #if RESOURCE_RELOADING -INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(sprite_resource_watch_callback, info) +INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(sprite_resource_watch_callback, name) { - struct string name = info->name; struct sprite_tag tag = sprite_tag_from_path(name); for (enum cache_node_kind kind = 0; kind < NUM_CACHE_NODE_KINDS; ++kind) { struct cache_node_hash hash = cache_node_hash_from_tag_hash(tag.hash, kind); @@ -1088,6 +1086,7 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(sprite_resource_watch_callback, info) { for (struct cache_node *n = bin->first; n; n = n->next_in_bin) { if (n->hash.v == hash.v) { + logf_info("Sprite resource file \"%F\" has changed and will be reloaded.", FMT_STR(name)); atomic_i32_eval_exchange(&n->out_of_date, 1); } } @@ -1162,13 +1161,10 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg) struct cache_node_refcount refcount = *(struct cache_node_refcount *)&refcount_uncast; if (refcount.count <= 0) { #if RESOURCE_RELOADING - /* Check if file changed for resource reloading */ - if (!consider_for_eviction) { - if (atomic_i32_eval(&n->out_of_date)) { - logf_info("Resource file for sprite texture/sheet [%F] has changed. Evicting to allow for reloading.", FMT_HEX(n->hash.v)); - consider_for_eviction = true; - force_evict = true; - } + /* Force evict out-of-date sprites */ + if (atomic_i32_eval(&n->out_of_date)) { + consider_for_eviction = true; + force_evict = true; } #endif diff --git a/src/sys_win32.c b/src/sys_win32.c index 0f5501a0..48d7f963 100644 --- a/src/sys_win32.c +++ b/src/sys_win32.c @@ -786,6 +786,7 @@ struct sys_watch_info_list sys_watch_wait(struct arena *arena, struct sys_watch list.last = info; } else { list.first = info; + list.last = info; } struct string16 name16 = ZI; @@ -857,6 +858,7 @@ struct sys_watch_info_list sys_watch_info_copy(struct arena *arena, struct sys_w dst_list.last = dst; } else { dst_list.first = dst; + dst_list.last = dst; } } return dst_list;