diff --git a/src/allocators.c b/src/allocators.c index 7ea1a31..a124e7a 100644 --- a/src/allocators.c +++ b/src/allocators.c @@ -228,8 +228,6 @@ static void FreeListInit(FLAlloc *alloc, usize size) alloc->lists = MemAllocZeroed(sizeof(FreeList *) * 16); alloc->list_count = 1; alloc->list_capacity = 16; - alloc->ticket = 0; - alloc->next_ticket = 0; alloc->nil = &FL_NIL_NODE; alloc->grow_size = size; @@ -248,8 +246,7 @@ static void _FreeListInit(FreeList **alloc, usize size) static void FreeListFreeAll(FLAlloc *alloc) { - u32 ticket = __atomic_fetch_add(&alloc->ticket, 1, __ATOMIC_SEQ_CST); - while (ticket != alloc->next_ticket); + TicketMutLock(&alloc->mut); if (alloc->list_count > 1) { @@ -269,9 +266,7 @@ static void FreeListFreeAll(FLAlloc *alloc) alloc->lists[0]->head = node; alloc->lists[0]->used = sizeof(FreeList); - __atomic_thread_fence(__ATOMIC_RELEASE); - - __atomic_fetch_add(&alloc->next_ticket, 1, __ATOMIC_SEQ_CST); + TicketMutUnlock(&alloc->mut); } static FLNode *FreeListSearch(FreeList *alloc, usize size, usize alignment, usize *out_padding, FLNode **prev_node) @@ -384,8 +379,7 @@ static rawptr FreeListAllocAlign(FLAlloc *alloc, usize size, usize alignment) GlobalFreeListInit(FL_GLOBAL_SIZE); } - u32 ticket = __atomic_fetch_add(&alloc->ticket, 1, __ATOMIC_SEQ_CST); - while (ticket != alloc->next_ticket); + TicketMutLock(&alloc->mut); FreeList *fl = NULL; for (u32 i = 0; i < alloc->list_count; i++) @@ -406,9 +400,7 @@ static rawptr FreeListAllocAlign(FLAlloc *alloc, usize size, usize alignment) rawptr ptr = _FreeListAllocAlign(fl, size, alignment); - __atomic_thread_fence(__ATOMIC_RELEASE); - - __atomic_add_fetch(&alloc->next_ticket, 1, __ATOMIC_SEQ_CST); + TicketMutUnlock(&alloc->mut); return ptr; } @@ -443,8 +435,7 @@ static void FreeListFree(FLAlloc *alloc, rawptr ptr) { if (ptr == NULL) return; - u32 ticket = __atomic_fetch_add(&alloc->ticket, 1, __ATOMIC_SEQ_CST); - while (ticket != alloc->next_ticket); + TicketMutLock(&alloc->mut); for (u32 i = 0; i < alloc->list_count; i++) { @@ -458,7 +449,7 @@ static void FreeListFree(FLAlloc *alloc, rawptr ptr) } } - __atomic_fetch_add(&alloc->next_ticket, 1, __ATOMIC_SEQ_CST); + TicketMutUnlock(&alloc->mut); } static void FreeListCoalescence(FreeList *alloc, FLNode *prev_node, FLNode *free_node) diff --git a/src/allocators.h b/src/allocators.h index d09f2e6..4ce9b50 100644 --- a/src/allocators.h +++ b/src/allocators.h @@ -83,13 +83,12 @@ typedef struct FreeList typedef struct FLAlloc { - FreeList **lists; - u32 list_count; - u32 list_capacity; - u32 volatile ticket; - u32 volatile next_ticket; - FLNode *nil; - usize grow_size; + FreeList **lists; + TicketMut mut; + u32 list_count; + u32 list_capacity; + FLNode *nil; + usize grow_size; } FLAlloc; static void GlobalFreeListInit(usize size); diff --git a/src/assets.c b/src/assets.c index 2ecc0d3..54d0c13 100644 --- a/src/assets.c +++ b/src/assets.c @@ -14,6 +14,10 @@ static Asset Texture_Asset_Lookup[TEXTURE_ASSET_MAX]; static AssetFile Shader_Assets[SHADER_ASSET_MAX]; static Asset Shader_Asset_Lookup[SHADER_ASSET_MAX]; +// TODO(MA): Implement async asset handling +static u32 Shader_Asset_Ref_Count[SHADER_ASSET_MAX]; +static u32 Texture_Asset_Ref_Count[TEXTURE_ASSET_MAX]; + static b32 ASSET_HEADER_LOADED = false; @@ -42,7 +46,7 @@ static void LoadAssetPackHeader() // ::Assets::Loading::Functions::Start:: -static Asset LoadTextureAsset(TextureAsset asset_id) +static Asset AssetPackLoadTexture(TextureAsset asset_id) { if (!ASSET_HEADER_LOADED) { @@ -74,7 +78,7 @@ static Asset LoadTextureAsset(TextureAsset asset_id) return asset; } -static Asset LoadShaderAsset(ShaderAsset asset_id) +static Asset AssetPackLoadShader(ShaderAsset asset_id) { if (!ASSET_HEADER_LOADED) { @@ -96,7 +100,7 @@ static Asset LoadShaderAsset(ShaderAsset asset_id) return asset; } -static void UnloadTextureAsset(Asset asset) +static void AssetPackUnloadTexture(Asset asset) { Assert(asset.bytes != NULL, "UnloadTextureAsset assert failure: ptr is NULL"); @@ -107,12 +111,13 @@ static void UnloadTextureAsset(Asset asset) Texture_Asset_Lookup[i].bytes = NULL; Texture_Asset_Lookup[i].len = 0; stbi_image_free(asset.bytes); + break; } } } -static void UnloadShaderAsset(Asset asset) +static void AssetPackUnloadShader(Asset asset) { Assert(asset.bytes != NULL, "UnloadShaderAsset assert failure: ptr is NULL"); @@ -123,6 +128,7 @@ static void UnloadShaderAsset(Asset asset) Shader_Asset_Lookup[i].bytes = NULL; Shader_Asset_Lookup[i].len = 0; FLMemFree(asset.bytes); + break; } } diff --git a/src/assets.h b/src/assets.h index a32e307..7894cfe 100644 --- a/src/assets.h +++ b/src/assets.h @@ -101,10 +101,19 @@ typedef struct FileHeader u64 asset_offsets[ASSET_TYPE_MAX]; } FileHeader; +// ::Assets::Init::Functions::Header:: + +static void AssetPackLoadHeader(); + // ::Assets::Loading::Functions::Header:: -static void LoadAssetPackHeader(); -static Asset LoadTextureAsset(TextureAsset asset_id); -static Asset LoadShaderAsset(ShaderAsset asset_id); -static void UnloadTextureAsset(Asset asset); -static void UnloadShaderAsset(Asset asset); +static Asset AssetPackLoadTexture(TextureAsset asset_id); +static Asset AssetPackLoadShader(ShaderAsset asset_id); +static void AssetPackUnloadTexture(Asset asset); +static void AssetPackUnloadShader(Asset asset); + +// ::Assets::Util::Functions::Header:: + +// TODO(MA): Implement async asset handling +static inline b32 AssetPackMarkUnloaded(AssetType type, u32 index); +static inline void AssetPackMarkLoaded(AssetType type, u32 index); diff --git a/src/platform/platform.h b/src/platform/platform.h index fc53a0d..a7edf32 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -70,3 +70,8 @@ b8 DirVisible(c8 *dir_name); static u64 GetOSTimerFreq(); static u64 ReadOSTimer(); static inline u64 ReadCPUTimer(); + +// ::Platform::Atomics::Header:: + +static inline u32 AtomicFetchIncrU32(u32 *ptr); +static inline void AtomicIncrU32(u32 *ptr); diff --git a/src/platform/platform_linux_public.c b/src/platform/platform_linux_public.c index ffe1fdd..6f6ec15 100644 --- a/src/platform/platform_linux_public.c +++ b/src/platform/platform_linux_public.c @@ -329,3 +329,19 @@ static inline u64 ReadCPUTimer() } // ::Platform::Profiling::Functions::End:: + + + +// ::Platform::Atomics::Functions::Start:: + +static inline u32 AtomicFetchIncrU32(u32 *ptr) +{ + return __atomic_fetch_add(ptr, 1, __ATOMIC_ACQUIRE); +} + +static inline void AtomicIncrU32(u32 *ptr) +{ + __atomic_fetch_add(ptr, 1, __ATOMIC_RELEASE); +} + +// ::Platform::Atomics::Functions::End:: diff --git a/src/renderer.h b/src/renderer.h index 013f7ba..36a22d2 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -2,7 +2,7 @@ // ::Renderer::Declarations::Header:: -typedef u16 DescHandle; +typedef u32 DescHandle; // @requirement RenderBuffer type; // @requirement u32 size; @@ -50,6 +50,8 @@ typedef struct RenderBuffers u32 len; } RenderBuffers; +typedef u32 AssetHandle; + // ::Renderer::Initialization::Header:: b32 InitRenderer(Arena *arena); @@ -63,6 +65,7 @@ static b32 UploadToBuffer(RenderBuffer **buffer, rawptr *ptr, u32 count, u8 thr_ static void CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr); static void BindVertexBuffer(RenderBuffer *buffer); static void BindIndexBuffer(RenderBuffer *buffer); +static AssetHandle RendererLoadTexture(TextureAsset asset_id); // ::Renderer::Uniforms::Header:: // ::Renderer::PushConstants::Header:: diff --git a/src/renderer_vulkan.c b/src/renderer_vulkan.c index 4bc46cd..03d4662 100644 --- a/src/renderer_vulkan.c +++ b/src/renderer_vulkan.c @@ -11,9 +11,6 @@ static Renderer renderer = { .color_space = INT_MAX, .present_mode = INT_MAX, }, - .imm = { - .next_ticket = 1, - }, } }; @@ -318,6 +315,39 @@ static void ResizeSwapchain() +// ::Vulkan::Descriptors::Functions::Start:: + +static DescAssetInfo *DescriptorTableSearch(DescType type, u64 asset_id) +{ + DescAssetInfo *asset_info = NULL; + + HashTable *table = &renderer.vk.pipe.bindings[type].lookup_table; + + KeyValuePair *kv_pair = HashTableSearchU64(table, asset_id); + if (kv_pair != NULL) + { + asset_info = (DescAssetInfo *)kv_pair->value_rawptr; + } + + return asset_info; +} + +static void DescriptorTableInsert(DescType type, u64 asset_id, DescHandle handle) +{ + DescAssetInfo *asset_info = FLMemAlloc(sizeof(DescAssetInfo)); + + asset_info->handle = handle; + asset_info->type = type; + asset_info->asset_id = asset_id; + + HashTable *table = &renderer.vk.pipe.bindings[type].lookup_table; + HashTablePushU64Rawptr(table, asset_id, asset_info); +} + +// ::Vulkan::Descriptors::Functions::End:: + + + // ::Vulkan::Init::Functions::Start:: static b32 CreateVmaAllocator() @@ -1045,7 +1075,8 @@ static b32 CreateDescriptors() { 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].handle_indices = ArenaAlloc(renderer.perm_arena, sizeof(DescHandle) * DESC_MAX_BINDINGS); + + HashTableInit(&bindings[i].lookup_table, 6); u16 free_count = 0; for (i32 j = DESC_MAX_BINDINGS-1; j >= 0; j--) @@ -1056,6 +1087,7 @@ static b32 CreateDescriptors() bindings[i].free_count = free_count; } + return success; } @@ -1065,8 +1097,8 @@ static b32 CreatePipelines() VkResult result; VkDevice device = renderer.vk.device; - Asset quad_vert_shader = LoadShaderAsset(QUAD_VERT_SPIRV_SHADER); - Asset quad_frag_shader = LoadShaderAsset(QUAD_FRAG_SPIRV_SHADER); + Asset quad_vert_shader = AssetPackLoadShader(QUAD_VERT_SPIRV_SHADER); + Asset quad_frag_shader = AssetPackLoadShader(QUAD_FRAG_SPIRV_SHADER); VkShaderModule cube_vert, cube_frag; success &= CreateShaderModule(quad_vert_shader.bytes, quad_vert_shader.len, &cube_vert); @@ -1109,11 +1141,11 @@ static b32 CreatePipelines() vkDestroyShaderModule(device, cube_vert, NULL); vkDestroyShaderModule(device, cube_frag, NULL); - UnloadShaderAsset(quad_vert_shader); - UnloadShaderAsset(quad_frag_shader); + AssetPackUnloadShader(quad_vert_shader); + AssetPackUnloadShader(quad_frag_shader); - Asset gui_vert_shader = LoadShaderAsset(GUI_VERT_SPIRV_SHADER); - Asset gui_frag_shader = LoadShaderAsset(GUI_FRAG_SPIRV_SHADER); + Asset gui_vert_shader = AssetPackLoadShader(GUI_VERT_SPIRV_SHADER); + Asset gui_frag_shader = AssetPackLoadShader(GUI_FRAG_SPIRV_SHADER); VkShaderModule gui_vert, gui_frag; success &= CreateShaderModule(gui_vert_shader.bytes, gui_vert_shader.len, &gui_vert); @@ -1149,8 +1181,8 @@ static b32 CreatePipelines() vkDestroyShaderModule(device, gui_vert, NULL); vkDestroyShaderModule(device, gui_frag, NULL); - UnloadShaderAsset(gui_vert_shader); - UnloadShaderAsset(gui_frag_shader); + AssetPackUnloadShader(gui_vert_shader); + AssetPackUnloadShader(gui_frag_shader); return success; } @@ -1216,20 +1248,17 @@ void *VkLoaderStart(void *i) for (;;) { - // TODO: Benchmark and test with __ATOMIC_RELEASE - u32 ticket = __atomic_add_fetch(&renderer.vk.imm.ticket, 1, __ATOMIC_SEQ_CST); - - while (ticket != renderer.vk.imm.next_ticket); + TicketMutLock(&renderer.vk.imm.mut); u32 job_count = __atomic_load_n(&renderer.vk.imm.job_count, __ATOMIC_SEQ_CST); if (job_count < 0) { - __atomic_store_n(&renderer.vk.imm.next_ticket, renderer.vk.imm.next_ticket+1, __ATOMIC_SEQ_CST); + TicketMutUnlock(&renderer.vk.imm.mut); pthread_exit(NULL); } else if (job_count == 0) { - __atomic_store_n(&renderer.vk.imm.next_ticket, renderer.vk.imm.next_ticket+1, __ATOMIC_SEQ_CST); + TicketMutUnlock(&renderer.vk.imm.mut); pthread_mutex_lock(&mut); pthread_cond_wait(&cond, &mut); pthread_mutex_unlock(&mut); @@ -1247,14 +1276,15 @@ void *VkLoaderStart(void *i) } __atomic_sub_fetch(&renderer.vk.imm.job_count, count, __ATOMIC_SEQ_CST); - __atomic_store_n(&renderer.vk.imm.next_ticket, renderer.vk.imm.next_ticket+1, __ATOMIC_SEQ_CST); + + TicketMutUnlock(&renderer.vk.imm.mut); for (u32 i = 0; i < count; i++) Assert(CreateBuffer(buffers[i]), "VkLoader CreateBuffer failure"); Assert(UploadToBuffer(buffers, data, count, index), "VkLoader UploadToBuffer failure"); - u32 rem = __atomic_sub_fetch(&renderer.vk.imm.remaining_count, count, __ATOMIC_SEQ_CST); + u32 rem = __atomic_sub_fetch(&renderer.vk.imm.remaining_count, count, __ATOMIC_RELEASE); } } } diff --git a/src/renderer_vulkan.h b/src/renderer_vulkan.h index cfcb2a3..5014e93 100644 --- a/src/renderer_vulkan.h +++ b/src/renderer_vulkan.h @@ -205,13 +205,24 @@ typedef struct GlobalUniforms f32 res[2]; } GlobalUniforms; +typedef struct DescAssetInfo +{ + DescHandle handle; + DescType type; + union + { + u64 asset_id; + TextureAsset texture_id; + }; +} DescAssetInfo; + typedef struct DescBindings { u16 *free; u16 free_count; u16 *used; u16 used_count; - DescHandle *handle_indices; + HashTable lookup_table; } DescBindings; typedef struct PipelineStructures @@ -228,6 +239,7 @@ typedef struct PipelineStructures typedef struct PushConst { Vec2 res; + Vec2 img_res; } PushConst; typedef struct FrameStructures @@ -250,8 +262,7 @@ typedef struct ImmediateStructures rawptr *data; i32 volatile job_count; i32 volatile remaining_count; - u32 volatile ticket; - u32 volatile next_ticket; + TicketMut mut; } ImmediateStructures; typedef struct DeviceQueues @@ -332,7 +343,7 @@ typedef struct VulkanConfig typedef struct Renderer { - Vulkan vk; + Vulkan vk; VulkanConfig vk_conf; FrameState frame_state; PendingUpdates pending; @@ -389,6 +400,7 @@ static inline void TransitionImageLayout(VkCommandBuffer cmd, VkImage img, VkIma static inline void CopyImageToImage(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent2D dst_ext); // ::Vulkan::Async::Functions::Header:: + #ifdef __linux__ void *VkLoaderStart(void *thread_data); #elif _WIN32 @@ -404,15 +416,19 @@ static b32 FinishImmSubmit(VkDevice device, VkFence *fence, VkCommandBuffer cmd, static void BeginRendering(); +// ::Vulkan::Swapchain::Functions::Header:: + +static void ResizeSwapchain(); + +// ::Vulkan::Descriptors::Functions::Header:: + +static DescAssetInfo *DescriptorTableSearch(DescType type, u64 asset_id); + // ::Vulkan::CleanUp::Functions::Header:: static void DestroySwapchain(); static void DestroyDrawImages(); -// ::Vulkan::Swapchain::Functions::Header:: - -static void ResizeSwapchain(); - // ::Vulkan::Logging::Functions::Header:: static void VkInfo(const char *str); diff --git a/src/renderer_vulkan_public.c b/src/renderer_vulkan_public.c index 3846011..0c5b585 100644 --- a/src/renderer_vulkan_public.c +++ b/src/renderer_vulkan_public.c @@ -251,48 +251,6 @@ static b32 UploadToBuffer(RenderBuffer **buffers, rawptr *ptrs, u32 count, u8 th vmaUnmapMemory(alloc, staging_buffers[i].alloc); vmaDestroyBuffer(alloc, staging_buffers[i].buffer, staging_buffers[i].alloc); } - /* - if (host_visible) - { - vmaMapMemory(alloc, buffer->alloc, &mapped_buffer); - MemCpy(mapped_buffer, ptr, buffer->size); - } - else - { - RenderBuffer staging_buffer = { .type = RENDER_BUFFER_TYPE_STAGING, .size = buffer->size }; - - success = CreateBuffer(&staging_buffer); - - b32 buffer_created = success; - - if (success) - { - vmaMapMemory(alloc, staging_buffer.alloc, &mapped_buffer); - MemCpy(mapped_buffer, ptr, staging_buffer.size); - } - - if (success) - success = BeginImmSubmit(device, &fence, cmd); - - b32 imm_started = success; - - if (success) - { - VkBufferCopy buffer_copy = { .size = (VkDeviceSize)buffer->size }; - Printfln("copy buffer: %d", buffer->buffer); - vkCmdCopyBuffer(cmd, staging_buffer.buffer, buffer->buffer, 1, &buffer_copy); - } - - if (imm_started) - FinishImmSubmit(device, &fence, cmd, queue); - - if (buffer_created) - { - vmaUnmapMemory(alloc, staging_buffer.alloc); - vmaDestroyBuffer(alloc, staging_buffer.buffer, staging_buffer.alloc); - } - } - */ return success; } @@ -302,9 +260,7 @@ static void CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr) // TODO: revisit this to see if it could be done better Assert(renderer.vk.imm.job_count+1 < BUFFER_QUEUE_LEN, "CreateAndUploadToBuffer out of bounds"); - u32 ticket = __atomic_add_fetch(&renderer.vk.imm.ticket, 1, __ATOMIC_SEQ_CST); - - while (ticket != renderer.vk.imm.next_ticket); + TicketMutLock(&renderer.vk.imm.mut); u32 i = __atomic_fetch_add(&renderer.vk.imm.job_count, 1, __ATOMIC_SEQ_CST); __atomic_fetch_add(&renderer.vk.imm.remaining_count, 1, __ATOMIC_SEQ_CST); @@ -312,9 +268,7 @@ static void CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr) renderer.vk.imm.queued_buffers[i] = buffer; renderer.vk.imm.data[i] = ptr; - __atomic_thread_fence(__ATOMIC_RELEASE); - - __atomic_add_fetch(&renderer.vk.imm.next_ticket, 1, __ATOMIC_SEQ_CST); + TicketMutUnlock(&renderer.vk.imm.mut); } static void FreeBuffers(RenderBuffer *buffers, u32 buffer_count) @@ -353,6 +307,13 @@ static void BindIndexBuffer(RenderBuffer *buffer) vkCmdBindIndexBuffer(cmd, buffer->buffer, 0, VK_INDEX_TYPE_UINT32); } +static AssetHandle RendererLoadTexture(TextureAsset asset_id) +{ + AssetHandle handle = 0; + + return handle; +} + // ::Vulkan::Renderer::Buffers::Functions::End:: diff --git a/src/shared_types.h b/src/shared_types.h index 111a767..bef0792 100644 --- a/src/shared_types.h +++ b/src/shared_types.h @@ -272,6 +272,7 @@ typedef struct GUIVertex Vec2 p0; Vec2 p1; Vec4 col; + u32 tex_idx; } GUIVertex; typedef struct GUIContext diff --git a/src/util.c b/src/util.c index a072ea7..36f7bca 100644 --- a/src/util.c +++ b/src/util.c @@ -297,3 +297,20 @@ static inline void EndProfileBlock(ProfileBlock *block) } // ::Util::Profiling::Functions::End:: + + + +// ::Util::Async::Functions::Start:: + +static inline void TicketMutLock(TicketMut *mut) +{ + u32 ticket = AtomicFetchIncrU32(&mut->ticket); + while (ticket != mut->next_ticket); +} + +static inline void TicketMutUnlock(TicketMut *mut) +{ + AtomicIncrU32(&mut->next_ticket); +} + +// ::Util::Async::Functions::End:: diff --git a/src/util.h b/src/util.h index d1dbc59..42d6b40 100644 --- a/src/util.h +++ b/src/util.h @@ -233,3 +233,14 @@ typedef struct Profiler static inline void StartProfileBlock(ProfileBlock *block, c8 *label, u32 anchor_index); static inline void EndProfileBlock(ProfileBlock *block); + +// ::Util::Async::Header:: + +typedef struct TicketMut +{ + u32 volatile ticket; + u32 volatile next_ticket; +} TicketMut; + +static inline void TicketMutLock(TicketMut *mut); +static inline void TicketMutUnlock(TicketMut *mut); diff --git a/src/vulkan_config.c b/src/vulkan_config.c index a9ed456..28ebae6 100644 --- a/src/vulkan_config.c +++ b/src/vulkan_config.c @@ -437,6 +437,7 @@ VkVertexInputAttributeDescription gui_input_descriptions[] = { { .binding = 0, .location = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = 0 }, { .binding = 0, .location = 1, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(GUIVertex, p1) }, { .binding = 0, .location = 2, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(GUIVertex, col) }, + { .binding = 0, .location = 3, .format = VK_FORMAT_R32_UINT, .offset = offsetof(GUIVertex, tex_idx) }, }; VkPipelineVertexInputStateCreateInfo gui_vertex_input_info = {