abstract ticket mutexes

This commit is contained in:
Matthew 2025-04-23 09:31:20 +10:00
parent 963554cd85
commit 45b8f96d34
14 changed files with 174 additions and 108 deletions

View File

@ -228,8 +228,6 @@ static void FreeListInit(FLAlloc *alloc, usize size)
alloc->lists = MemAllocZeroed(sizeof(FreeList *) * 16); alloc->lists = MemAllocZeroed(sizeof(FreeList *) * 16);
alloc->list_count = 1; alloc->list_count = 1;
alloc->list_capacity = 16; alloc->list_capacity = 16;
alloc->ticket = 0;
alloc->next_ticket = 0;
alloc->nil = &FL_NIL_NODE; alloc->nil = &FL_NIL_NODE;
alloc->grow_size = size; alloc->grow_size = size;
@ -248,8 +246,7 @@ static void _FreeListInit(FreeList **alloc, usize size)
static void FreeListFreeAll(FLAlloc *alloc) static void FreeListFreeAll(FLAlloc *alloc)
{ {
u32 ticket = __atomic_fetch_add(&alloc->ticket, 1, __ATOMIC_SEQ_CST); TicketMutLock(&alloc->mut);
while (ticket != alloc->next_ticket);
if (alloc->list_count > 1) if (alloc->list_count > 1)
{ {
@ -269,9 +266,7 @@ static void FreeListFreeAll(FLAlloc *alloc)
alloc->lists[0]->head = node; alloc->lists[0]->head = node;
alloc->lists[0]->used = sizeof(FreeList); alloc->lists[0]->used = sizeof(FreeList);
__atomic_thread_fence(__ATOMIC_RELEASE); TicketMutUnlock(&alloc->mut);
__atomic_fetch_add(&alloc->next_ticket, 1, __ATOMIC_SEQ_CST);
} }
static FLNode *FreeListSearch(FreeList *alloc, usize size, usize alignment, usize *out_padding, FLNode **prev_node) 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); GlobalFreeListInit(FL_GLOBAL_SIZE);
} }
u32 ticket = __atomic_fetch_add(&alloc->ticket, 1, __ATOMIC_SEQ_CST); TicketMutLock(&alloc->mut);
while (ticket != alloc->next_ticket);
FreeList *fl = NULL; FreeList *fl = NULL;
for (u32 i = 0; i < alloc->list_count; i++) 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); rawptr ptr = _FreeListAllocAlign(fl, size, alignment);
__atomic_thread_fence(__ATOMIC_RELEASE); TicketMutUnlock(&alloc->mut);
__atomic_add_fetch(&alloc->next_ticket, 1, __ATOMIC_SEQ_CST);
return ptr; return ptr;
} }
@ -443,8 +435,7 @@ static void FreeListFree(FLAlloc *alloc, rawptr ptr)
{ {
if (ptr == NULL) return; if (ptr == NULL) return;
u32 ticket = __atomic_fetch_add(&alloc->ticket, 1, __ATOMIC_SEQ_CST); TicketMutLock(&alloc->mut);
while (ticket != alloc->next_ticket);
for (u32 i = 0; i < alloc->list_count; i++) 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) static void FreeListCoalescence(FreeList *alloc, FLNode *prev_node, FLNode *free_node)

View File

@ -84,10 +84,9 @@ typedef struct FreeList
typedef struct FLAlloc typedef struct FLAlloc
{ {
FreeList **lists; FreeList **lists;
TicketMut mut;
u32 list_count; u32 list_count;
u32 list_capacity; u32 list_capacity;
u32 volatile ticket;
u32 volatile next_ticket;
FLNode *nil; FLNode *nil;
usize grow_size; usize grow_size;
} FLAlloc; } FLAlloc;

View File

@ -14,6 +14,10 @@ static Asset Texture_Asset_Lookup[TEXTURE_ASSET_MAX];
static AssetFile Shader_Assets[SHADER_ASSET_MAX]; static AssetFile Shader_Assets[SHADER_ASSET_MAX];
static Asset Shader_Asset_Lookup[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; static b32 ASSET_HEADER_LOADED = false;
@ -42,7 +46,7 @@ static void LoadAssetPackHeader()
// ::Assets::Loading::Functions::Start:: // ::Assets::Loading::Functions::Start::
static Asset LoadTextureAsset(TextureAsset asset_id) static Asset AssetPackLoadTexture(TextureAsset asset_id)
{ {
if (!ASSET_HEADER_LOADED) if (!ASSET_HEADER_LOADED)
{ {
@ -74,7 +78,7 @@ static Asset LoadTextureAsset(TextureAsset asset_id)
return asset; return asset;
} }
static Asset LoadShaderAsset(ShaderAsset asset_id) static Asset AssetPackLoadShader(ShaderAsset asset_id)
{ {
if (!ASSET_HEADER_LOADED) if (!ASSET_HEADER_LOADED)
{ {
@ -96,7 +100,7 @@ static Asset LoadShaderAsset(ShaderAsset asset_id)
return asset; return asset;
} }
static void UnloadTextureAsset(Asset asset) static void AssetPackUnloadTexture(Asset asset)
{ {
Assert(asset.bytes != NULL, "UnloadTextureAsset assert failure: ptr is NULL"); 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].bytes = NULL;
Texture_Asset_Lookup[i].len = 0; Texture_Asset_Lookup[i].len = 0;
stbi_image_free(asset.bytes); stbi_image_free(asset.bytes);
break; break;
} }
} }
} }
static void UnloadShaderAsset(Asset asset) static void AssetPackUnloadShader(Asset asset)
{ {
Assert(asset.bytes != NULL, "UnloadShaderAsset assert failure: ptr is NULL"); 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].bytes = NULL;
Shader_Asset_Lookup[i].len = 0; Shader_Asset_Lookup[i].len = 0;
FLMemFree(asset.bytes); FLMemFree(asset.bytes);
break; break;
} }
} }

