From 1f2809d23e8dbd63cbd97e9ad1cf4d961e9c4b66 Mon Sep 17 00:00:00 2001 From: Charlie <66182434+asbott@users.noreply.github.com> Date: Tue, 2 Jul 2024 19:12:31 +0200 Subject: [PATCH] Ooga'd some boogas --- build.c | 12 +++- entry_randygame.c | 3 +- oogabooga/base.c | 8 +++ .../examples/berry_bush.png | Bin hammer.png => oogabooga/examples/hammer.png | Bin .../examples/minimal_game_loop.c | 0 .../examples/renderer_stress_test.c | 6 +- oogabooga/memory.c | 24 ++++++-- oogabooga/oogabooga.c | 13 ++++- oogabooga/os_impl_windows.c | 55 +++++++++++++++++- oogabooga/os_interface.c | 2 + oogabooga/tests.c | 23 ++++++-- 12 files changed, 124 insertions(+), 22 deletions(-) rename berry_bush.png => oogabooga/examples/berry_bush.png (100%) rename hammer.png => oogabooga/examples/hammer.png (100%) rename entry_minimal_example.c => oogabooga/examples/minimal_game_loop.c (100%) rename entry_engine_test.c => oogabooga/examples/renderer_stress_test.c (90%) diff --git a/build.c b/build.c index 150e60b..b7a0bf9 100644 --- a/build.c +++ b/build.c @@ -2,6 +2,7 @@ /// // Build config stuff + #define RUN_TESTS 0 // This is only for people developing oogabooga! @@ -9,6 +10,8 @@ #define ENABLE_PROFILING 0 +#define INITIAL_PROGRAM_MEMORY_SIZE MB(5) + // When we need very debug // #define CONFIGURATION VERY_DEBUG @@ -20,12 +23,15 @@ typedef struct Context_Extra { #define GFX_RENDERER GFX_RENDERER_D3D11 +// This defaults to "entry", but we can set it to anything (except "main" or other existing proc names" +#define ENTRY_PROC entry + #include "oogabooga/oogabooga.c" // // Comment & Uncomment to swap projects -// #include "entry_engine_test.c" -// #include "entry_minimal_example.c" - #include "entry_randygame.c" \ No newline at end of file +// #include "oogabooga/examples/renderer_stress_test.c" +// #include "oogabooga/examples/minimal_game_loop.c" +#include "entry_randygame.c" \ No newline at end of file diff --git a/entry_randygame.c b/entry_randygame.c index 089d2c5..3fce173 100644 --- a/entry_randygame.c +++ b/entry_randygame.c @@ -7,10 +7,11 @@ int entry(int argc, char **argv) { window.x = 200; window.y = 200; window.clear_color = hex_to_rgba(0x2a2d3aff); - + Gfx_Image* player = load_image_from_disk(STR("player.png"), get_heap_allocator()); assert(player, "fuckie wucky happen"); + Vector2 player_pos = v2(0, 0); float64 seconds_counter = 0.0; s32 frame_count = 0; diff --git a/oogabooga/base.c b/oogabooga/base.c index fa3d573..b9bc88a 100644 --- a/oogabooga/base.c +++ b/oogabooga/base.c @@ -196,7 +196,15 @@ thread_local u64 num_contexts = 0; forward_global thread_local Allocator temp; +void* memset(void* dest, int value, size_t amount); void* alloc(Allocator allocator, u64 size) { + void *p = allocator.proc(size, 0, ALLOCATOR_ALLOCATE, allocator.data); +#if DO_ZERO_INITIALIZATION + memset(p, 0, size); +#endif + return p; +} +void* alloc_uninitialized(Allocator allocator, u64 size) { return allocator.proc(size, 0, ALLOCATOR_ALLOCATE, allocator.data); } void dealloc(Allocator allocator, void *p) { diff --git a/berry_bush.png b/oogabooga/examples/berry_bush.png similarity index 100% rename from berry_bush.png rename to oogabooga/examples/berry_bush.png diff --git a/hammer.png b/oogabooga/examples/hammer.png similarity index 100% rename from hammer.png rename to oogabooga/examples/hammer.png diff --git a/entry_minimal_example.c b/oogabooga/examples/minimal_game_loop.c similarity index 100% rename from entry_minimal_example.c rename to oogabooga/examples/minimal_game_loop.c diff --git a/entry_engine_test.c b/oogabooga/examples/renderer_stress_test.c similarity index 90% rename from entry_engine_test.c rename to oogabooga/examples/renderer_stress_test.c index 3a57583..0b81cd7 100644 --- a/entry_engine_test.c +++ b/oogabooga/examples/renderer_stress_test.c @@ -10,9 +10,9 @@ int entry(int argc, char **argv) { window.clear_color = hex_to_rgba(0x2a2d3aff); - Gfx_Image *bush_image = load_image_from_disk(STR("berry_bush.png"), get_heap_allocator()); + Gfx_Image *bush_image = load_image_from_disk(STR("oogabooga/examples/berry_bush.png"), get_heap_allocator()); assert(bush_image, "Failed loading berry_bush.png"); - Gfx_Image *hammer_image = load_image_from_disk(STR("hammer.png"), get_heap_allocator()); + Gfx_Image *hammer_image = load_image_from_disk(STR("oogabooga/examples/hammer.png"), get_heap_allocator()); assert(hammer_image, "Failed loading hammer.png"); seed_for_random = os_get_current_cycle_count(); @@ -50,7 +50,7 @@ int entry(int argc, char **argv) { if (is_key_just_released('Q')) { delete_image(bush_image); - bush_image = load_image_from_disk(STR("berry_bush.png"), get_heap_allocator()); + bush_image = load_image_from_disk(STR("oogabooga/examples/berry_bush.png"), get_heap_allocator()); assert(bush_image, "Failed loading berry_bush.png"); } diff --git a/oogabooga/memory.c b/oogabooga/memory.c index e1f1487..aaf040d 100644 --- a/oogabooga/memory.c +++ b/oogabooga/memory.c @@ -1,11 +1,15 @@ +#define KB(x) (x*1024ull) +#define MB(x) ((KB(x))*1024ull) +#define GB(x) ((MB(x))*1024ull) + void* program_memory = 0; u64 program_memory_size = 0; #ifndef INIT_MEMORY_SIZE - #define INIT_MEMORY_SIZE (1024*50) + #define INIT_MEMORY_SIZE KB(50) #endif // We may need to allocate stuff in initialization time before the heap is ready. // That's what this is for. @@ -50,7 +54,8 @@ Allocator get_initialization_allocator() { // We could fix it by merging free nodes every now and then // BUT: We aren't really supposed to allocate/deallocate directly on the heap too much anyways... -#define DEFAULT_HEAP_BLOCK_SIZE min((os.page_size * 1024ULL * 50ULL), program_memory_size) +#define MAX_HEAP_BLOCK_SIZE ((MB(500)+os.page_size)& ~(os.page_size-1)) +#define DEFAULT_HEAP_BLOCK_SIZE (min(MAX_HEAP_BLOCK_SIZE, program_memory_size)) #define HEAP_ALIGNMENT (sizeof(Heap_Free_Node)) typedef struct Heap_Free_Node Heap_Free_Node; typedef struct Heap_Block Heap_Block; @@ -187,7 +192,7 @@ Heap_Block *make_heap_block(Heap_Block *parent, u64 size) { // #Speed #Cleanup if (((u8*)block)+size >= ((u8*)program_memory)+program_memory_size) { u64 minimum_size = ((u8*)block+size) - (u8*)program_memory + 1; - u64 new_program_size = (cast(u64)(minimum_size * 1.5)); + u64 new_program_size = max((cast(u64)(minimum_size*2)), program_memory_size*2); assert(new_program_size >= minimum_size, "Bröd"); const u64 ATTEMPTS = 1000; for (u64 i = 0; i <= ATTEMPTS; i++) { @@ -226,7 +231,7 @@ void *heap_alloc(u64 size) { size = (size+HEAP_ALIGNMENT) & ~(HEAP_ALIGNMENT-1); - assert(size < DEFAULT_HEAP_BLOCK_SIZE, "Past Charlie has been lazy and did not handle large allocations like this. I apologize on behalf of past Charlie. A quick fix could be to increase the heap block size for now."); + assert(size < MAX_HEAP_BLOCK_SIZE, "Past Charlie has been lazy and did not handle large allocations like this. I apologize on behalf of past Charlie. A quick fix could be to increase the heap block size for now."); Heap_Block *block = heap_head; Heap_Block *last_block = 0; @@ -237,6 +242,13 @@ void *heap_alloc(u64 size) { // #Speed // Maybe instead of going through EVERY free node to find best fit we do a good-enough fit while (block != 0) { + + if (block->size < size) { + last_block = block; + block = block->next; + continue; + } + Heap_Search_Result result = search_heap_block(block, size); Heap_Free_Node *node = result.best_fit; if (node) { @@ -263,7 +275,7 @@ void *heap_alloc(u64 size) { } if (!best_fit) { - block = make_heap_block(last_block, DEFAULT_HEAP_BLOCK_SIZE); + block = make_heap_block(last_block, max(DEFAULT_HEAP_BLOCK_SIZE, size)); previous = 0; best_fit = block->free_head; best_fit_block = block; @@ -423,7 +435,7 @@ Allocator get_heap_allocator() { /// #ifndef TEMPORARY_STORAGE_SIZE - #define TEMPORARY_STORAGE_SIZE (1024ULL*1024ULL*16ULL) // 16mb + #define TEMPORARY_STORAGE_SIZE (1024ULL*1024ULL*2ULL) // 2mb #endif void* talloc(u64); diff --git a/oogabooga/oogabooga.c b/oogabooga/oogabooga.c index f29b852..1c37fd4 100644 --- a/oogabooga/oogabooga.c +++ b/oogabooga/oogabooga.c @@ -1,4 +1,5 @@ + #define DEBUG 0 #define VERY_DEBUG 1 #define RELEASE 2 @@ -17,6 +18,10 @@ #define ENTRY_PROC entry #endif +#ifndef DO_ZERO_INITIALIZATION + #define DO_ZERO_INITIALIZATION 1 +#endif + #define WINDOWS 0 #define LINUX 1 #define MACOS 2 @@ -213,7 +218,7 @@ void oogabooga_init(u64 program_memory_size) { } #ifndef INITIAL_PROGRAM_MEMORY_SIZE - #define INITIAL_PROGRAM_MEMORY_SIZE (1024ULL * 1024ULL * 100ULL) // Start with 100mb program memory + #define INITIAL_PROGRAM_MEMORY_SIZE (max((1024ULL * 1024ULL * 100ULL), TEMPORARY_STORAGE_SIZE*2)) #endif #ifndef RUN_TESTS #define RUN_TESTS 0 @@ -223,8 +228,12 @@ void oogabooga_init(u64 program_memory_size) { int ENTRY_PROC(int argc, char **argv); int main(int argc, char **argv) { - oogabooga_init(INITIAL_PROGRAM_MEMORY_SIZE); + + printf("Ooga booga program started\n"); + oogabooga_init(INITIAL_PROGRAM_MEMORY_SIZE); + + assert(main != ENTRY_PROC, "You've ooga'd your last booga"); // This can be disabled in build.c #if RUN_TESTS diff --git a/oogabooga/os_impl_windows.c b/oogabooga/os_impl_windows.c index 15e69fd..207ef10 100644 --- a/oogabooga/os_impl_windows.c +++ b/oogabooga/os_impl_windows.c @@ -1,6 +1,6 @@ -#define VIRTUAL_MEMORY_BASE ((void*)0x0000010000000000ULL) +#define VIRTUAL_MEMORY_BASE ((void*)0x0000690000000000ULL) void* heap_alloc(u64); void heap_dealloc(void*); @@ -238,6 +238,48 @@ void os_init(u64 program_memory_size) { +} + +void s64_to_null_terminated_string_reverse(char str[], int length) +{ + int start = 0; + int end = length - 1; + while (start < end) { + char temp = str[start]; + str[start] = str[end]; + str[end] = temp; + end--; + start++; + } +} + +void s64_to_null_terminated_string(s64 num, char* str, int base) +{ + int i = 0; + bool neg = false; + + if (num == 0) { + str[i++] = '0'; + str[i] = '\0'; + return; + } + + if (num < 0 && base == 10) { + neg = true; + num = -num; + } + + while (num != 0) { + int rem = num % base; + str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0'; + num = num / base; + } + + if (neg) + str[i++] = '-'; + + str[i] = '\0'; + s64_to_null_terminated_string_reverse(str, i); } bool os_grow_program_memory(u64 new_size) { @@ -275,6 +317,10 @@ bool os_grow_program_memory(u64 new_size) { assert(m == 0, "amount_to_allocate is not aligned to granularity!"); // Just keep allocating at the tail of the current chunk void* result = VirtualAlloc(tail, amount_to_allocate, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + assert(result == tail); +#if CONFIGURATION == DEBUG + volatile u8 a = *(u8*)tail = 69; +#endif memset(result, 0xBA, amount_to_allocate); if (result == 0) { os_unlock_mutex(program_memory_mutex); // #Sync @@ -289,7 +335,12 @@ bool os_grow_program_memory(u64 new_size) { } + char size_str[32]; + s64_to_null_terminated_string(program_memory_size/1024, size_str, 10); + os_write_string_to_stdout(STR("Program memory grew to ")); + os_write_string_to_stdout(STR(size_str)); + os_write_string_to_stdout(STR(" kb\n")); os_unlock_mutex(program_memory_mutex); // #Sync return true; } @@ -440,7 +491,7 @@ void os_high_precision_sleep(f64 ms) { f64 start = os_get_current_time_in_seconds(); f64 end = start + (f64)s; - u32 sleep_time = (u32)((end-start)-1.0); + s32 sleep_time = (s32)((end-start)-1.0); bool do_sleep = sleep_time >= 1; timeBeginPeriod(1); // I don't see a reason to reset this diff --git a/oogabooga/os_interface.c b/oogabooga/os_interface.c index 182981a..c9e0d8e 100644 --- a/oogabooga/os_interface.c +++ b/oogabooga/os_interface.c @@ -91,6 +91,8 @@ inline int crt_vprintf(const char* fmt, va_list args) { } #endif +inline bool bytes_match(void *a, void *b, u64 count) { return memcmp(a, b, count) == 0; } + inline int vsnprintf(char* buffer, size_t n, const char* fmt, va_list args) { return os.crt_vsnprintf(buffer, n, fmt, args); } diff --git a/oogabooga/tests.c b/oogabooga/tests.c index 2d23b17..a2af6b5 100644 --- a/oogabooga/tests.c +++ b/oogabooga/tests.c @@ -47,15 +47,23 @@ void test_allocator(bool do_log_heap) { assert(*c == 1337, "Test failed: Memory corrupted"); // Test growing memory - os_grow_program_memory(1024 * 1024 * 1000); + //os_grow_program_memory(1024 * 1024 * 1000); assert(*a == 69, "Test failed: Memory corrupted"); assert(*b == 420, "Test failed: Memory corrupted"); assert(*c == 1337, "Test failed: Memory corrupted"); - + + u8 check_bytes[1024]; + for (u64 i = 0; i < 1024; i += 4) { + *((int*)&check_bytes[i]) = (int)get_random(); + } + u8 *check_bytes_copy = (u8*)alloc(heap, 1024); + memcpy(check_bytes_copy, check_bytes, 1024); + + // Allocate and free large block - void* large_block = alloc(heap, 1024 * 1024 * 100); - dealloc(heap, large_block); + //void* large_block = alloc(heap, 1024 * 1024 * 100); + //dealloc(heap, large_block); // Allocate multiple small blocks void* blocks[100]; @@ -75,6 +83,7 @@ void test_allocator(bool do_log_heap) { dealloc(heap, p); } + // Free in reverse order for (int i = 0; i < 100; ++i) { blocks[i] = alloc(heap, 128); @@ -93,7 +102,7 @@ void test_allocator(bool do_log_heap) { nums[i][j] = i * 10 + j; } } - + for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { assert(nums[i][j] == i * 10 + j, "Memory corruption detected"); @@ -102,8 +111,10 @@ void test_allocator(bool do_log_heap) { } + reset_temporary_storage(); + int* foo = (int*)alloc(temp, 72); *foo = 1337; void* bar = alloc(temp, 69); @@ -174,6 +185,8 @@ void test_allocator(bool do_log_heap) { dealloc(heap, blocks[i]); } + assert(bytes_match(check_bytes, check_bytes_copy, 1024), "Memory corrupt"); + if (do_log_heap) log_heap(); }