From 30153e1af38d14ecdeab32aed067ad0f7a9a06b8 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sun, 20 Apr 2025 16:51:44 +1000 Subject: [PATCH] convert math functions to generics --- src/allocators.c | 88 ++++++++++++++++++++++++++++++++----------- src/allocators.h | 25 ++++++------ src/ds.c | 55 +++++++++++++++++++++------ src/ds.h | 10 +++-- src/entry_linux.c | 11 +++++- src/renderer_vulkan.c | 4 +- src/util.c | 34 +++-------------- src/util.h | 60 ++++++++++++++++++++++++++--- 8 files changed, 199 insertions(+), 88 deletions(-) diff --git a/src/allocators.c b/src/allocators.c index 94d5c34..325469b 100644 --- a/src/allocators.c +++ b/src/allocators.c @@ -4,8 +4,6 @@ FLAlloc FL_ALLOC = {0}; Allocator ALLOC = {0}; read_only FLNode FL_NIL_NODE = {0}; -#define ALLOC_CAP 16 - // ::Allocator::Util::Header:: usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size) @@ -104,33 +102,64 @@ static Arena * ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no) static void InitAllocator(usize init_size) { - ALLOC.tree = FLMemAlloc(sizeof(RBTree)); - RBTreeInit(ALLOC.tree); + ALLOC.grow_size = init_size; + ALLOC.buffer = MemAllocZeroed(init_size); + ALLOC.size = init_size; + ALLOC.free_size = init_size; ALLOC.hash_table = FLMemAlloc(sizeof(HashTable)); HashTableInit(ALLOC.hash_table, 32); - ALLOC.buffers = FLMemAlloc(sizeof(FreeListBuffer) * ALLOC_CAP); - ALLOC.count = 1; - ALLOC.cap = ALLOC_CAP; - ALLOC.grow_size = init_size; + ALLOC.tree = FLMemAlloc(sizeof(RBTree)); + RBTreeInit(ALLOC.tree); + + AllocInfo *info = CreateAllocInfo(ALLOC.buffer); - InitAllocatorBuffer(&ALLOC.buffers[0], init_size); + RBTreeFindOrInsert(ALLOC.tree, init_size, info); } -static void InitAllocatorBuffer(FreeListBuffer *buffer, usize init_size) +static AllocInfo *CreateAllocInfo(rawptr ptr) { - buffer->buf = MemAllocZeroed(init_size); - buffer->size = init_size; - buffer->free_size = init_size; + AllocInfo *info = FLMemAlloc(sizeof(AllocInfo)); + info->ptrs = FLMemAlloc(sizeof(rawptr *)); + info->ptrs[0] = ptr; + info->count = 1; +} + +static void AllocInfoAdd(AllocInfo *info, rawptr ptr) +{ + rawptr *ptrs = FLMemAlloc(sizeof(rawptr) * (info->count+1)); + MemCpy(ptrs, info->ptrs, sizeof(rawptr) * (info->count+1)); + FLMemFree(info->ptrs); + info->ptrs = ptrs; +} + +static void AllocInfoRemove(AllocInfo *info, rawptr ptr) +{ + u32 index = UINT32_MAX; + for (u32 i = 0; i < info->count; i++) + { + if (info->ptrs[i] == ptr) + { + index = i; + break; + } + } + + Assert(index != UINT32_MAX, "AllocInfoRemove called with invalid pointer"); + + rawptr *ptrs = FLMemAlloc(sizeof(rawptr) * (info->count-1)); + MemCpy(ptrs, info->ptrs, index); + MemCpy(&ptrs[index], &info->ptrs[index+1], info->count-index-1); + + FLMemFree(info->ptrs); + info->ptrs = ptrs; + info->count -= 1; } static void DeinitAlloc() { - for (u8 i = 0; i < ALLOC.count; i++) - { - MemFree(ALLOC.buffers[i].buf, ALLOC.buffers[i].size); - } + MemFree(ALLOC.buffer, ALLOC.size); } static rawptr Alloc(usize size) @@ -140,19 +169,30 @@ static rawptr Alloc(usize size) static rawptr AllocAlign(usize size, usize alignment) { - return NULL; + if (size == 0) return NULL; + + usize padding = 0; + + if (alignment < 8) + alignment = 8; + + RBNode *node = NULL; + RBTreeSearch(ALLOC.tree, size, &node); } static void Free(rawptr ptr) { + if (ptr == NULL) return; + } -static void AllocGrow() +static void AllocGrow(usize size) { - Assert(ALLOC.count < ALLOC.cap, "Global allocator has reached capacity"); - InitAllocatorBuffer(&ALLOC.buffers[ALLOC.count], ALLOC.grow_size); - ALLOC.count += 1; + usize grow_size = size < ALLOC.grow_size ? ALLOC.grow_size : ALLOC.grow_size + size; + MemRealloc(ALLOC.buffer, ALLOC.size, ALLOC.size + grow_size); + ALLOC.size += grow_size; + ALLOC.free_size += grow_size; } // ::Allocator::GlobalAlloc::End:: @@ -171,7 +211,7 @@ static rawptr FLMemAlloc(usize size) return FreeListAlloc(&FL_ALLOC, size); } -static void FLFree(rawptr ptr) +static void FLMemFree(rawptr ptr) { FreeListFree(&FL_ALLOC, ptr); } @@ -285,6 +325,8 @@ static void FreeListGrow(FLAlloc *alloc, usize alloc_size) static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, u32 alignment) { + if (size == 0) return NULL; + usize padding = 0; FLNode *prev_node = &FL_NIL_NODE; diff --git a/src/allocators.h b/src/allocators.h index ce5b705..d18d8f0 100644 --- a/src/allocators.h +++ b/src/allocators.h @@ -32,27 +32,28 @@ static Arena *ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no); // ::Allocator::GlobalAlloc::Header:: -typedef struct FreeListBuffer +typedef struct AllocInfo { - rawptr buf; - u32 size; - u32 free_size; -} FreeListBuffer; + rawptr *ptrs; + u32 count; +} AllocInfo; typedef struct Allocator { RBTree *tree; - FreeListBuffer *buffers; HashTable *hash_table; - usize grow_size; - u64 count; - u64 cap; + rawptr buffer; + u64 size; + u64 free_size; + u64 grow_size; } Allocator; static void InitAllocator(usize init_size); -static void InitAllocatorBuffer(FreeListBuffer *buffer, usize init_size); +static AllocInfo *CreateAllocInfo(rawptr ptr); +static void AllocInfoAdd(AllocInfo *info, rawptr ptr); +static void AllocInfoRemove(AllocInfo *info, rawptr ptr); static void DeinitAlloc(); -static void AllocGrow(); +static void AllocGrow(usize size); static rawptr Alloc(usize size); static rawptr AllocAlign(usize size, usize alignment); static void Free(rawptr ptr); @@ -92,7 +93,7 @@ typedef struct FLAlloc static void GlobalFreeListInit(usize size); static rawptr FLMemAlloc(usize size); -static void FLFree(rawptr ptr); +static void FLMemFree(rawptr ptr); static void _FreeListInit(FreeList **alloc, usize size); static void FreeListInit(FLAlloc *alloc, usize size); static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, u32 alignment); diff --git a/src/ds.c b/src/ds.c index b6ed31d..06ab85b 100644 --- a/src/ds.c +++ b/src/ds.c @@ -21,8 +21,19 @@ static void RBTreeInit(RBTree *tree) tree->nil = P_RB_NIL; } -static RBNode *RBTreeFindOrInsert(RBTree *tree, RBNode *node) +static inline void RBTreeInitNode(RBNode *node, u32 key, rawptr value) { + node->parent = node->left = node->right = P_RB_NIL; + node->color = RB_BLACK; + node->key = key; + node->data = value; +} + +static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value) +{ + RBNode *node = FLMemAlloc(sizeof(RBNode)); + RBTreeInitNode(node, key, value); + RBNode *existing_node = P_RB_NIL; node->left = node->right = tree->nil; @@ -41,12 +52,12 @@ static RBNode *RBTreeFindOrInsert(RBTree *tree, RBNode *node) { Assert(curr_node != tree->nil, "Current Node is NIL"); - if (curr_node->value == node->value) + if (curr_node->key == node->key) { existing_node = curr_node; break; } - else if (curr_node->value < node->value) + else if (curr_node->key < node->key) { if (curr_node->right == tree->nil) { @@ -124,10 +135,10 @@ static void RBTreeCorrect(RBTree *tree, RBNode *node) } while ((p = node->parent)); } -static void RBTreeDelete(RBTree *tree, i32 value) +static void RBTreeDelete(RBTree *tree, u32 key) { RBNode *node = NULL; - Assert(RBTreeSearch(tree, value, &node), "Unable to find node in RBTreeDelete"); + Assert(RBTreeSearch(tree, key, &node), "Unable to find node in RBTreeDelete"); if (node == tree->root && node->left == tree->nil && node->right == tree->nil) { @@ -140,7 +151,7 @@ static void RBTreeDelete(RBTree *tree, i32 value) while (ln->left != tree->nil) ln = ln->left; - node->value = ln->value; + node->key = ln->key; node->data = ln->data; if (node->right == ln) @@ -152,13 +163,13 @@ static void RBTreeDelete(RBTree *tree, i32 value) } else if (node->color == RB_BLACK && node->left != tree->nil) { - node->value = node->left->value; + node->key = node->left->key; node->data = node->left->data; node->left = tree->nil; } else if (node->color == RB_BLACK && node->right != tree->nil) { - node->value = node->right->value; + node->key = node->right->key; node->data = node->right->data; node->right = tree->nil; } @@ -240,7 +251,29 @@ static void RBTreeDelete(RBTree *tree, i32 value) } } -static b32 RBTreeSearch(RBTree *tree, i32 value, RBNode **out_node) +static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **out_node) +{ + if (tree->root == tree->nil) return false; + + RBNode *node = tree->root; + RBNode *nearest = tree->root; + + while (true) + { + + + if (node->key == key) + break; + + if (node->left == tree->nil && node->right == tree->nil) + break; + + if (node->key < key && node->right != tree->nil) + node = node->right; + } +} + +static b32 RBTreeSearch(RBTree *tree, u32 key, RBNode **out_node) { if (tree->root == tree->nil) return false; @@ -249,7 +282,7 @@ static b32 RBTreeSearch(RBTree *tree, i32 value, RBNode **out_node) while (true) { - if (node->value == value) + if (node->key == key) { found = true; break; @@ -258,7 +291,7 @@ static b32 RBTreeSearch(RBTree *tree, i32 value, RBNode **out_node) if (node == tree->nil) break; - if (node->value < value) + if (node->key < key) node = node->right; else node = node->left; diff --git a/src/ds.h b/src/ds.h index 4857404..843c0d7 100644 --- a/src/ds.h +++ b/src/ds.h @@ -30,7 +30,7 @@ typedef struct RBNode struct RBNode *child[2]; }; struct RBNode *parent; - i32 value; + u32 key; rawptr data; RBNodeColor color; } RBNode; @@ -42,9 +42,11 @@ typedef struct RBTree } RBTree; static void RBTreeInit (RBTree *tree); -static RBNode *RBTreeFindOrInsert(RBTree *tree, RBNode *node); -static b32 RBTreeSearch (RBTree *tree, i32 value, RBNode **node); -static void RBTreeDelete (RBTree *tree, i32 value); +static inline void RBTreeInitNode(RBNode *node, u32 key, rawptr value); +static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value); +static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **node); +static b32 RBTreeSearch (RBTree *tree, u32 key, RBNode **node); +static void RBTreeDelete (RBTree *tree, u32 key); static void RBTreeLeftRotate (RBTree *tree, RBNode *node); static void RBTreeRightRotate(RBTree *tree, RBNode *node); static void RBTreeRotate (RBTree *tree, RBNode *node, RBNodeDir dir); diff --git a/src/entry_linux.c b/src/entry_linux.c index 501809a..88e0956 100644 --- a/src/entry_linux.c +++ b/src/entry_linux.c @@ -1,5 +1,7 @@ #ifdef __linux__ +// ::Entry::Linux::Globals::End:: + #include "entry_linux.h" // ::ThirdParty::Include:: @@ -16,12 +18,19 @@ # include "tests.c" #endif +// ::Entry::Linux::Globals::Start:: + +constexpr u8 asset_pack[] = +{ + #embed "../assets.sgp" +}; + static_assert(__COUNTER__ < Len(GLOBAL_PROFILER.anchors)); void TraverseNode(RBTree *tree, RBNode *node, RBNodeDir *dir) { char *dir_str = dir == NULL ? "Root" : *dir == RB_RIGHT ? "Right" : "Left"; - Printfln("Color: %s Value: %d Dir: %s", node->color == RB_RED ? "Red" : "Black", node->value, dir_str); + Printfln("Color: %s Value: %d Dir: %s", node->color == RB_RED ? "Red" : "Black", node->key, dir_str); if (node->left != tree->nil) { RBNodeDir left_dir = RB_LEFT; diff --git a/src/renderer_vulkan.c b/src/renderer_vulkan.c index eb69eea..7ed3aa8 100644 --- a/src/renderer_vulkan.c +++ b/src/renderer_vulkan.c @@ -841,8 +841,8 @@ static b32 CreateSwapchain() u32 width = renderer.vk.sc.extent.width; u32 height = renderer.vk.sc.extent.height; - extent.width = u32Clamp((u32)width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); - extent.height = u32Clamp((u32)height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); + extent.width = Clamp((u32)width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); + extent.height = Clamp((u32)height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); if (present_mode == INT_MAX || format == INT_MAX || color_space == INT_MAX) { diff --git a/src/util.c b/src/util.c index 0fcd460..362b1da 100644 --- a/src/util.c +++ b/src/util.c @@ -119,6 +119,8 @@ void MemZero(void *ptr, isize size) void MemCpy(rawptr dst, rawptr src, usize size) { + if (size == 0) return; + isize iter_size = size > sizeof(u64) ? 8 : 1; iter_size *= 4; isize iter_len = size / iter_size; @@ -164,35 +166,9 @@ void MemCpy(rawptr dst, rawptr src, usize size) // ::Util::Math::Functions::Start:: -u32 u32Min(u32 l, u32 r) -{ - return l >= r ? r : l; -} - -i32 i32Min(i32 l, i32 r) -{ - return l >= r ? r : l; -} - -u32 u32Max(u32 l, u32 r) -{ - return l >= r ? l : r; -} - -i32 i32Max(i32 l, i32 r) -{ - return l >= r ? l : r; -} - -i32 i32Clamp(i32 v, i32 min, i32 max) -{ - return i32Min(max, i32Max(v, min)); -} - -u32 u32Clamp(u32 v, u32 min, u32 max) -{ - return i32Min(max, i32Max(v, min)); -} +DefMathImpl(Min); +DefMathImpl(Max); +DefMathImpl(Clamp); // ::Util::Math::Functions::End:: diff --git a/src/util.h b/src/util.h index c7dc30e..147e265 100644 --- a/src/util.h +++ b/src/util.h @@ -113,12 +113,60 @@ void MemCpy(rawptr dst, rawptr src, usize len); // ::Util::Math::Functions::Header:: -u32 u32Min(u32 l, u32 r); -i32 i32Min(i32 l, i32 r); -u32 u32Max(u32 l, u32 r); -i32 i32Max(i32 l, i32 r); -i32 i32Clamp(i32 v, i32 min, i32 max); -u32 u32Clamp(u32 v, u32 min, u32 max); +#define DefIntegerImpl(def) \ + Def##def(i8); \ + Def##def(i16); \ + Def##def(i32); \ + Def##def(i64); \ + Def##def(u8); \ + Def##def(u16); \ + Def##def(u32); \ + Def##def(u64) + +#define DefFloatImpl(def) \ + Def##def(f32); \ + Def##def(f64) + +#define DefMathImpl(def) \ + DefIntegerImpl(def); \ + DefFloatImpl(def); + +#define MathGeneric(fn, params) _Generic(params, \ + i8: i8##fn, \ + i16: i16##fn, \ + i32: i32##fn, \ + i64: i64##fn, \ + u8: u8##fn, \ + u16: u16##fn, \ + u32: u32##fn, \ + u64: u64##fn, \ + f32: f32##fn, \ + f64: f64##fn \ +)params + +#define Min(l, r) MathGeneric(Min, (l, r)) + +#define Max(l, r) MathGeneric(Max, (l, r)) + +#define Clamp(v, min, max) MathGeneric(Clamp, (v, min, max)) + +#define DefMin(T) \ +T T##Min(T l, T r) \ +{ \ + return l < r ? l : r; \ +} + +#define DefMax(T) \ +T T##Max(T l, T r) \ +{ \ + return l > r ? l : r; \ +} + +#define DefClamp(T) \ +T T##Clamp(T v, T min, T max) \ +{ \ + return Min(max, Max(v, min)); \ +} // ::Util::Hashing::Functions::Header::