View File

@ -101,10 +101,19 @@ typedef struct FileHeader
u64 asset_offsets[ASSET_TYPE_MAX]; u64 asset_offsets[ASSET_TYPE_MAX];
} FileHeader; } FileHeader;
// ::Assets::Init::Functions::Header::
static void AssetPackLoadHeader();
// ::Assets::Loading::Functions::Header:: // ::Assets::Loading::Functions::Header::
static void LoadAssetPackHeader(); static Asset AssetPackLoadTexture(TextureAsset asset_id);
static Asset LoadTextureAsset(TextureAsset asset_id); static Asset AssetPackLoadShader(ShaderAsset asset_id);
static Asset LoadShaderAsset(ShaderAsset asset_id); static void AssetPackUnloadTexture(Asset asset);
static void UnloadTextureAsset(Asset asset); static void AssetPackUnloadShader(Asset asset);
static void UnloadShaderAsset(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);

View File

@ -70,3 +70,8 @@ b8 DirVisible(c8 *dir_name);
static u64 GetOSTimerFreq(); static u64 GetOSTimerFreq();
static u64 ReadOSTimer(); static u64 ReadOSTimer();
static inline u64 ReadCPUTimer(); static inline u64 ReadCPUTimer();
// ::Platform::Atomics::Header::
static inline u32 AtomicFetchIncrU32(u32 *ptr);
static inline void AtomicIncrU32(u32 *ptr);

View File

@ -329,3 +329,19 @@ static inline u64 ReadCPUTimer()
} }
// ::Platform::Profiling::Functions::End:: // ::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::

View File

@ -2,7 +2,7 @@
// ::Renderer::Declarations::Header:: // ::Renderer::Declarations::Header::
typedef u16 DescHandle; typedef u32 DescHandle;
// @requirement RenderBuffer type; // @requirement RenderBuffer type;
// @requirement u32 size; // @requirement u32 size;
@ -50,6 +50,8 @@ typedef struct RenderBuffers
u32 len; u32 len;
} RenderBuffers; } RenderBuffers;
typedef u32 AssetHandle;
// ::Renderer::Initialization::Header:: // ::Renderer::Initialization::Header::
b32 InitRenderer(Arena *arena); 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 CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr);
static void BindVertexBuffer(RenderBuffer *buffer); static void BindVertexBuffer(RenderBuffer *buffer);
static void BindIndexBuffer(RenderBuffer *buffer); static void BindIndexBuffer(RenderBuffer *buffer);
static AssetHandle RendererLoadTexture(TextureAsset asset_id);
// ::Renderer::Uniforms::Header:: // ::Renderer::Uniforms::Header::
// ::Renderer::PushConstants::Header:: // ::Renderer::PushConstants::Header::

View File

