From deb8de63490df5015531abc03c58fda9c1ff97de Mon Sep 17 00:00:00 2001 From: Samdal Date: Mon, 29 Jul 2024 12:57:29 +0200 Subject: [PATCH 1/8] add low level OS memory API and arena --- gs.h | 90 +++++++++++++- impl/gs_platform_impl.h | 267 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 356 insertions(+), 1 deletion(-) diff --git a/gs.h b/gs.h index 2c04f1a..8636082 100644 --- a/gs.h +++ b/gs.h @@ -736,6 +736,8 @@ typedef bool32_t bool32; ===================================*/ // Operating system function pointer +// NOTE(Samdal): the name "OS" is misleading, +// these are just wrappers around libc, not the Operating System typedef struct gs_os_api_s { void* (* malloc)(size_t sz); @@ -795,7 +797,73 @@ gs_os_api_new_default(); #ifndef gs_strdup #define gs_strdup(__STR) (gs_ctx()->os.strdup(__STR)) -#endif +#endif + +//=== arena impl ===// + +#ifndef GS_DEFAULT_ARENA + +typedef struct gs_arena_default gs_arena_default; +struct gs_arena_default +{ + gs_arena_default *prev; + gs_arena_default *current; + uint64_t base_pos; + uint64_t pos; + uint64_t cmt; + uint64_t cap; +}; +#define GS_IMPL_ARENA gs_arena_default + +#endif // GS_DEFAULT_ARENA + +#if !defined(GS_IMPL_ARENA) +# error Missing implementation for GS_IMPL_ARENA +#endif + +typedef GS_IMPL_ARENA gs_arena; + +typedef struct gs_arena_temp gs_arena_temp; +struct gs_arena_temp +{ + gs_arena *arena; + uint64_t pos; +}; + +// arena functions + +GS_API_DECL gs_arena* gs_arena_alloc(void); +GS_API_DECL void gs_arena_release(gs_arena* arena); + +GS_API_DECL void* _gs_arena_push(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes); +GS_API_DECL void* _gs_arena_push_nz(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes); +GS_API_DECL void gs_arena_reset(gs_arena* arena); + +#if 1 // _Alignof is C11... + +#define gs_arena_push(a,T) (T*)(_gs_arena_push((a), sizeof(T), _Alignof(T))) +#define gs_arena_push_array(a,T,c) (T*)(_gs_arena_push((a), sizeof(T)*(c), _Alignof(T))) +#define gs_arena_push_no_zero(a,T) (T*)(_gs_arena_push_nz((a), sizeof(T), _Alignof(T))) +#define gs_arena_push_array_no_zero(a,T,c) (T*)(_gs_arena_push_nz((a), sizeof(T)*(c), _Alignof(T))) + +#else + +#define gs_arena_push(a,T) (T*)(_gs_arena_push((a), sizeof(T), 16)) +#define gs_arena_push_array(a,T,c) (T*)(_gs_arena_push((a), sizeof(T)*(c), 16)) +#define gs_arena_push_no_zero(a,T) (T*)(_gs_arena_push_nz((a), sizeof(T), 16)) +#define gs_arena_push_array_no_zero(a,T,c) (T*)(_gs_arena_push_nz((a), sizeof(T)*(c), 16)) + +#endif + + +GS_API_DECL gs_arena_temp gs_arena_begin_temp(gs_arena* arena); +GS_API_DECL void gs_arena_end_temp(gs_arena_temp temp); + +// arena scratch pool + +GS_API_DECL gs_arena_temp gs_arena_get_scratch(gs_arena **conflicts, uint64_t count); +#define gs_arena_release_scratch(scratch) gs_arena_end_temp(scratch) + // Modified from: https://stackoverflow.com/questions/11815894/how-to-read-write-arbitrary-bits-in-c-c #define gs_bit_mask(INDEX, SIZE)\ @@ -5579,6 +5647,26 @@ GS_API_DECL void* gs_platform_library_proc_address_default_impl(void* lib, #define gs_platform_library_proc_address gs_platform_library_proc_address_default_impl #endif +// === low level memory === // + +GS_API_DECL void* gs_platform_reserve_default_impl(uint32_t size); +GS_API_DECL bool32 gs_platform_commit_default_impl(void* ptr, uint32_t size); +GS_API_DECL void gs_platform_decommit_default_impl(void* ptr, uint32_t size); +GS_API_DECL void gs_platform_release_default_impl(void* ptr, uint32_t size); + +#ifndef gs_platform_reserve +#define gs_platform_reserve gs_platform_reserve_default_impl +#endif +#ifndef gs_platform_commit +#define gs_platform_commit gs_platform_commit_default_impl +#endif +#ifndef gs_platform_decommit +#define gs_platform_decommit gs_platform_decommit_default_impl +#endif +#ifndef gs_platform_release +#define gs_platform_release gs_platform_release_default_impl +#endif + /* == Platform Dependent API == */ GS_API_DECL void gs_platform_init(gs_platform_t* platform); // Initialize platform layer diff --git a/impl/gs_platform_impl.h b/impl/gs_platform_impl.h index 75beea7..827517a 100644 --- a/impl/gs_platform_impl.h +++ b/impl/gs_platform_impl.h @@ -13,6 +13,7 @@ =================================*/ // Define default platform implementation if certain platforms are enabled +#include #if (!defined GS_PLATFORM_IMPL_NO_DEFAULT) #define GS_PLATFORM_IMPL_DEFAULT #endif @@ -901,6 +902,272 @@ gs_platform_library_proc_address_default_impl(void* lib, const char* func) return NULL; } +// === low level memory === // +#ifndef GS_PLATFORM_WINDOWS +#include +#endif // GS_PLATFORM_WINDOWS + +GS_API_DECL void* gs_platform_reserve_default_impl(uint32_t size) +{ +#ifdef GS_PLATFORM_WINDOWS + return VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); +#else + return mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, (off_t)0); +#endif +} +GS_API_DECL bool32 gs_platform_commit_default_impl(void* ptr, uint32_t size) +{ +#ifdef GS_PLATFORM_WINDOWS + return (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0); +#else + return (mprotect(ptr, size, PROT_READ|PROT_WRITE) == 0); +#endif +} +GS_API_DECL void gs_platform_decommit_default_impl(void* ptr, uint32_t size) +{ +#ifdef GS_PLATFORM_WINDOWS + VirtualFree(ptr, size, MEM_DECOMMIT); +#else + mprotect(ptr, size, PROT_NONE); + madvise(ptr, size, MADV_DONTNEED); +#endif +} +GS_API_DECL void gs_platform_release_default_impl(void* ptr, uint32_t size) +{ +#ifdef GS_PLATFORM_WINDOWS + VirtualFree(ptr, 0, MEM_RELEASE); +#else + munmap(ptr, size); +#endif +} + + +// default arena functions + + +////////////////////////////////////////////////// +// TODO(Samdal): allow more customization +// +// typedef U32 ArenaFlags; +// enum +// { +// ArenaFlag_NoChain = (1<<0), +// ArenaFlag_LargePages = (1<<1), +// }; +// +// typedef struct ArenaParams ArenaParams; +// struct ArenaParams +// { +// ArenaFlags flags; +// U64 reserve_size; +// U64 commit_size; +// void *optional_backing_buffer; +// }; +// +/////////////////////////////////// + + +#define gs_arena_self_size (gs_max(sizeof(gs_arena), 64)) +#define GS_DEFAULT_ARENA_CMT_SIZE (64 << 10) +#define GS_DEFAULT_ARENA_RES_SIZE (64 << 20) +#define GS_DEFAULT_ARENA_VERY_BIG (GS_DEFAULT_ARENA_RES_SIZE - gs_arena_self_size)/2 + +#define _gs_align_pow2(x,b) (((x)+((b)-1))&(~((b)-1))) + + +static gs_arena* +gs_arena_alloc_size(uint64_t cmt, uint64_t res) +{ + gs_assert(gs_arena_self_size < cmt && cmt <= res); + uint64_t cmt_clamped = gs_min(cmt, res); + gs_arena* result = 0; + void *mem = gs_platform_reserve(res); + + if (gs_platform_commit(mem, cmt_clamped)) { + result = (gs_arena*)mem; + result->prev = 0; + result->current = result; + result->base_pos = 0; + result->pos = gs_arena_self_size; + result->cmt = cmt_clamped; + result->cap = res; + } + + return result; +} + +GS_API_DECL gs_arena* gs_arena_alloc(void) +{ + return gs_arena_alloc_size(GS_DEFAULT_ARENA_CMT_SIZE, GS_DEFAULT_ARENA_RES_SIZE); +} +GS_API_DECL void gs_arena_release(gs_arena* arena) +{ + for (gs_arena *node = arena->current, *prev = 0; node; node = prev) { + prev = node->prev; + gs_platform_release(node, node->cap); + } +} +static uint64_t +gs_arena_get_pos(gs_arena* arena) +{ + gs_arena *current = arena->current; + uint64_t result = current->base_pos + current->pos; + return result; +} + +GS_API_DECL void* _gs_arena_push_nz(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) +{ + // try to be fast! + gs_arena *current = arena->current; + uint64_t pos = current->pos; + uint64_t pos_aligned = _gs_align_pow2(pos, align_bytes); + uint64_t new_pos = pos_aligned + size_bytes; + void *result = (uint8_t*)current + pos_aligned; + current->pos = new_pos; + + // if it's not going to work do the slow path + if (new_pos > current->cmt) { + result = 0; + current->pos = pos; + + // new chunk if necessary + if (new_pos > current->cap) { + gs_arena *new_arena = 0; + if (size_bytes > GS_DEFAULT_ARENA_VERY_BIG) { + uint64_t big_size_unrounded = size_bytes + gs_arena_self_size; + uint64_t big_size = _gs_align_pow2(big_size_unrounded, (4 << 10)); + new_arena = gs_arena_alloc_size(big_size, big_size); + } else { + new_arena = gs_arena_alloc(); + } + + // link in new chunk & recompute new_pos + if (new_arena != 0) { + new_arena->base_pos = current->base_pos + current->cap; + new_arena->prev = current; + current = new_arena; + arena->current = current; + pos_aligned = current->pos; + new_pos = pos_aligned + size_bytes; + } + } + + // move ahead if the current chunk has enough reserve + if (new_pos <= current->cap) { + + // extend commit if necessary + if (new_pos > current->cmt) { + uint64_t new_cmt_unclamped = _gs_align_pow2(new_pos, GS_DEFAULT_ARENA_CMT_SIZE); + uint64_t new_cmt = gs_min(new_cmt_unclamped, current->cap); + uint64_t cmt_size = new_cmt - current->cmt; + if (gs_platform_commit((uint8_t*)current + current->cmt, cmt_size)) { + current->cmt = new_cmt; + } + } + + // move ahead if the current chunk has enough commit + if (new_pos <= current->cmt) { + result = (uint8_t*)current + current->pos; + current->pos = new_pos; + } + } + } + + return result; +} +GS_API_DECL void* _gs_arena_push(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) +{ + return memset(_gs_arena_push_nz(arena, size_bytes, align_bytes), 0, size_bytes); +} + +static void +gs_arena_pop_to(gs_arena *arena, uint64_t pos) +{ + + // pop chunks in the chain + uint64_t pos_clamped = gs_max(gs_arena_self_size, pos); + { + gs_arena *node = arena->current; + for (gs_arena *prev = 0; node && node->base_pos >= pos; node = prev) { + prev = node->prev; + gs_platform_release(node, node->cap); + } + arena->current = node; + } + + // reset the pos of the current + { + gs_arena *current = arena->current; + uint64_t local_pos_unclamped = pos - current->base_pos; + uint64_t local_pos = gs_max(local_pos_unclamped, gs_arena_self_size); + current->pos = local_pos; + } +} + + +GS_API_DECL void gs_arena_reset(gs_arena* arena) +{ + gs_arena_pop_to(arena, gs_arena_self_size); +} + +GS_API_DECL gs_arena_temp gs_arena_begin_temp(gs_arena* arena) +{ + return (gs_arena_temp){ + .arena = arena, + .pos = gs_arena_get_pos(arena) + }; +} + +GS_API_DECL void gs_arena_end_temp(gs_arena_temp temp) +{ + gs_arena_pop_to(temp.arena, temp.pos); +} + + +// arena scratch pool + + +#ifndef _gs_scratch_count +#define _gs_scratch_count 2 +#endif + +#ifdef _WIN32 +__declspec(thread) gs_arena* _gs_thread_scratch_pool[_gs_scratch_count] = {0, 0}; +#else +__thread gs_arena* _gs_thread_scratch_pool[_gs_scratch_count] = {0, 0}; +#endif + +GS_API_DECL gs_arena_temp gs_arena_get_scratch(gs_arena **conflicts, uint64_t count) +{ + gs_arena** scratch_pool = _gs_thread_scratch_pool; + if (scratch_pool[0] == 0) { + gs_arena **arena_ptr = scratch_pool; + for (uint64_t i = 0; i < _gs_scratch_count; i += 1, arena_ptr += 1) { + *arena_ptr = gs_arena_alloc(); + } + } + gs_arena *result = 0; + gs_arena **arena_ptr = scratch_pool; + for (uint64_t i = 0; i < _gs_scratch_count; i += 1, arena_ptr += 1) { + gs_arena *arena = *arena_ptr; + gs_arena **conflict_ptr = conflicts; + for (uint32_t j = 0; j < count; j += 1, conflict_ptr += 1) { + if (arena == *conflict_ptr) { + arena = 0; + break; + } + } + if (arena != 0) { + result = arena; + break; + } + } + + return gs_arena_begin_temp(result); +} + + + #undef GS_PLATFORM_IMPL_DEFAULT #endif // GS_PLATFORM_IMPL_DEFAULT From 0efe8ed46d1f28e2c41bfd5a66d526815e87b795 Mon Sep 17 00:00:00 2001 From: Samdal Date: Mon, 29 Jul 2024 13:00:36 +0200 Subject: [PATCH 2/8] fix compile errors in linux --- impl/gs_graphics_impl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/impl/gs_graphics_impl.h b/impl/gs_graphics_impl.h index d55d064..39c6d09 100644 --- a/impl/gs_graphics_impl.h +++ b/impl/gs_graphics_impl.h @@ -207,7 +207,7 @@ void gsgl_pipeline_state() void GLAPIENTRY gsgl_message_cb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, - const GLchar* message, void* user_param) + const GLchar* message, const void* user_param) { return; if (type == GL_DEBUG_TYPE_ERROR) { @@ -1499,7 +1499,7 @@ gs_grapics_storage_buffer_unlock_impl(gs_handle(gs_graphics_storage_buffer_t) hn gsgl_data_t* ogl = (gsgl_data_t*)gs_subsystem(graphics)->user_data; if (!gs_slot_array_handle_valid(ogl->storage_buffers, hndl.id)) { gs_log_warning("Storage buffer handle invalid: %zu", hndl.id); - return NULL; + return; } gsgl_storage_buffer_t* sbo = gs_slot_array_getp(ogl->storage_buffers, hndl.id); @@ -1567,7 +1567,7 @@ gs_storage_buffer_get_data_impl(gs_handle(gs_graphics_storage_buffer_t) hndl, si gsgl_data_t* ogl = (gsgl_data_t*)gs_subsystem(graphics)->user_data; if (!gs_slot_array_handle_valid(ogl->storage_buffers, hndl.id)) { gs_log_warning("Storage buffer handle invalid: %zu", hndl.id); - return NULL; + return; } gsgl_storage_buffer_t* sbo = gs_slot_array_getp(ogl->storage_buffers, hndl.id); glBindBuffer(GL_SHADER_STORAGE_BUFFER, sbo->buffer); From 00ab463375a6fc09e164f247b6e2c8f062b852de Mon Sep 17 00:00:00 2001 From: Samdal Date: Mon, 29 Jul 2024 13:32:43 +0200 Subject: [PATCH 3/8] add seperator comment --- gs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gs.h b/gs.h index 8636082..3d6afed 100644 --- a/gs.h +++ b/gs.h @@ -864,6 +864,7 @@ GS_API_DECL void gs_arena_end_temp(gs_arena_temp temp); GS_API_DECL gs_arena_temp gs_arena_get_scratch(gs_arena **conflicts, uint64_t count); #define gs_arena_release_scratch(scratch) gs_arena_end_temp(scratch) +///////////////////////////// // Modified from: https://stackoverflow.com/questions/11815894/how-to-read-write-arbitrary-bits-in-c-c #define gs_bit_mask(INDEX, SIZE)\ From 0ca38fb4a3306d48b3e443e7f68cf74ac40c72d7 Mon Sep 17 00:00:00 2001 From: Samdal Date: Mon, 29 Jul 2024 13:37:00 +0200 Subject: [PATCH 4/8] clean up --- gs.h | 21 ++++----------------- impl/gs_platform_impl.h | 1 - 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/gs.h b/gs.h index 3d6afed..a96275b 100644 --- a/gs.h +++ b/gs.h @@ -5650,23 +5650,10 @@ GS_API_DECL void* gs_platform_library_proc_address_default_impl(void* lib, // === low level memory === // -GS_API_DECL void* gs_platform_reserve_default_impl(uint32_t size); -GS_API_DECL bool32 gs_platform_commit_default_impl(void* ptr, uint32_t size); -GS_API_DECL void gs_platform_decommit_default_impl(void* ptr, uint32_t size); -GS_API_DECL void gs_platform_release_default_impl(void* ptr, uint32_t size); - -#ifndef gs_platform_reserve -#define gs_platform_reserve gs_platform_reserve_default_impl -#endif -#ifndef gs_platform_commit -#define gs_platform_commit gs_platform_commit_default_impl -#endif -#ifndef gs_platform_decommit -#define gs_platform_decommit gs_platform_decommit_default_impl -#endif -#ifndef gs_platform_release -#define gs_platform_release gs_platform_release_default_impl -#endif +GS_API_DECL void* gs_platform_reserve(uint32_t size); +GS_API_DECL bool32 gs_platform_commit(void* ptr, uint32_t size); +GS_API_DECL void gs_platform_decommit(void* ptr, uint32_t size); +GS_API_DECL void gs_platform_release(void* ptr, uint32_t size); /* == Platform Dependent API == */ diff --git a/impl/gs_platform_impl.h b/impl/gs_platform_impl.h index 827517a..218fd95 100644 --- a/impl/gs_platform_impl.h +++ b/impl/gs_platform_impl.h @@ -13,7 +13,6 @@ =================================*/ // Define default platform implementation if certain platforms are enabled -#include #if (!defined GS_PLATFORM_IMPL_NO_DEFAULT) #define GS_PLATFORM_IMPL_DEFAULT #endif From e2b40a869c2519ad0e0f4b9995670189c7d5500d Mon Sep 17 00:00:00 2001 From: Samdal Date: Mon, 29 Jul 2024 13:40:11 +0200 Subject: [PATCH 5/8] change whitespace and nameing --- impl/gs_platform_impl.h | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/impl/gs_platform_impl.h b/impl/gs_platform_impl.h index 218fd95..15b7580 100644 --- a/impl/gs_platform_impl.h +++ b/impl/gs_platform_impl.h @@ -906,7 +906,7 @@ gs_platform_library_proc_address_default_impl(void* lib, const char* func) #include #endif // GS_PLATFORM_WINDOWS -GS_API_DECL void* gs_platform_reserve_default_impl(uint32_t size) +GS_API_DECL void* gs_platform_reserve(uint32_t size) { #ifdef GS_PLATFORM_WINDOWS return VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); @@ -914,7 +914,7 @@ GS_API_DECL void* gs_platform_reserve_default_impl(uint32_t size) return mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, (off_t)0); #endif } -GS_API_DECL bool32 gs_platform_commit_default_impl(void* ptr, uint32_t size) +GS_API_DECL bool32 gs_platform_commit(void* ptr, uint32_t size) { #ifdef GS_PLATFORM_WINDOWS return (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0); @@ -922,7 +922,7 @@ GS_API_DECL bool32 gs_platform_commit_default_impl(void* ptr, uint32_t size) return (mprotect(ptr, size, PROT_READ|PROT_WRITE) == 0); #endif } -GS_API_DECL void gs_platform_decommit_default_impl(void* ptr, uint32_t size) +GS_API_DECL void gs_platform_decommit(void* ptr, uint32_t size) { #ifdef GS_PLATFORM_WINDOWS VirtualFree(ptr, size, MEM_DECOMMIT); @@ -931,7 +931,7 @@ GS_API_DECL void gs_platform_decommit_default_impl(void* ptr, uint32_t size) madvise(ptr, size, MADV_DONTNEED); #endif } -GS_API_DECL void gs_platform_release_default_impl(void* ptr, uint32_t size) +GS_API_DECL void gs_platform_release(void* ptr, uint32_t size) { #ifdef GS_PLATFORM_WINDOWS VirtualFree(ptr, 0, MEM_RELEASE); @@ -995,17 +995,21 @@ gs_arena_alloc_size(uint64_t cmt, uint64_t res) return result; } -GS_API_DECL gs_arena* gs_arena_alloc(void) +GS_API_DECL gs_arena* +gs_arena_alloc(void) { return gs_arena_alloc_size(GS_DEFAULT_ARENA_CMT_SIZE, GS_DEFAULT_ARENA_RES_SIZE); } -GS_API_DECL void gs_arena_release(gs_arena* arena) + +GS_API_DECL void +gs_arena_release(gs_arena* arena) { for (gs_arena *node = arena->current, *prev = 0; node; node = prev) { prev = node->prev; gs_platform_release(node, node->cap); } } + static uint64_t gs_arena_get_pos(gs_arena* arena) { @@ -1014,7 +1018,8 @@ gs_arena_get_pos(gs_arena* arena) return result; } -GS_API_DECL void* _gs_arena_push_nz(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) +GS_API_DECL void* +_gs_arena_push_nz(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) { // try to be fast! gs_arena *current = arena->current; @@ -1074,7 +1079,9 @@ GS_API_DECL void* _gs_arena_push_nz(gs_arena* arena, uint64_t size_bytes, return result; } -GS_API_DECL void* _gs_arena_push(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) + +GS_API_DECL void* +_gs_arena_push(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) { return memset(_gs_arena_push_nz(arena, size_bytes, align_bytes), 0, size_bytes); } @@ -1104,12 +1111,14 @@ gs_arena_pop_to(gs_arena *arena, uint64_t pos) } -GS_API_DECL void gs_arena_reset(gs_arena* arena) +GS_API_DECL void +gs_arena_reset(gs_arena* arena) { gs_arena_pop_to(arena, gs_arena_self_size); } -GS_API_DECL gs_arena_temp gs_arena_begin_temp(gs_arena* arena) +GS_API_DECL gs_arena_temp +gs_arena_begin_temp(gs_arena* arena) { return (gs_arena_temp){ .arena = arena, @@ -1117,7 +1126,8 @@ GS_API_DECL gs_arena_temp gs_arena_begin_temp(gs_arena* arena) }; } -GS_API_DECL void gs_arena_end_temp(gs_arena_temp temp) +GS_API_DECL void +gs_arena_end_temp(gs_arena_temp temp) { gs_arena_pop_to(temp.arena, temp.pos); } @@ -1136,7 +1146,8 @@ __declspec(thread) gs_arena* _gs_thread_scratch_pool[_gs_scratch_count] = {0, 0} __thread gs_arena* _gs_thread_scratch_pool[_gs_scratch_count] = {0, 0}; #endif -GS_API_DECL gs_arena_temp gs_arena_get_scratch(gs_arena **conflicts, uint64_t count) +GS_API_DECL gs_arena_temp +gs_arena_get_scratch(gs_arena **conflicts, uint64_t count) { gs_arena** scratch_pool = _gs_thread_scratch_pool; if (scratch_pool[0] == 0) { @@ -1166,7 +1177,6 @@ GS_API_DECL gs_arena_temp gs_arena_get_scratch(gs_arena **conflicts, uint64_t co } - #undef GS_PLATFORM_IMPL_DEFAULT #endif // GS_PLATFORM_IMPL_DEFAULT From f31ba61ff0836d8a4f68ef95a6c55769893ac15e Mon Sep 17 00:00:00 2001 From: Samdal Date: Mon, 29 Jul 2024 13:51:13 +0200 Subject: [PATCH 6/8] move from gs_platform to gs_memory --- gs.h | 439 +++++++++++++++++++++++++++++++++------- impl/gs_platform_impl.h | 275 ------------------------- 2 files changed, 366 insertions(+), 348 deletions(-) diff --git a/gs.h b/gs.h index a96275b..7566af6 100644 --- a/gs.h +++ b/gs.h @@ -799,72 +799,6 @@ gs_os_api_new_default(); #define gs_strdup(__STR) (gs_ctx()->os.strdup(__STR)) #endif -//=== arena impl ===// - -#ifndef GS_DEFAULT_ARENA - -typedef struct gs_arena_default gs_arena_default; -struct gs_arena_default -{ - gs_arena_default *prev; - gs_arena_default *current; - uint64_t base_pos; - uint64_t pos; - uint64_t cmt; - uint64_t cap; -}; -#define GS_IMPL_ARENA gs_arena_default - -#endif // GS_DEFAULT_ARENA - -#if !defined(GS_IMPL_ARENA) -# error Missing implementation for GS_IMPL_ARENA -#endif - -typedef GS_IMPL_ARENA gs_arena; - -typedef struct gs_arena_temp gs_arena_temp; -struct gs_arena_temp -{ - gs_arena *arena; - uint64_t pos; -}; - -// arena functions - -GS_API_DECL gs_arena* gs_arena_alloc(void); -GS_API_DECL void gs_arena_release(gs_arena* arena); - -GS_API_DECL void* _gs_arena_push(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes); -GS_API_DECL void* _gs_arena_push_nz(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes); -GS_API_DECL void gs_arena_reset(gs_arena* arena); - -#if 1 // _Alignof is C11... - -#define gs_arena_push(a,T) (T*)(_gs_arena_push((a), sizeof(T), _Alignof(T))) -#define gs_arena_push_array(a,T,c) (T*)(_gs_arena_push((a), sizeof(T)*(c), _Alignof(T))) -#define gs_arena_push_no_zero(a,T) (T*)(_gs_arena_push_nz((a), sizeof(T), _Alignof(T))) -#define gs_arena_push_array_no_zero(a,T,c) (T*)(_gs_arena_push_nz((a), sizeof(T)*(c), _Alignof(T))) - -#else - -#define gs_arena_push(a,T) (T*)(_gs_arena_push((a), sizeof(T), 16)) -#define gs_arena_push_array(a,T,c) (T*)(_gs_arena_push((a), sizeof(T)*(c), 16)) -#define gs_arena_push_no_zero(a,T) (T*)(_gs_arena_push_nz((a), sizeof(T), 16)) -#define gs_arena_push_array_no_zero(a,T,c) (T*)(_gs_arena_push_nz((a), sizeof(T)*(c), 16)) - -#endif - - -GS_API_DECL gs_arena_temp gs_arena_begin_temp(gs_arena* arena); -GS_API_DECL void gs_arena_end_temp(gs_arena_temp temp); - -// arena scratch pool - -GS_API_DECL gs_arena_temp gs_arena_get_scratch(gs_arena **conflicts, uint64_t count); -#define gs_arena_release_scratch(scratch) gs_arena_end_temp(scratch) - -///////////////////////////// // Modified from: https://stackoverflow.com/questions/11815894/how-to-read-write-arbitrary-bits-in-c-c #define gs_bit_mask(INDEX, SIZE)\ @@ -2798,6 +2732,88 @@ void gs_command_buffer_free(gs_command_buffer_t* cb) * @{ */ + +// === low level OS memory === // + +GS_API_DECL void* gs_memory_reserve(uint32_t size); +GS_API_DECL bool32 gs_memory_commit(void* ptr, uint32_t size); +GS_API_DECL void gs_memory_decommit(void* ptr, uint32_t size); +GS_API_DECL void gs_memory_release(void* ptr, uint32_t size); + +/*================================================================================ +// Arena Allocator / Linear Allocator / Stack Allocator / Bump Allocator +================================================================================*/ + +//=== arena impl ===// + +#ifndef GS_DEFAULT_ARENA + +typedef struct gs_arena_default gs_arena_default; +struct gs_arena_default +{ + gs_arena_default *prev; + gs_arena_default *current; + uint64_t base_pos; + uint64_t pos; + uint64_t cmt; + uint64_t cap; +}; +#define GS_IMPL_ARENA gs_arena_default + +#endif // GS_DEFAULT_ARENA + +#if !defined(GS_IMPL_ARENA) +# error Missing implementation for GS_IMPL_ARENA +#endif + +typedef GS_IMPL_ARENA gs_arena; + +typedef struct gs_arena_temp gs_arena_temp; +struct gs_arena_temp +{ + gs_arena *arena; + uint64_t pos; +}; + +// arena functions + +GS_API_DECL gs_arena* gs_arena_alloc(void); +GS_API_DECL void gs_arena_release(gs_arena* arena); + +GS_API_DECL void* _gs_arena_push(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes); +GS_API_DECL void* _gs_arena_push_nz(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes); +GS_API_DECL void gs_arena_reset(gs_arena* arena); + +#if 1 // _Alignof is C11... + +#define gs_arena_push(a,T) (T*)(_gs_arena_push((a), sizeof(T), _Alignof(T))) +#define gs_arena_push_array(a,T,c) (T*)(_gs_arena_push((a), sizeof(T)*(c), _Alignof(T))) +#define gs_arena_push_no_zero(a,T) (T*)(_gs_arena_push_nz((a), sizeof(T), _Alignof(T))) +#define gs_arena_push_array_no_zero(a,T,c) (T*)(_gs_arena_push_nz((a), sizeof(T)*(c), _Alignof(T))) + +#else + +#define gs_arena_push(a,T) (T*)(_gs_arena_push((a), sizeof(T), 16)) +#define gs_arena_push_array(a,T,c) (T*)(_gs_arena_push((a), sizeof(T)*(c), 16)) +#define gs_arena_push_no_zero(a,T) (T*)(_gs_arena_push_nz((a), sizeof(T), 16)) +#define gs_arena_push_array_no_zero(a,T,c) (T*)(_gs_arena_push_nz((a), sizeof(T)*(c), 16)) + +#endif + + +GS_API_DECL gs_arena_temp gs_arena_begin_temp(gs_arena* arena); +GS_API_DECL void gs_arena_end_temp(gs_arena_temp temp); + +// arena scratch pool + +GS_API_DECL gs_arena_temp gs_arena_get_scratch(gs_arena **conflicts, uint64_t count); +#define gs_arena_release_scratch(scratch) gs_arena_end_temp(scratch) + + +/*================================================================================ +// Memory Block +================================================================================*/ + #define gs_ptr_add(P, BYTES) \ (((uint8_t*)P + (BYTES))) @@ -2815,6 +2831,9 @@ GS_API_DECL size_t gs_memory_calc_padding_w_header(size_t base_address, size_t a // Linear Allocator ================================================================================*/ +// NOTE(Samdal): +// You may want to use gs_arena instead + typedef struct gs_linear_allocator_t { uint8_t* memory; size_t total_size; @@ -2830,6 +2849,9 @@ GS_API_DECL void gs_linear_allocator_clear(gs_linear_allocator_t* la); // Stack Allocator ================================================================================*/ +// NOTE(Samdal): +// You may want to use gs_arena instead + typedef struct gs_stack_allocator_header_t { uint32_t size; } gs_stack_allocator_header_t; @@ -5648,13 +5670,6 @@ GS_API_DECL void* gs_platform_library_proc_address_default_impl(void* lib, #define gs_platform_library_proc_address gs_platform_library_proc_address_default_impl #endif -// === low level memory === // - -GS_API_DECL void* gs_platform_reserve(uint32_t size); -GS_API_DECL bool32 gs_platform_commit(void* ptr, uint32_t size); -GS_API_DECL void gs_platform_decommit(void* ptr, uint32_t size); -GS_API_DECL void gs_platform_release(void* ptr, uint32_t size); - /* == Platform Dependent API == */ GS_API_DECL void gs_platform_init(gs_platform_t* platform); // Initialize platform layer @@ -7503,6 +7518,284 @@ __gs_pqueue_pop_internal(void** pqueue, void* tmp, void** data, int32_t* priorit // GS_MEMORY ========================*/ +// === low level memory === // +#ifndef GS_PLATFORM_WINDOWS +#include +#endif // GS_PLATFORM_WINDOWS + +GS_API_DECL void* gs_memory_reserve(uint32_t size) +{ +#ifdef GS_PLATFORM_WINDOWS + return VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); +#else + return mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, (off_t)0); +#endif +} +GS_API_DECL bool32 gs_memory_commit(void* ptr, uint32_t size) +{ +#ifdef GS_PLATFORM_WINDOWS + return (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0); +#else + return (mprotect(ptr, size, PROT_READ|PROT_WRITE) == 0); +#endif +} +GS_API_DECL void gs_memory_decommit(void* ptr, uint32_t size) +{ +#ifdef GS_PLATFORM_WINDOWS + VirtualFree(ptr, size, MEM_DECOMMIT); +#else + mprotect(ptr, size, PROT_NONE); + madvise(ptr, size, MADV_DONTNEED); +#endif +} +GS_API_DECL void gs_memory_release(void* ptr, uint32_t size) +{ +#ifdef GS_PLATFORM_WINDOWS + VirtualFree(ptr, 0, MEM_RELEASE); +#else + munmap(ptr, size); +#endif +} + + +// default arena functions + + +////////////////////////////////////////////////// +// TODO(Samdal): allow more customization +// +// typedef U32 ArenaFlags; +// enum +// { +// ArenaFlag_NoChain = (1<<0), +// ArenaFlag_LargePages = (1<<1), +// }; +// +// typedef struct ArenaParams ArenaParams; +// struct ArenaParams +// { +// ArenaFlags flags; +// U64 reserve_size; +// U64 commit_size; +// void *optional_backing_buffer; +// }; +// +/////////////////////////////////// + + +#define gs_arena_self_size (gs_max(sizeof(gs_arena), 64)) +#define GS_DEFAULT_ARENA_CMT_SIZE (64 << 10) +#define GS_DEFAULT_ARENA_RES_SIZE (64 << 20) +#define GS_DEFAULT_ARENA_VERY_BIG (GS_DEFAULT_ARENA_RES_SIZE - gs_arena_self_size)/2 + +#define _gs_align_pow2(x,b) (((x)+((b)-1))&(~((b)-1))) + + +static gs_arena* +gs_arena_alloc_size(uint64_t cmt, uint64_t res) +{ + gs_assert(gs_arena_self_size < cmt && cmt <= res); + uint64_t cmt_clamped = gs_min(cmt, res); + gs_arena* result = 0; + void *mem = gs_memory_reserve(res); + + if (gs_memory_commit(mem, cmt_clamped)) { + result = (gs_arena*)mem; + result->prev = 0; + result->current = result; + result->base_pos = 0; + result->pos = gs_arena_self_size; + result->cmt = cmt_clamped; + result->cap = res; + } + + return result; +} + +GS_API_DECL gs_arena* +gs_arena_alloc(void) +{ + return gs_arena_alloc_size(GS_DEFAULT_ARENA_CMT_SIZE, GS_DEFAULT_ARENA_RES_SIZE); +} + +GS_API_DECL void +gs_arena_release(gs_arena* arena) +{ + for (gs_arena *node = arena->current, *prev = 0; node; node = prev) { + prev = node->prev; + gs_memory_release(node, node->cap); + } +} + +static uint64_t +gs_arena_get_pos(gs_arena* arena) +{ + gs_arena *current = arena->current; + uint64_t result = current->base_pos + current->pos; + return result; +} + +GS_API_DECL void* +_gs_arena_push_nz(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) +{ + // try to be fast! + gs_arena *current = arena->current; + uint64_t pos = current->pos; + uint64_t pos_aligned = _gs_align_pow2(pos, align_bytes); + uint64_t new_pos = pos_aligned + size_bytes; + void *result = (uint8_t*)current + pos_aligned; + current->pos = new_pos; + + // if it's not going to work do the slow path + if (new_pos > current->cmt) { + result = 0; + current->pos = pos; + + // new chunk if necessary + if (new_pos > current->cap) { + gs_arena *new_arena = 0; + if (size_bytes > GS_DEFAULT_ARENA_VERY_BIG) { + uint64_t big_size_unrounded = size_bytes + gs_arena_self_size; + uint64_t big_size = _gs_align_pow2(big_size_unrounded, (4 << 10)); + new_arena = gs_arena_alloc_size(big_size, big_size); + } else { + new_arena = gs_arena_alloc(); + } + + // link in new chunk & recompute new_pos + if (new_arena != 0) { + new_arena->base_pos = current->base_pos + current->cap; + new_arena->prev = current; + current = new_arena; + arena->current = current; + pos_aligned = current->pos; + new_pos = pos_aligned + size_bytes; + } + } + + // move ahead if the current chunk has enough reserve + if (new_pos <= current->cap) { + + // extend commit if necessary + if (new_pos > current->cmt) { + uint64_t new_cmt_unclamped = _gs_align_pow2(new_pos, GS_DEFAULT_ARENA_CMT_SIZE); + uint64_t new_cmt = gs_min(new_cmt_unclamped, current->cap); + uint64_t cmt_size = new_cmt - current->cmt; + if (gs_memory_commit((uint8_t*)current + current->cmt, cmt_size)) { + current->cmt = new_cmt; + } + } + + // move ahead if the current chunk has enough commit + if (new_pos <= current->cmt) { + result = (uint8_t*)current + current->pos; + current->pos = new_pos; + } + } + } + + return result; +} + +GS_API_DECL void* +_gs_arena_push(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) +{ + return memset(_gs_arena_push_nz(arena, size_bytes, align_bytes), 0, size_bytes); +} + +static void +gs_arena_pop_to(gs_arena *arena, uint64_t pos) +{ + + // pop chunks in the chain + uint64_t pos_clamped = gs_max(gs_arena_self_size, pos); + { + gs_arena *node = arena->current; + for (gs_arena *prev = 0; node && node->base_pos >= pos; node = prev) { + prev = node->prev; + gs_memory_release(node, node->cap); + } + arena->current = node; + } + + // reset the pos of the current + { + gs_arena *current = arena->current; + uint64_t local_pos_unclamped = pos - current->base_pos; + uint64_t local_pos = gs_max(local_pos_unclamped, gs_arena_self_size); + current->pos = local_pos; + } +} + + +GS_API_DECL void +gs_arena_reset(gs_arena* arena) +{ + gs_arena_pop_to(arena, gs_arena_self_size); +} + +GS_API_DECL gs_arena_temp +gs_arena_begin_temp(gs_arena* arena) +{ + return (gs_arena_temp){ + .arena = arena, + .pos = gs_arena_get_pos(arena) + }; +} + +GS_API_DECL void +gs_arena_end_temp(gs_arena_temp temp) +{ + gs_arena_pop_to(temp.arena, temp.pos); +} + + +// arena scratch pool + + +#ifndef _gs_scratch_count +#define _gs_scratch_count 2 +#endif + +#ifdef _WIN32 +__declspec(thread) gs_arena* _gs_thread_scratch_pool[_gs_scratch_count] = {0, 0}; +#else +__thread gs_arena* _gs_thread_scratch_pool[_gs_scratch_count] = {0, 0}; +#endif + +GS_API_DECL gs_arena_temp +gs_arena_get_scratch(gs_arena **conflicts, uint64_t count) +{ + gs_arena** scratch_pool = _gs_thread_scratch_pool; + if (scratch_pool[0] == 0) { + gs_arena **arena_ptr = scratch_pool; + for (uint64_t i = 0; i < _gs_scratch_count; i += 1, arena_ptr += 1) { + *arena_ptr = gs_arena_alloc(); + } + } + gs_arena *result = 0; + gs_arena **arena_ptr = scratch_pool; + for (uint64_t i = 0; i < _gs_scratch_count; i += 1, arena_ptr += 1) { + gs_arena *arena = *arena_ptr; + gs_arena **conflict_ptr = conflicts; + for (uint32_t j = 0; j < count; j += 1, conflict_ptr += 1) { + if (arena == *conflict_ptr) { + arena = 0; + break; + } + } + if (arena != 0) { + result = arena; + break; + } + } + + return gs_arena_begin_temp(result); +} + + + + // typedef struct gs_memory_block_t { // uint8_t* data; // size_t size; diff --git a/impl/gs_platform_impl.h b/impl/gs_platform_impl.h index 15b7580..84623ea 100644 --- a/impl/gs_platform_impl.h +++ b/impl/gs_platform_impl.h @@ -901,281 +901,6 @@ gs_platform_library_proc_address_default_impl(void* lib, const char* func) return NULL; } -// === low level memory === // -#ifndef GS_PLATFORM_WINDOWS -#include -#endif // GS_PLATFORM_WINDOWS - -GS_API_DECL void* gs_platform_reserve(uint32_t size) -{ -#ifdef GS_PLATFORM_WINDOWS - return VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); -#else - return mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, (off_t)0); -#endif -} -GS_API_DECL bool32 gs_platform_commit(void* ptr, uint32_t size) -{ -#ifdef GS_PLATFORM_WINDOWS - return (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != 0); -#else - return (mprotect(ptr, size, PROT_READ|PROT_WRITE) == 0); -#endif -} -GS_API_DECL void gs_platform_decommit(void* ptr, uint32_t size) -{ -#ifdef GS_PLATFORM_WINDOWS - VirtualFree(ptr, size, MEM_DECOMMIT); -#else - mprotect(ptr, size, PROT_NONE); - madvise(ptr, size, MADV_DONTNEED); -#endif -} -GS_API_DECL void gs_platform_release(void* ptr, uint32_t size) -{ -#ifdef GS_PLATFORM_WINDOWS - VirtualFree(ptr, 0, MEM_RELEASE); -#else - munmap(ptr, size); -#endif -} - - -// default arena functions - - -////////////////////////////////////////////////// -// TODO(Samdal): allow more customization -// -// typedef U32 ArenaFlags; -// enum -// { -// ArenaFlag_NoChain = (1<<0), -// ArenaFlag_LargePages = (1<<1), -// }; -// -// typedef struct ArenaParams ArenaParams; -// struct ArenaParams -// { -// ArenaFlags flags; -// U64 reserve_size; -// U64 commit_size; -// void *optional_backing_buffer; -// }; -// -/////////////////////////////////// - - -#define gs_arena_self_size (gs_max(sizeof(gs_arena), 64)) -#define GS_DEFAULT_ARENA_CMT_SIZE (64 << 10) -#define GS_DEFAULT_ARENA_RES_SIZE (64 << 20) -#define GS_DEFAULT_ARENA_VERY_BIG (GS_DEFAULT_ARENA_RES_SIZE - gs_arena_self_size)/2 - -#define _gs_align_pow2(x,b) (((x)+((b)-1))&(~((b)-1))) - - -static gs_arena* -gs_arena_alloc_size(uint64_t cmt, uint64_t res) -{ - gs_assert(gs_arena_self_size < cmt && cmt <= res); - uint64_t cmt_clamped = gs_min(cmt, res); - gs_arena* result = 0; - void *mem = gs_platform_reserve(res); - - if (gs_platform_commit(mem, cmt_clamped)) { - result = (gs_arena*)mem; - result->prev = 0; - result->current = result; - result->base_pos = 0; - result->pos = gs_arena_self_size; - result->cmt = cmt_clamped; - result->cap = res; - } - - return result; -} - -GS_API_DECL gs_arena* -gs_arena_alloc(void) -{ - return gs_arena_alloc_size(GS_DEFAULT_ARENA_CMT_SIZE, GS_DEFAULT_ARENA_RES_SIZE); -} - -GS_API_DECL void -gs_arena_release(gs_arena* arena) -{ - for (gs_arena *node = arena->current, *prev = 0; node; node = prev) { - prev = node->prev; - gs_platform_release(node, node->cap); - } -} - -static uint64_t -gs_arena_get_pos(gs_arena* arena) -{ - gs_arena *current = arena->current; - uint64_t result = current->base_pos + current->pos; - return result; -} - -GS_API_DECL void* -_gs_arena_push_nz(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) -{ - // try to be fast! - gs_arena *current = arena->current; - uint64_t pos = current->pos; - uint64_t pos_aligned = _gs_align_pow2(pos, align_bytes); - uint64_t new_pos = pos_aligned + size_bytes; - void *result = (uint8_t*)current + pos_aligned; - current->pos = new_pos; - - // if it's not going to work do the slow path - if (new_pos > current->cmt) { - result = 0; - current->pos = pos; - - // new chunk if necessary - if (new_pos > current->cap) { - gs_arena *new_arena = 0; - if (size_bytes > GS_DEFAULT_ARENA_VERY_BIG) { - uint64_t big_size_unrounded = size_bytes + gs_arena_self_size; - uint64_t big_size = _gs_align_pow2(big_size_unrounded, (4 << 10)); - new_arena = gs_arena_alloc_size(big_size, big_size); - } else { - new_arena = gs_arena_alloc(); - } - - // link in new chunk & recompute new_pos - if (new_arena != 0) { - new_arena->base_pos = current->base_pos + current->cap; - new_arena->prev = current; - current = new_arena; - arena->current = current; - pos_aligned = current->pos; - new_pos = pos_aligned + size_bytes; - } - } - - // move ahead if the current chunk has enough reserve - if (new_pos <= current->cap) { - - // extend commit if necessary - if (new_pos > current->cmt) { - uint64_t new_cmt_unclamped = _gs_align_pow2(new_pos, GS_DEFAULT_ARENA_CMT_SIZE); - uint64_t new_cmt = gs_min(new_cmt_unclamped, current->cap); - uint64_t cmt_size = new_cmt - current->cmt; - if (gs_platform_commit((uint8_t*)current + current->cmt, cmt_size)) { - current->cmt = new_cmt; - } - } - - // move ahead if the current chunk has enough commit - if (new_pos <= current->cmt) { - result = (uint8_t*)current + current->pos; - current->pos = new_pos; - } - } - } - - return result; -} - -GS_API_DECL void* -_gs_arena_push(gs_arena* arena, uint64_t size_bytes, uint64_t align_bytes) -{ - return memset(_gs_arena_push_nz(arena, size_bytes, align_bytes), 0, size_bytes); -} - -static void -gs_arena_pop_to(gs_arena *arena, uint64_t pos) -{ - - // pop chunks in the chain - uint64_t pos_clamped = gs_max(gs_arena_self_size, pos); - { - gs_arena *node = arena->current; - for (gs_arena *prev = 0; node && node->base_pos >= pos; node = prev) { - prev = node->prev; - gs_platform_release(node, node->cap); - } - arena->current = node; - } - - // reset the pos of the current - { - gs_arena *current = arena->current; - uint64_t local_pos_unclamped = pos - current->base_pos; - uint64_t local_pos = gs_max(local_pos_unclamped, gs_arena_self_size); - current->pos = local_pos; - } -} - - -GS_API_DECL void -gs_arena_reset(gs_arena* arena) -{ - gs_arena_pop_to(arena, gs_arena_self_size); -} - -GS_API_DECL gs_arena_temp -gs_arena_begin_temp(gs_arena* arena) -{ - return (gs_arena_temp){ - .arena = arena, - .pos = gs_arena_get_pos(arena) - }; -} - -GS_API_DECL void -gs_arena_end_temp(gs_arena_temp temp) -{ - gs_arena_pop_to(temp.arena, temp.pos); -} - - -// arena scratch pool - - -#ifndef _gs_scratch_count -#define _gs_scratch_count 2 -#endif - -#ifdef _WIN32 -__declspec(thread) gs_arena* _gs_thread_scratch_pool[_gs_scratch_count] = {0, 0}; -#else -__thread gs_arena* _gs_thread_scratch_pool[_gs_scratch_count] = {0, 0}; -#endif - -GS_API_DECL gs_arena_temp -gs_arena_get_scratch(gs_arena **conflicts, uint64_t count) -{ - gs_arena** scratch_pool = _gs_thread_scratch_pool; - if (scratch_pool[0] == 0) { - gs_arena **arena_ptr = scratch_pool; - for (uint64_t i = 0; i < _gs_scratch_count; i += 1, arena_ptr += 1) { - *arena_ptr = gs_arena_alloc(); - } - } - gs_arena *result = 0; - gs_arena **arena_ptr = scratch_pool; - for (uint64_t i = 0; i < _gs_scratch_count; i += 1, arena_ptr += 1) { - gs_arena *arena = *arena_ptr; - gs_arena **conflict_ptr = conflicts; - for (uint32_t j = 0; j < count; j += 1, conflict_ptr += 1) { - if (arena == *conflict_ptr) { - arena = 0; - break; - } - } - if (arena != 0) { - result = arena; - break; - } - } - - return gs_arena_begin_temp(result); -} - #undef GS_PLATFORM_IMPL_DEFAULT #endif // GS_PLATFORM_IMPL_DEFAULT From 897d4a6f484269f2c5ed034db4cb4b9c735d1544 Mon Sep 17 00:00:00 2001 From: Samdal Date: Mon, 29 Jul 2024 13:52:22 +0200 Subject: [PATCH 7/8] remove whitespace --- impl/gs_platform_impl.h | 1 - 1 file changed, 1 deletion(-) diff --git a/impl/gs_platform_impl.h b/impl/gs_platform_impl.h index 84623ea..75beea7 100644 --- a/impl/gs_platform_impl.h +++ b/impl/gs_platform_impl.h @@ -901,7 +901,6 @@ gs_platform_library_proc_address_default_impl(void* lib, const char* func) return NULL; } - #undef GS_PLATFORM_IMPL_DEFAULT #endif // GS_PLATFORM_IMPL_DEFAULT From ff37985b475fb4b59b390d3339d4f28853432ec5 Mon Sep 17 00:00:00 2001 From: Samdal Date: Mon, 29 Jul 2024 13:54:44 +0200 Subject: [PATCH 8/8] change comment styling --- gs.h | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/gs.h b/gs.h index 7566af6..b111433 100644 --- a/gs.h +++ b/gs.h @@ -2732,8 +2732,9 @@ void gs_command_buffer_free(gs_command_buffer_t* cb) * @{ */ - -// === low level OS memory === // +/*================================================================================ +// Low Level OS Memory +================================================================================*/ GS_API_DECL void* gs_memory_reserve(uint32_t size); GS_API_DECL bool32 gs_memory_commit(void* ptr, uint32_t size); @@ -7518,10 +7519,13 @@ __gs_pqueue_pop_internal(void** pqueue, void* tmp, void** data, int32_t* priorit // GS_MEMORY ========================*/ -// === low level memory === // +/*================================================================================ +// Low Level OS Memory +================================================================================*/ + #ifndef GS_PLATFORM_WINDOWS #include -#endif // GS_PLATFORM_WINDOWS +#endif // !GS_PLATFORM_WINDOWS GS_API_DECL void* gs_memory_reserve(uint32_t size) { @@ -7557,8 +7561,9 @@ GS_API_DECL void gs_memory_release(void* ptr, uint32_t size) #endif } - -// default arena functions +/*================================================================================ +// Arena Allocator / Linear Allocator / Stack Allocator / Bump Allocator +================================================================================*/ ////////////////////////////////////////////////// @@ -7793,8 +7798,9 @@ gs_arena_get_scratch(gs_arena **conflicts, uint64_t count) return gs_arena_begin_temp(result); } - - +/*================================================================================ +// Memory Block +================================================================================*/ // typedef struct gs_memory_block_t { // uint8_t* data;