From 06400325053998a5dafe8f374950b4f6dc189a1d Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 14 May 2025 07:05:47 +1000 Subject: [PATCH] fixed allocator and asset system bug, still experiencing an awful asset cleanup bug though --- src/allocators.c | 3 ++ src/assets.h | 2 -- src/ds.c | 31 ++++++++++++++++++- src/ds.h | 7 ++--- src/game.c | 30 ++++++++++-------- src/platform/platform.h | 2 ++ src/platform/platform_linux_public.c | 5 +++ src/renderer_vulkan.c | 46 +++++++++++++++++++++++----- src/renderer_vulkan.h | 6 ++-- src/renderer_vulkan_public.c | 7 +++-- src/shared_types.h | 6 ++++ 11 files changed, 112 insertions(+), 33 deletions(-) diff --git a/src/allocators.c b/src/allocators.c index 0459ab9..40a0da0 100644 --- a/src/allocators.c +++ b/src/allocators.c @@ -480,7 +480,10 @@ static void FreeListInsert(FLNode **head, FLNode *prev_node, FLNode *new_node) if (prev_node == &FL_NIL_NODE) { if (*head != &FL_NIL_NODE) + { new_node->next = *head; + *head = new_node; + } else *head = new_node; } diff --git a/src/assets.h b/src/assets.h index 0aea7ca..f6327a2 100644 --- a/src/assets.h +++ b/src/assets.h @@ -19,7 +19,6 @@ typedef enum AssetType_e : u32 typedef enum ShaderAsset_e : u32 { - SHADER_ASSET_NONE, QUAD_FRAG_SPIRV_SHADER, QUAD_VERT_SPIRV_SHADER, GUI_FRAG_SPIRV_SHADER, @@ -30,7 +29,6 @@ typedef enum ShaderAsset_e : u32 typedef enum TextureAsset_e : u32 { - TEXTURE_ASSET_NONE, PATTERMON_OBESE, PATTERMON_PURPLOID, PATTERMON_YUKATA, diff --git a/src/ds.c b/src/ds.c index 016907b..93cdbf1 100644 --- a/src/ds.c +++ b/src/ds.c @@ -511,7 +511,7 @@ static HashNode *HashTablePushU64Rawptr(HashTable *table, u64 key, rawptr value) static HashNode *HashTablePushU64U64Split(HashTable *table, u64 key, u32 upper, u32 lower) { u64 hash = HashFromString(String8Struct(&key)); - return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_u64_upper = upper, .value_u64_lower = lower }); + return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_u64_split = { .upper = upper, .lower = lower }}); } static HashNode *HashTablePushRawptrU64(HashTable *table, rawptr key, u64 value) @@ -606,6 +606,35 @@ static rawptr HashTableDeleteU64Rawptr(HashTable *table, u64 key) return value; } +static U64Split HashTableDeleteU64U64Split(HashTable *table, u64 key) +{ + U64Split value = { .upper = UINT32_MAX }; + + u64 hash = HashFromString(String8Struct(&key)); + u64 index = hash % table->cap; + HashList *list = table->lists + index; + HashNode *prev = P_HT_NIL; + for (HashNode *node = list->first; node != P_HT_NIL; node = node->next) + { + if (node->v.key_u64 == key) + { + if (prev != P_HT_NIL) + prev->next = node->next; + + value.upper = node->v.value_u64_split.upper; + value.lower = node->v.value_u64_split.lower; + + node->v.key_u64 = 0; + node->v.value_u64_split.upper = 0; + node->v.value_u64_split.lower = 0; + HTQueuePush(table->free_lists.first, table->free_lists.last, node); + break; + } + } + + return value; +} + // ::DataStructures::HashTable::Functions::End:: diff --git a/src/ds.h b/src/ds.h index cb5f9c6..b355708 100644 --- a/src/ds.h +++ b/src/ds.h @@ -86,11 +86,7 @@ typedef struct KeyValuePair rawptr value_rawptr; u32 value_u32; u64 value_u64; - union - { - u32 value_u64_upper; - u32 value_u64_lower; - }; + U64Split value_u64_split; }; } KeyValuePair; @@ -127,5 +123,6 @@ static HashNode *HashTablePushU64U64(HashTable *table, u64 key, u64 value); static HashNode *HashTablePushU64String8(HashTable *table, u64 key, String8 value); static HashNode *HashTablePushU64Rawptr(HashTable *table, u64 key, rawptr value); static HashNode *HashTablePushU64U64Split(HashTable *table, u64 key, u32 upper, u32 lower); +static rawptr HashTableDeleteU64Rawptr(HashTable *table, u64 key); static void HashTableDeleteU64(HashTable *table, u64 key); diff --git a/src/game.c b/src/game.c index c7962af..12d99f7 100644 --- a/src/game.c +++ b/src/game.c @@ -58,6 +58,14 @@ static void gRunCycle(gGameCtx *ctx, pGameInput *inputs, u32 i_count) gPrepareGUICtx(ctx); gHandleInputs(inputs, i_count); + + rFrameBegin(); + + + // This is fucked up, it's triggering before even being set + vTextureCleanUp(); + + Printfln("post clean up"); /* if (gButton(ctx, "Show 2", 150.0f, 150.0f, 200.0f, 200.0f)) @@ -76,19 +84,19 @@ static void gRunCycle(gGameCtx *ctx, pGameInput *inputs, u32 i_count) } */ + u64 index = vFrameIndex(); + rDescHandle texture; + if (index == 0) + texture = rTextureLoad(HAMSMOKER); + else + texture = rTextureLoad(HOG); + + rTextureUnload(texture); + rViewportSize(&ctx->pc.res); ctx->pc.time = (f32)pCPUTimerRead(); - rDescHandle pattermon = rTextureLoad(CHEESOID); - rDescHandle pattermon2 = rTextureLoad(HAMSTER); - rDescHandle purplemon = rTextureLoad(HAMSMOKER); - rDescHandle hog = rTextureLoad(HOG); - - gWindow(ctx, "Pattermon", 100.0f, 100.0f, 300.0f, 300.0f, pattermon); - gWindow(ctx, "Pattermon2", 350.0f, 350.0f, 550.0f, 550.0f, purplemon); - gWindow(ctx, "Pattermon3", 600.0f, 100.0f, 800.0f, 300.0f, pattermon2); - gWindow(ctx, "ham", 100.0f, 600.0f, 300.0f, 800.0f, pattermon2); - gWindow(ctx, "hog", 150.0f, 820.0f, 450.0f, 1020.0f, hog); + gWindow(ctx, "texture", 100.0f, 100.0f, 300.0f, 300.0f, texture); rawptr vert_buffer = rBufferGUIVertMapping(); rawptr idx_buffer = rBufferGUIIdxMapping(); @@ -98,8 +106,6 @@ static void gRunCycle(gGameCtx *ctx, pGameInput *inputs, u32 i_count) vBufferQueueWait(); - rFrameBegin(); - rPipelineBind(R_PIPELINE_GUI, rPT_GRAPHICS); rPushConstantsSet(&ctx->pc); diff --git a/src/platform/platform.h b/src/platform/platform.h index dd47d4d..921c17c 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -132,6 +132,8 @@ static inline u64 pCPUTimerRead(); // ::Platform::Atomics::Header:: +static inline void AtomicSignalFenceSeqCst(); + #define DefSigAtomicFetchIncr(T) static inline T p##T##AtomicFetchIncr(T volatile *ptr) #define DefSigAtomicFetchSub(T) static inline T p##T##AtomicFetchSub(T volatile *ptr, T count) #define DefSigAtomicIncr(T) static inline void p##T##AtomicIncr(T volatile *ptr) diff --git a/src/platform/platform_linux_public.c b/src/platform/platform_linux_public.c index 3c47d88..b45e653 100644 --- a/src/platform/platform_linux_public.c +++ b/src/platform/platform_linux_public.c @@ -334,6 +334,11 @@ static inline u64 pCPUTimerRead() // ::Platform::Atomics::Functions::Start:: +static inline void AtomicSignalFenceSeqCst() +{ + __atomic_signal_fence(__ATOMIC_SEQ_CST); +} + DefScalarImpl(AtomicFetchIncr); DefScalarImpl(AtomicIncr); DefScalarImpl(AtomicStore); diff --git a/src/renderer_vulkan.c b/src/renderer_vulkan.c index 44cac12..ff61c36 100644 --- a/src/renderer_vulkan.c +++ b/src/renderer_vulkan.c @@ -401,18 +401,27 @@ static b32 vImageViewCreate(vImageView *view, u32 width, u32 height, u32 channel return success; } -static void vTextureCleanUp(vImageView *view) +static void vTextureCleanUp() { VkDevice device = v_Renderer.handles.device; VmaAllocator vma_alloc = v_Renderer.handles.vma_alloc; HashTable *table = &v_Renderer.buffers.images; b8 *queue = vFrameTexDestroyQueue(); + Printfln("frame: %llu", v_Renderer.state.renderer.frame_count); + + // NOTE: might need a mutex here at some point, check if crashes related to image access for (u64 i = 0; i < TEXTURE_ASSET_MAX; i++) { if (queue[i]) { - vImageView *view = HashTableDeleteU64Rawptr(table, i); + Printfln("fetching handle for id: %llu", i); + + rDescHandle handle = vDescHandlePop(vDT_SAMPLED_IMAGE, (u32)i); + vDescIndexPush(vDT_SAMPLED_IMAGE, handle.desc_index); + + Printfln("queue %llu %d", i, queue[i]); + vImageView *view = vImagePop(i); Assert(view != NULL, "rTextureUnload failure: value not in hash table"); vkDestroyImageView(device, view->view, NULL); @@ -423,17 +432,19 @@ static void vTextureCleanUp(vImageView *view) queue[i] = false; } } + + AtomicSignalFenceSeqCst(); } static void vImagePush(TextureAsset asset_id, vImageView *view) { - Assert(asset_id != 0, "asset_id is TEXTURE_ASSET_NONE"); HashTablePushU64Rawptr(&v_Renderer.buffers.images, asset_id, view); } -static void vImagePop(TextureAsset asset_id) +static vImageView *vImagePop(TextureAsset asset_id) { - + Printfln("popping id: %llu", asset_id); + return (vImageView *)HashTableDeleteU64Rawptr(&v_Renderer.buffers.images, asset_id); } static vImageView *vImageSearch(TextureAsset asset_id) @@ -507,24 +518,41 @@ static rDescHandle vDescHandleSearch(vDescType type, u32 asset_id) .asset_id = UINT32_MAX, }; + Printfln("search asset_id: %llu", asset_id); + HashTable *table = &v_Renderer.desc_bindings[type].lookup_table; KeyValuePair *kv_pair = HashTableSearchU64(table, asset_id); if (kv_pair != NULL) { - asset_info.asset_id = kv_pair->value_u64_upper; - asset_info.desc_index = kv_pair->value_u64_lower; + asset_info.asset_id = kv_pair->value_u64_split.upper; + asset_info.desc_index = kv_pair->value_u64_split.lower; } return asset_info; } -static void vDescHandleInsert(vDescType type, rDescHandle handle) +static void vDescHandlePush(vDescType type, rDescHandle handle) { HashTable *table = &v_Renderer.desc_bindings[type].lookup_table; HashTablePushU64U64Split(table, handle.asset_id, handle.asset_id, handle.desc_index); } +static rDescHandle vDescHandlePop(vDescType type, u32 asset_id) +{ + HashTable *table = &v_Renderer.desc_bindings[type].lookup_table; + + U64Split split = HashTableDeleteU64U64Split(table, (u64)asset_id); + Assert(split.upper != UINT32_MAX, "vDescHandlePop failure: unable to find asset handle"); + + rDescHandle handle = { + .asset_id = split.upper, + .desc_index = split.lower, + }; + + return handle; +} + static void vDescHandleDelete(vDescType type, u32 asset_id) { HashTable *table = &v_Renderer.desc_bindings[type].lookup_table; @@ -1433,6 +1461,7 @@ static b32 vDescriptorsInit() { for (u32 i = 0; i < vDT_MAX; i++) { + // FREE MIGHT BE NULL bindings[i].free = ArenaAlloc(v_Renderer.mem.perm_arena, sizeof(u32) * DESC_MAX_BINDINGS); HashTableInit(&bindings[i].lookup_table, 6); @@ -1626,6 +1655,7 @@ static b32 vBuffersInit() InitArrayType(buf->frame_images[i], arena, vImageView *, 128); buf->tex_destroy_queue[i] = MakeArray(arena, b8, TEXTURE_ASSET_MAX); + MemZero(buf->tex_destroy_queue, sizeof(b8) * TEXTURE_ASSET_MAX); } diff --git a/src/renderer_vulkan.h b/src/renderer_vulkan.h index 3223bf6..58d4b79 100644 --- a/src/renderer_vulkan.h +++ b/src/renderer_vulkan.h @@ -550,8 +550,9 @@ static void vSwapchainResize(); // ::Vulkan::Images::Functions::Header:: static b32 vImageViewCreate(vImageView *view, u32 width, u32 height, u32 channels); -static void vTextureCleanUp(vImageView *view); +static void vTextureCleanUp(); static void vImagePush(TextureAsset asset_id, vImageView *view); +static vImageView *vImagePop(TextureAsset asset_id); static vImageView *vImageSearch(TextureAsset asset_id); // ::Vulkan::Descriptors::Functions::Header:: @@ -559,7 +560,8 @@ static vImageView *vImageSearch(TextureAsset asset_id); static void vDescIndexPush(vDescType type, u32 index); static u32 vDescIndexPop(vDescType type); static rDescHandle vDescHandleSearch(vDescType type, u32 asset_id); -static void vDescHandleInsert(vDescType type, rDescHandle handle); +static void vDescHandlePush(vDescType type, rDescHandle handle); +static rDescHandle vDescHandlePop(vDescType type, u32 asset_id); static void vDescHandleDelete(vDescType type, u32 asset_id); static u32 vDescPushImage(vImageView *view); diff --git a/src/renderer_vulkan_public.c b/src/renderer_vulkan_public.c index 141425c..ad04e5d 100644 --- a/src/renderer_vulkan_public.c +++ b/src/renderer_vulkan_public.c @@ -139,6 +139,7 @@ static rDescHandle rTextureLoad(TextureAsset asset_id) // TODO: handle errors instead of failing Assert(vImageViewCreate(view, meta.w, meta.h, meta.ch), "rTextureLoad failure: vImageViewCreate failed"); + Printfln("Loading asset: %llu", asset_id); handle.asset_id = asset_id; handle.desc_index = vDescPushImage(view); @@ -160,7 +161,7 @@ static rDescHandle rTextureLoad(TextureAsset asset_id) v_Renderer.upload.transfers[job_idx] = transfer; - vDescHandleInsert(vDT_SAMPLED_IMAGE, handle); + vDescHandlePush(vDT_SAMPLED_IMAGE, handle); vImagePush(asset_id, view); TicketMutUnlock(&v_Renderer.upload.mut); @@ -177,9 +178,9 @@ static void rTextureUnload(rDescHandle current_handle) if (handle.asset_id != UINT32_MAX) { - b8 *queue = vFrameNextTexDestroyQueue(); + b8 *queue = vFrameTexDestroyQueue(); - queue[handle.asset_id] = true; + queue[current_handle.asset_id] = true; } } diff --git a/src/shared_types.h b/src/shared_types.h index 61d60c7..41f7dd6 100644 --- a/src/shared_types.h +++ b/src/shared_types.h @@ -77,6 +77,12 @@ typedef uint32_t usize; #endif +typedef union +{ + struct { u32 upper, lower; }; + u64 full; +} U64Split; + typedef union { struct { f32 r, g; };