@ -11,9 +11,6 @@ static Renderer renderer = {
.color_space = INT_MAX, .color_space = INT_MAX,
.present_mode = 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:: // ::Vulkan::Init::Functions::Start::
static b32 CreateVmaAllocator() static b32 CreateVmaAllocator()
@ -1045,7 +1075,8 @@ static b32 CreateDescriptors()
{ {
bindings[i].free = ArenaAlloc(renderer.perm_arena, sizeof(u16) * DESC_MAX_BINDINGS); 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].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; u16 free_count = 0;
for (i32 j = DESC_MAX_BINDINGS-1; j >= 0; j--) for (i32 j = DESC_MAX_BINDINGS-1; j >= 0; j--)
@ -1056,6 +1087,7 @@ static b32 CreateDescriptors()
bindings[i].free_count = free_count; bindings[i].free_count = free_count;
} }
return success; return success;
} }
@ -1065,8 +1097,8 @@ static b32 CreatePipelines()
VkResult result; VkResult result;
VkDevice device = renderer.vk.device; VkDevice device = renderer.vk.device;
Asset quad_vert_shader = LoadShaderAsset(QUAD_VERT_SPIRV_SHADER); Asset quad_vert_shader = AssetPackLoadShader(QUAD_VERT_SPIRV_SHADER);
Asset quad_frag_shader = LoadShaderAsset(QUAD_FRAG_SPIRV_SHADER); Asset quad_frag_shader = AssetPackLoadShader(QUAD_FRAG_SPIRV_SHADER);
VkShaderModule cube_vert, cube_frag; VkShaderModule cube_vert, cube_frag;
success &= CreateShaderModule(quad_vert_shader.bytes, quad_vert_shader.len, &cube_vert); 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_vert, NULL);
vkDestroyShaderModule(device, cube_frag, NULL); vkDestroyShaderModule(device, cube_frag, NULL);
UnloadShaderAsset(quad_vert_shader); AssetPackUnloadShader(quad_vert_shader);
UnloadShaderAsset(quad_frag_shader); AssetPackUnloadShader(quad_frag_shader);
Asset gui_vert_shader = LoadShaderAsset(GUI_VERT_SPIRV_SHADER); Asset gui_vert_shader = AssetPackLoadShader(GUI_VERT_SPIRV_SHADER);
Asset gui_frag_shader = LoadShaderAsset(GUI_FRAG_SPIRV_SHADER); Asset gui_frag_shader = AssetPackLoadShader(GUI_FRAG_SPIRV_SHADER);
VkShaderModule gui_vert, gui_frag; VkShaderModule gui_vert, gui_frag;
success &= CreateShaderModule(gui_vert_shader.bytes, gui_vert_shader.len, &gui_vert); 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_vert, NULL);
vkDestroyShaderModule(device, gui_frag, NULL); vkDestroyShaderModule(device, gui_frag, NULL);
UnloadShaderAsset(gui_vert_shader); AssetPackUnloadShader(gui_vert_shader);
UnloadShaderAsset(gui_frag_shader); AssetPackUnloadShader(gui_frag_shader);
return success; return success;
} }
@ -1216,20 +1248,17 @@ void *VkLoaderStart(void *i)
for (;;) for (;;)
{ {
// TODO: Benchmark and test with __ATOMIC_RELEASE TicketMutLock(&renderer.vk.imm.mut);
u32 ticket = __atomic_add_fetch(&renderer.vk.imm.ticket, 1, __ATOMIC_SEQ_CST);
while (ticket != renderer.vk.imm.next_ticket);
u32 job_count = __atomic_load_n(&renderer.vk.imm.job_count, __ATOMIC_SEQ_CST); u32 job_count = __atomic_load_n(&renderer.vk.imm.job_count, __ATOMIC_SEQ_CST);
if (job_count < 0) 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); pthread_exit(NULL);
} }
else if (job_count == 0) 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_mutex_lock(&mut);
pthread_cond_wait(&cond, &mut); pthread_cond_wait(&cond, &mut);
pthread_mutex_unlock(&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_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++) for (u32 i = 0; i < count; i++)
Assert(CreateBuffer(buffers[i]), "VkLoader CreateBuffer failure"); Assert(CreateBuffer(buffers[i]), "VkLoader CreateBuffer failure");
Assert(UploadToBuffer(buffers, data, count, index), "VkLoader UploadToBuffer 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);
} }
} }
} }

View File

