From fee5f311f2c41a86c874a8b103e1397614659505 Mon Sep 17 00:00:00 2001 From: Matthew Date: Fri, 25 Apr 2025 18:48:31 +1000 Subject: [PATCH] work on asset loading queues --- src/ds.c | 10 +++++-- src/game.c | 1 + src/platform/platform.h | 2 +- src/platform/platform_linux.h | 2 +- src/renderer.h | 8 +++--- src/renderer_vulkan.c | 53 +++++++++++++++++++++++++++-------- src/renderer_vulkan.h | 14 ++++----- src/renderer_vulkan_public.c | 52 ++++++++++++++++++++++++++-------- src/util.c | 14 ++++----- src/util.h | 14 ++------- src/vulkan_config.c | 11 ++------ 11 files changed, 115 insertions(+), 66 deletions(-) diff --git a/src/ds.c b/src/ds.c index 9245b3f..0526d2e 100644 --- a/src/ds.c +++ b/src/ds.c @@ -434,9 +434,15 @@ static void HashTableInit(HashTable *table, u32 init_size) { table->cap = init_size; table->count = 0; - table->lists = FLMemAlloc(sizeof(HashList) * init_size); table->free_lists.first = P_HT_NIL; table->free_lists.last = P_HT_NIL; + + table->lists = FLMemAlloc(sizeof(HashList) * init_size); + for (u32 i = 0; i < init_size; i++) + { + table->lists[i].first = P_HT_NIL; + table->lists[i].last = P_HT_NIL; + } } static void HashTableConcatInPlace(HashList *list, HashList *to_concat) @@ -561,7 +567,7 @@ static void HashTableDeleteU64(HashTable *table, u64 key) node->v.key_u64 = 0; node->v.value_u64 = 0; - HTQueuePush(ht->free_lists.first, ht->free_lists.last, node); + HTQueuePush(table->free_lists.first, table->free_lists.last, node); break; } } diff --git a/src/game.c b/src/game.c index f0721be..2a61879 100644 --- a/src/game.c +++ b/src/game.c @@ -72,6 +72,7 @@ static void RunCycle(GameContext *ctx, GameInput *inputs, u32 i_count) GetViewportSize(&ctx->pc.res); + //DescHandle pattermon = CreateAndUploadToTexture(PATTERMON_OBESE); RenderBuffer *vertex_buffer = MakeArray(ctx->arena, RenderBuffer, 1); vertex_buffer->type = RENDER_BUFFER_TYPE_VERTEX; diff --git a/src/platform/platform.h b/src/platform/platform.h index b5892d2..c540aee 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -78,7 +78,7 @@ static inline u64 ReadCPUTimer(); #define DefSigAtomicIncr(T) static inline void AtomicIncr##T(T *ptr) #define DefSigAtomicStore(T) static inline void AtomicStore##T(T *ptr, T value) #define DefSigAtomicLoad(T) static inline T AtomicLoad##T(T *ptr) -#define DefSigAtomicCompareExchange(T) static inline T AtomicCompareExchange##T(T *ptr, T *expected, T desired) +#define DefSigAtomicCompareExchange(T) static inline b32 AtomicCompareExchange##T(T *ptr, T *expected, T desired) DefScalarSig(AtomicFetchIncr); DefScalarSig(AtomicFetchSub); diff --git a/src/platform/platform_linux.h b/src/platform/platform_linux.h index 3000e36..77cf0a0 100644 --- a/src/platform/platform_linux.h +++ b/src/platform/platform_linux.h @@ -91,7 +91,7 @@ b32 CheckSyscallErr(void *ptr); #define DefAtomicFetchIncr(T) \ static inline T AtomicFetchIncr##T(T *ptr) \ -{ \ +{ \ return __atomic_fetch_add(ptr, (T)1, __ATOMIC_ACQUIRE); \ } diff --git a/src/renderer.h b/src/renderer.h index 4d72207..8572d44 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -46,9 +46,9 @@ typedef enum RenderBufferType_e typedef enum TextureBufferType_e { - IMAGE_BUFFER_TYPE_NONE = 0x0000, - IMAGE_BUFFER_TYPE_IMAGE = 0x0001, - IMAGE_BUFFER_TYPE_SAMPLER = 0x0002, + TEXTURE_BUFFER_TYPE_NONE = 0x0000, + TEXTURE_BUFFER_TYPE_IMAGE = 0x0001, + TEXTURE_BUFFER_TYPE_SAMPLER = 0x0002, } TextureBufferType; typedef enum VertexAttrType_e @@ -78,7 +78,7 @@ static b32 CreateBuffer(RenderBuffer *buffer); static void FreeBuffers(RenderBuffer *buffers, u32 buffer_count); static b32 UploadToBuffer(RenderBuffer **buffer, rawptr *ptr, u32 count, u32 thr_ix); static void CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr); -static DescHandle CreateAndUploadToTexture(TextureBuffer *buffer, rawptr ptr); +static DescHandle CreateAndUploadToTexture(TextureAsset asset_id); static void BindVertexBuffer(RenderBuffer *buffer); static void BindIndexBuffer(RenderBuffer *buffer); static AssetHandle RendererLoadTexture(TextureAsset asset_id); diff --git a/src/renderer_vulkan.c b/src/renderer_vulkan.c index f12c1bc..01a96c8 100644 --- a/src/renderer_vulkan.c +++ b/src/renderer_vulkan.c @@ -344,6 +344,7 @@ static b32 CreateVkSampler(TextureBuffer *buffer) .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .samples = VK_SAMPLE_COUNT_1_BIT, .extent = { .width = buffer->width, .height = buffer->height, @@ -427,14 +428,17 @@ static void UploadToImage(TextureBuffer *buffer, u8 *data, u32 thread_idx) u32 width = buffer->width; u32 height = buffer->height; u32 channels = buffer->channels; - RenderBuffer staging_buffer; + RenderBuffer staging_buffer = { + .type = RENDER_BUFFER_TYPE_STAGING, + .size = width * height * channels, + }; TransitionImage(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - success = CreateBuffer(&staging_buffer); + success = BeginImmSubmit(device, fence, cmd); if (success) - success = BeginImmSubmit(device, fence, cmd); + Assert(CreateBuffer(&staging_buffer), "UploadToImage failure: error creating buffer"); if (success) { @@ -471,6 +475,26 @@ static void UploadToImage(TextureBuffer *buffer, u8 *data, u32 thread_idx) // ::Vulkan::Descriptors::Functions::Start:: +static void DescriptorHandlePush(DescType type, DescHandle handle) +{ + DescBindings *bindings = renderer.vk.pipe.bindings + type; + + Assert(bindings->free_count < DESC_MAX_BINDINGS-1, "DescriptorHandlePush failure: free_count equal to DESC_MAX_BINDINGS-1"); + + bindings->free[bindings->free_count] = handle; + bindings->free_count += 1; +} + +static DescHandle DescriptorHandlePop(DescType type) +{ + DescBindings *bindings = renderer.vk.pipe.bindings + type; + + Assert(bindings->free_count > 0, "DescriptorHandlePop failure: free_count is 0"); + + bindings->free_count -= 1; + return bindings->free[bindings->free_count]; +} + static DescAssetInfo *DescriptorTableSearch(DescType type, u64 asset_id) { DescAssetInfo *asset_info = NULL; @@ -501,9 +525,7 @@ static void DescriptorTableInsert(DescType type, u64 asset_id, DescHandle handle static void DescriptorTableDelete(DescType type, u64 asset_id) { HashTable *table = &renderer.vk.pipe.bindings[type].lookup_table; - - - + HashTableDeleteU64(table, asset_id); } // ::Vulkan::Descriptors::Functions::End:: @@ -657,6 +679,7 @@ static b32 CheckDeviceFeatureSupport(VkPhysicalDevice device) result &= (b32)features.shaderSampledImageArrayDynamicIndexing; result &= (b32)features.shaderStorageBufferArrayDynamicIndexing; result &= (b32)features.shaderStorageImageArrayDynamicIndexing; + result &= (b32)features.samplerAnisotropy; result &= (b32)features_12.descriptorIndexing; result &= (b32)features_12.bufferDeviceAddress; @@ -1243,12 +1266,11 @@ static b32 CreateDescriptors() for (u32 i = 0; i < DESC_TYPE_MAX; i++) { - bindings[i].free = ArenaAlloc(renderer.perm_arena, sizeof(u16) * DESC_MAX_BINDINGS); - bindings[i].used = ArenaAlloc(renderer.perm_arena, sizeof(u16) * DESC_MAX_BINDINGS); + bindings[i].free = ArenaAlloc(renderer.perm_arena, sizeof(u32) * DESC_MAX_BINDINGS); HashTableInit(&bindings[i].lookup_table, 6); - u16 free_count = 0; + u32 free_count = 0; for (i32 j = DESC_MAX_BINDINGS-1; j >= 0; j--) { bindings[i].free[j] = free_count++; @@ -1422,7 +1444,7 @@ static u32 VkLoaderProcessBuffers(u32 thread_index) RenderBuffer *buffers[16]; rawptr data[16]; - for (u32 i = buffer_count; i >= 0 && count < 16; i++) + for (i32 i = i32(buffer_count - 1); i >= 0 && count < 16; i--) { buffers[count] = render_buffers[i]; data[count] = buffer_data[i]; @@ -1459,7 +1481,7 @@ static u32 VkLoaderProcessSamplers(u32 thread_index) TextureBuffer *buffers[16]; rawptr data[16]; - for (u32 i = buffer_count; i >= 0 && count < 16; i++) + for (i32 i = i32(buffer_count - 1); i >= 0 && count < 16; i--) { buffers[count] = texture_buffers[i]; data[count] = texture_data[i]; @@ -1476,7 +1498,12 @@ static u32 VkLoaderProcessSamplers(u32 thread_index) UploadToImage(buffers[i], data[i], thread_index); } - JobQueueMarkCompleted(&renderer.vk.imm.texture_queue, count); + JobQueueMarkCompleted(job_queue, count); + + for (u32 i = 0; i < count; i++) + { + FLMemFree(buffers[i]); + } } return count; @@ -1526,9 +1553,11 @@ void *VkLoaderStart(void *i) else if (processed_count == 0 && iter_count >= 3) { iter_count = 0; + AtomicIncru8(&renderer.vk_conf.sleeping_threads); pthread_mutex_lock(&mut); pthread_cond_wait(&cond, &mut); pthread_mutex_unlock(&mut); + AtomicFetchSubu8(&renderer.vk_conf.sleeping_threads, 1); } } } diff --git a/src/renderer_vulkan.h b/src/renderer_vulkan.h index 11e90e9..7d6103a 100644 --- a/src/renderer_vulkan.h +++ b/src/renderer_vulkan.h @@ -240,10 +240,8 @@ typedef struct DescAssetInfo typedef struct DescBindings { - u16 *free; - u16 free_count; - u16 *used; - u16 used_count; + u32 *free; + u32 free_count; HashTable lookup_table; } DescBindings; @@ -294,8 +292,6 @@ typedef struct ImmediateStructures VkCommandPool *pools; VkCommandBuffer *cmds; VkFence *fences; - JobQueue buffer_queue; - JobQueue texture_queue; } ImmediateStructures; typedef struct DeviceQueues @@ -357,7 +353,8 @@ typedef struct PendingUpdates typedef struct VulkanConfig { - u8 avail_threads; + u8 avail_threads; + u8 volatile sleeping_threads; #ifdef __linux__ pthread_t *threads; #elif _WIN32 @@ -457,7 +454,10 @@ static void UploadToImage(TextureBuffer *buffer, u8 *data, u32 thread_idx); // ::Vulkan::Descriptors::Functions::Header:: +static void DescriptorHandlePush(DescType type, DescHandle handle); +static DescHandle DescriptorHandlePop(DescType type); static DescAssetInfo *DescriptorTableSearch(DescType type, u64 asset_id); +static void DescriptorTableDelete(DescType type, u64 asset_id); // ::Vulkan::CleanUp::Functions::Header:: diff --git a/src/renderer_vulkan_public.c b/src/renderer_vulkan_public.c index 1358c25..6b14069 100644 --- a/src/renderer_vulkan_public.c +++ b/src/renderer_vulkan_public.c @@ -269,17 +269,39 @@ static void CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr) VkLoaderWake(); } -static DescHandle CreateAndUploadToTexture(TextureBuffer *buffer, rawptr ptr) +static DescHandle CreateAndUploadToTexture(TextureAsset asset_id) { - TicketMutLock(&renderer.upload_queues[DESC_TYPE_SAMPLER].ticket_mut); + DescHandle handle = 0; - u32 job_idx = JobQueueAdd(&renderer.upload_queues[DESC_TYPE_SAMPLER].job_queue, 1); - renderer.upload_queues[DESC_TYPE_SAMPLER].queued_textures[job_idx] = buffer; - renderer.upload_queues[DESC_TYPE_SAMPLER].data[job_idx] = ptr; + DescAssetInfo *info = DescriptorTableSearch(DESC_TYPE_SAMPLER, asset_id); + if (info == NULL) + { + Asset asset = AssetPackLoadTexture(asset_id); - TicketMutUnlock(&renderer.upload_queues[DESC_TYPE_SAMPLER].ticket_mut); + TextureBuffer *buffer = FLMemAlloc(sizeof(TextureBuffer)); + buffer->type = TEXTURE_BUFFER_TYPE_SAMPLER; + buffer->width = asset.texture_meta.w; + buffer->height = asset.texture_meta.h; + buffer->channels = asset.texture_meta.ch; - VkLoaderWake(); + TicketMutLock(&renderer.upload_queues[DESC_TYPE_SAMPLER].ticket_mut); + + u32 job_idx = JobQueueAdd(&renderer.upload_queues[DESC_TYPE_SAMPLER].job_queue, 1); + renderer.upload_queues[DESC_TYPE_SAMPLER].queued_textures[job_idx] = buffer; + renderer.upload_queues[DESC_TYPE_SAMPLER].data[job_idx] = asset.bytes; + + handle = DescriptorHandlePop(DESC_TYPE_SAMPLER); + + TicketMutUnlock(&renderer.upload_queues[DESC_TYPE_SAMPLER].ticket_mut); + + VkLoaderWake(); + } + else + { + handle = info->handle; + } + + return handle; } static void FreeBuffers(RenderBuffer *buffers, u32 buffer_count) @@ -327,14 +349,22 @@ static AssetHandle RendererLoadTexture(TextureAsset asset_id) static void WaitForBufferQueue() { - JobQueueWaitForCompletion(&renderer.vk.imm.buffer_queue); - JobQueueWaitForCompletion(&renderer.vk.imm.texture_queue); + for (u32 i = 0; i < DESC_TYPE_MAX; i++) + { + while (!JobQueueCompleted(&renderer.upload_queues[DESC_TYPE_BUFFER].job_queue)) + { + if (renderer.vk_conf.sleeping_threads > 0) + VkLoaderWake(); + } + } } static void ResetBufferQueue() { - JobQueueReset(&renderer.vk.imm.texture_queue); - JobQueueReset(&renderer.vk.imm.buffer_queue); + for (u32 i = 0; i < DESC_TYPE_MAX; i++) + { + JobQueueReset(&renderer.upload_queues[i].job_queue); + } } // ::Vulkan::Renderer::Buffers::Functions::End:: diff --git a/src/util.c b/src/util.c index 51b793f..a249cff 100644 --- a/src/util.c +++ b/src/util.c @@ -304,13 +304,13 @@ static inline void EndProfileBlock(ProfileBlock *block) static inline b32 MutTryLock(Mut *mut) { - b32 lock = true; - return AtomicCompareExchangeb32(&mut->lock, &lock, false); + b32 lock = false; + return AtomicCompareExchangeb32(&mut->lock, &lock, 1); } static inline void MutUnlock(Mut *mut) { - AtomicStoreb32(&mut->lock, false); + AtomicStoreb32(&mut->lock, 0); } static inline void TicketMutLock(TicketMut *mut) @@ -353,12 +353,10 @@ static inline void JobQueueReset(JobQueue *queue) AtomicFetchSubu32(&queue->remaining, queue->remaining); } -static inline void JobQueueWaitForCompletion(JobQueue *queue) +static inline b32 JobQueueCompleted(JobQueue *queue) { - u32 remaining; - do { - remaining = AtomicLoadu32(&queue->remaining); - } while (remaining != 0); + u32 remaining = AtomicLoadu32(&queue->remaining); + return remaining == 0; } // ::Util::Async::Functions::End:: diff --git a/src/util.h b/src/util.h index f42e068..cc7db2a 100644 --- a/src/util.h +++ b/src/util.h @@ -57,12 +57,8 @@ typedef struct Arena Arena; DefSig##def(u16); \ DefSig##def(u32); \ DefSig##def(u64); \ - DefSig##def(f32); \ - DefSig##def(f64); \ DefSig##def(b8); \ - DefSig##def(b32); \ - DefSig##def(uintptr); \ - DefSig##def(intptr) + DefSig##def(b32) #define DefScalarImpl(def) \ Def##def(i8); \ @@ -73,12 +69,8 @@ typedef struct Arena Arena; Def##def(u16); \ Def##def(u32); \ Def##def(u64); \ - Def##def(f32); \ - Def##def(f64); \ Def##def(b8); \ - Def##def(b32); \ - Def##def(uintptr); \ - Def##def(intptr) + Def##def(b32) // ::Util::LinkedList::Macros:: @@ -273,4 +265,4 @@ static inline u32 JobQueueAdd(JobQueue *queue, u32 count); static inline void JobQueueMarkUnqueued(JobQueue *queue, u32 count); static inline void JobQueueMarkCompleted(JobQueue *queue, u32 count); static inline void JobQueueReset(JobQueue *queue); -static inline void JobQueueWaitForCompletion(JobQueue *queue); +static inline b32 JobQueueCompleted(JobQueue *queue); diff --git a/src/vulkan_config.c b/src/vulkan_config.c index 85b953f..f737ded 100644 --- a/src/vulkan_config.c +++ b/src/vulkan_config.c @@ -88,14 +88,6 @@ static VkPhysicalDeviceVulkan11Features vk_11_features = { .pNext = &vk_12_features }; -static const VkPhysicalDeviceFeatures vk_features = { - .shaderUniformBufferArrayDynamicIndexing = VK_TRUE, - .shaderSampledImageArrayDynamicIndexing = VK_TRUE, - .shaderStorageBufferArrayDynamicIndexing = VK_TRUE, - .shaderStorageImageArrayDynamicIndexing = VK_TRUE, - .samplerAnisotropy = VK_TRUE, -}; - static const VkPhysicalDeviceFeatures2 vk_features_2 = { .sType = STYPE(PHYSICAL_DEVICE_FEATURES_2), .pNext = &vk_11_features, @@ -103,7 +95,8 @@ static const VkPhysicalDeviceFeatures2 vk_features_2 = { .shaderUniformBufferArrayDynamicIndexing = VK_TRUE, .shaderSampledImageArrayDynamicIndexing = VK_TRUE, .shaderStorageBufferArrayDynamicIndexing = VK_TRUE, - .shaderStorageImageArrayDynamicIndexing = VK_TRUE + .shaderStorageImageArrayDynamicIndexing = VK_TRUE, + .samplerAnisotropy = VK_TRUE, }, };