@ -205,13 +205,24 @@ typedef struct GlobalUniforms
f32 res[2]; f32 res[2];
} GlobalUniforms; } GlobalUniforms;
typedef struct DescAssetInfo
{
DescHandle handle;
DescType type;
union
{
u64 asset_id;
TextureAsset texture_id;
};
} DescAssetInfo;
typedef struct DescBindings typedef struct DescBindings
{ {
u16 *free; u16 *free;
u16 free_count; u16 free_count;
u16 *used; u16 *used;
u16 used_count; u16 used_count;
DescHandle *handle_indices; HashTable lookup_table;
} DescBindings; } DescBindings;
typedef struct PipelineStructures typedef struct PipelineStructures
@ -228,6 +239,7 @@ typedef struct PipelineStructures
typedef struct PushConst typedef struct PushConst
{ {
Vec2 res; Vec2 res;
Vec2 img_res;
} PushConst; } PushConst;
typedef struct FrameStructures typedef struct FrameStructures
@ -250,8 +262,7 @@ typedef struct ImmediateStructures
rawptr *data; rawptr *data;
i32 volatile job_count; i32 volatile job_count;
i32 volatile remaining_count; i32 volatile remaining_count;
u32 volatile ticket; TicketMut mut;
u32 volatile next_ticket;
} ImmediateStructures; } ImmediateStructures;
typedef struct DeviceQueues typedef struct DeviceQueues
@ -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); static inline void CopyImageToImage(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent2D dst_ext);
// ::Vulkan::Async::Functions::Header:: // ::Vulkan::Async::Functions::Header::
#ifdef __linux__ #ifdef __linux__
void *VkLoaderStart(void *thread_data); void *VkLoaderStart(void *thread_data);
#elif _WIN32 #elif _WIN32
@ -404,15 +416,19 @@ static b32 FinishImmSubmit(VkDevice device, VkFence *fence, VkCommandBuffer cmd,
static void BeginRendering(); 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:: // ::Vulkan::CleanUp::Functions::Header::
static void DestroySwapchain(); static void DestroySwapchain();
static void DestroyDrawImages(); static void DestroyDrawImages();
// ::Vulkan::Swapchain::Functions::Header::
static void ResizeSwapchain();
// ::Vulkan::Logging::Functions::Header:: // ::Vulkan::Logging::Functions::Header::
static void VkInfo(const char *str); static void VkInfo(const char *str);

View File

@ -251,48 +251,6 @@ static b32 UploadToBuffer(RenderBuffer **buffers, rawptr *ptrs, u32 count, u8 th
vmaUnmapMemory(alloc, staging_buffers[i].alloc); vmaUnmapMemory(alloc, staging_buffers[i].alloc);
vmaDestroyBuffer(alloc, staging_buffers[i].buffer, 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; return success;
} }
@ -302,9 +260,7 @@ static void CreateAndUploadToBuffer(RenderBuffer *buffer, rawptr ptr)
// TODO: revisit this to see if it could be done better // 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"); 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); TicketMutLock(&renderer.vk.imm.mut);
while (ticket != renderer.vk.imm.next_ticket);
u32 i = __atomic_fetch_add(&renderer.vk.imm.job_count, 1, __ATOMIC_SEQ_CST); 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); __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.queued_buffers[i] = buffer;
renderer.vk.imm.data[i] = ptr; renderer.vk.imm.data[i] = ptr;
__atomic_thread_fence(__ATOMIC_RELEASE); TicketMutUnlock(&renderer.vk.imm.mut);
__atomic_add_fetch(&renderer.vk.imm.next_ticket, 1, __ATOMIC_SEQ_CST);
} }
static void FreeBuffers(RenderBuffer *buffers, u32 buffer_count) 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); 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:: // ::Vulkan::Renderer::Buffers::Functions::End::

View File

@ -272,6 +272,7 @@ typedef struct GUIVertex
Vec2 p0; Vec2 p0;
Vec2 p1; Vec2 p1;
Vec4 col; Vec4 col;
u32 tex_idx;
} GUIVertex; } GUIVertex;
typedef struct GUIContext typedef struct GUIContext

View File

@ -297,3 +297,20 @@ static inline void EndProfileBlock(ProfileBlock *block)
} }
// ::Util::Profiling::Functions::End:: // ::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::

View File

@ -233,3 +233,14 @@ typedef struct Profiler
static inline void StartProfileBlock(ProfileBlock *block, c8 *label, u32 anchor_index); static inline void StartProfileBlock(ProfileBlock *block, c8 *label, u32 anchor_index);
static inline void EndProfileBlock(ProfileBlock *block); 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);

View File

@ -437,6 +437,7 @@ VkVertexInputAttributeDescription gui_input_descriptions[] = {
{ .binding = 0, .location = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = 0 }, { .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 = 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 = 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 = { VkPipelineVertexInputStateCreateInfo gui_vertex_input_info = {