diff options
author | Omniscient <omniscient.oce@gmail.com> | 2024-05-17 13:50:33 +1000 |
---|---|---|
committer | Omniscient <omniscient.oce@gmail.com> | 2024-05-17 13:50:33 +1000 |
commit | 519329e98467d0cdcc39720cef0f69c9936b6d55 (patch) | |
tree | 2837063ce51984dee00c6e2194e6f58ba189e8d8 | |
parent | 9df999df385b74be5096218d206dd39988784237 (diff) |
pool tests and try get macro working
-rw-r--r-- | src/physics/broadphase.h | 6 | ||||
-rw-r--r-- | src/physics/collision.h | 8 | ||||
-rw-r--r-- | src/physics/narrowphase.h | 6 | ||||
-rw-r--r-- | src/renderer/backends/backend_vulkan.h | 3 | ||||
-rw-r--r-- | src/renderer/backends/vulkan_helpers.h | 10 | ||||
-rw-r--r-- | src/renderer/ral.c | 22 | ||||
-rw-r--r-- | src/renderer/ral.h | 9 | ||||
-rw-r--r-- | src/renderer/ral_types.h | 30 | ||||
-rw-r--r-- | src/renderer/render.h | 16 | ||||
-rw-r--r-- | src/std/mem.c | 67 | ||||
-rw-r--r-- | src/std/mem.h | 24 | ||||
-rw-r--r-- | tests/pool_test_runner.c | 12 | ||||
-rw-r--r-- | tests/pool_tests.c | 72 | ||||
-rw-r--r-- | xmake.lua | 17 |
14 files changed, 261 insertions, 41 deletions
diff --git a/src/physics/broadphase.h b/src/physics/broadphase.h index 43b57f6..8b49716 100644 --- a/src/physics/broadphase.h +++ b/src/physics/broadphase.h @@ -1,10 +1,10 @@ /** * @file broadphase.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-05-12 - * + * * @copyright Copyright (c) 2024 - * + * */
\ No newline at end of file diff --git a/src/physics/collision.h b/src/physics/collision.h index 3b65b1b..cca6042 100644 --- a/src/physics/collision.h +++ b/src/physics/collision.h @@ -1,17 +1,17 @@ /** * @file collision.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-05-12 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once #include "geometry.h" - enum collider_type { +enum collider_type { cuboid_collider, sphere_collider, }; diff --git a/src/physics/narrowphase.h b/src/physics/narrowphase.h index 501c690..2368c49 100644 --- a/src/physics/narrowphase.h +++ b/src/physics/narrowphase.h @@ -1,10 +1,10 @@ /** * @file narrowphase.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-05-12 - * + * * @copyright Copyright (c) 2024 - * + * */
\ No newline at end of file diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h index 7bdf821..77b9f94 100644 --- a/src/renderer/backends/backend_vulkan.h +++ b/src/renderer/backends/backend_vulkan.h @@ -4,8 +4,8 @@ #include <vulkan/vulkan_core.h> #include "defines.h" +#include "mem.h" #include "ral.h" -// #include "vulkan_helpers.h" #define MAX_FRAMES_IN_FLIGHT 2 #define GPU_SWAPCHAIN_IMG_COUNT 2 @@ -102,4 +102,3 @@ typedef struct gpu_buffer { VkDeviceMemory memory; u64 size; } gpu_buffer; - diff --git a/src/renderer/backends/vulkan_helpers.h b/src/renderer/backends/vulkan_helpers.h index db9b5a4..23666c6 100644 --- a/src/renderer/backends/vulkan_helpers.h +++ b/src/renderer/backends/vulkan_helpers.h @@ -20,12 +20,12 @@ static void plat_get_required_extension_names(cstr_darray* extensions) { } // TODO(omni): port to using internal assert functions -#define VK_CHECK(vulkan_expr) \ - do { \ - VkResult res = vulkan_expr; \ - if (res != VK_SUCCESS) { \ +#define VK_CHECK(vulkan_expr) \ + do { \ + VkResult res = vulkan_expr; \ + if (res != VK_SUCCESS) { \ ERROR_EXIT("Vulkan error: %u (%s:%d)", res, __FILE__, __LINE__); \ - } \ + } \ } while (0) // TODO: typedef struct vk_debugger {} vk_debugger; diff --git a/src/renderer/ral.c b/src/renderer/ral.c new file mode 100644 index 0000000..25c2909 --- /dev/null +++ b/src/renderer/ral.c @@ -0,0 +1,22 @@ +#include "ral.h" + +/* typedef struct foo { */ +/* u32 a; */ +/* f32 b; */ +/* char c; */ +/* } foo; */ + +/* TYPED_POOL(gpu_buffer, buffer); */ + +/* typedef struct buffer_handle { */ +/* u32 raw; */ +/* } buffer_handle; */ + +/* typedef struct gpu_buffer gpu_buffer; */ +TYPED_POOL(gpu_buffer, buffer); +TYPED_POOL(gpu_texture, texture); + +struct resource_pools { + buffer_pool buffers; + texture_pool textures; +}; diff --git a/src/renderer/ral.h b/src/renderer/ral.h index ee65233..03bdeab 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -13,6 +13,7 @@ #include "buf.h" #include "defines.h" +#include "mem.h" #include "ral_types.h" #include "str.h" @@ -40,6 +41,8 @@ typedef struct gpu_backend_pools { // pools for each gpu structure } gpu_backend_pools; +typedef struct resource_pools resource_pools; + typedef enum pipeline_kind { PIPELINE_GRAPHICS, PIPELINE_COMPUTE, @@ -78,11 +81,6 @@ struct graphics_pipeline_desc { typedef struct gpu_renderpass_desc { } gpu_renderpass_desc; -typedef struct resource_pools { - // TODO: buffer pool - // TODO: texture pool -} resource_pools; - // --- Lifecycle functions bool gpu_backend_init(const char* window_name, struct GLFWwindow* window); @@ -163,4 +161,3 @@ void vertex_desc_add(vertex_description* builder, const char* name, vertex_attri // TEMP void gpu_temp_draw(size_t n_verts); - diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index c802a9b..5d4e88a 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -16,15 +16,24 @@ #define MAX_VERTEX_ATTRIBUTES 16 -#ifndef RENDERER_TYPED_HANDLES +/* #ifndef RENDERER_TYPED_HANDLES */ CORE_DEFINE_HANDLE(buffer_handle); CORE_DEFINE_HANDLE(texture_handle); CORE_DEFINE_HANDLE(sampler_handle); CORE_DEFINE_HANDLE(shader_handle); CORE_DEFINE_HANDLE(model_handle); #define ABSENT_MODEL_HANDLE 999999999 -#define RENDERER_TYPED_HANDLES -#endif + +/* #define RENDERER_TYPED_HANDLES */ +/* #endif */ + +/* typedef struct gpu_buffer { */ +/* u32 a; */ +/* } gpu_buffer; */ + +/* #ifndef RAL_TYPED_POOLS */ +/* #define RAL_TYPED_POOLS */ +/* #endif */ // gpu types typedef enum gpu_primitive_topology { @@ -57,6 +66,9 @@ typedef struct texture_desc { u32x2 extents; } texture_desc; +typedef struct gpu_texture { +} gpu_texture; + typedef enum gpu_buffer_type { CEL_BUFFER_DEFAULT, // on Vulkan this would be a storage buffer? CEL_BUFFER_VERTEX, @@ -157,11 +169,12 @@ typedef struct vertex_description { typedef enum shader_visibility { VISIBILITY_VERTEX = 1 << 0, - VISIBILITY_FRAGMENT = 1 << 1 , + VISIBILITY_FRAGMENT = 1 << 1, VISIBILITY_COMPUTE = 1 << 2, } shader_visibility; -/** @brief Describes the kind of binding a `shader_binding` is for. This changes how we create backing data for it. */ +/** @brief Describes the kind of binding a `shader_binding` is for. This changes how we create + * backing data for it. */ typedef enum shader_binding_type { /** * @brief Binds a buffer to a shader @@ -205,7 +218,7 @@ typedef struct shader_binding { #define MAX_LAYOUT_BINDINGS 8 -/** @brief A list of bindings that describe what data a shader / pipeline expects +/** @brief A list of bindings that describe what data a shader / pipeline expects @note This roughly correlates to a descriptor set layout in Vulkan */ typedef struct shader_data_layout { @@ -221,8 +234,9 @@ typedef struct shader_data { /* Usage: - 1. When we create the pipeline, we must call a function that return a layout without .data fields - 2. When binding + 1. When we create the pipeline, we must call a function that return a layout without .data + fields + 2. When binding */ typedef enum gpu_cull_mode { CULL_BACK_FACE, CULL_FRONT_FACE, CULL_COUNT } gpu_cull_mode; diff --git a/src/renderer/render.h b/src/renderer/render.h index c87e5f7..5657fc1 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -26,8 +26,8 @@ typedef struct camera camera; void gfx_backend_draw_frame(renderer* ren, camera* camera, mat4 model, texture* tex); typedef struct render_ctx { - mat4 view; - mat4 projection; + mat4 view; + mat4 projection; } render_ctx; // frontend -- these can be called from say a loop in an example, or via FFI @@ -47,15 +47,15 @@ void shader_hot_reload(const char* filepath); /** * @brief Creates buffers and returns a struct that holds handles to our resources - * - * @param geometry - * @param free_on_upload frees the CPU-side vertex/index data stored in geometry_data when we successfully upload - that data to the GPU-side buffer - * @return mesh + * + * @param geometry + * @param free_on_upload frees the CPU-side vertex/index data stored in geometry_data when we + successfully upload that data to the GPU-side buffer + * @return mesh */ mesh mesh_create(geometry_data* geometry, bool free_on_upload); -void draw_mesh(mesh* mesh, mat4* model);//, mat4* view, mat4* proj); // TODO: material +void draw_mesh(mesh* mesh, mat4* model); //, mat4* view, mat4* proj); // TODO: material model_handle model_load(const char* debug_name, const char* filepath); diff --git a/src/std/mem.c b/src/std/mem.c index 7d768c9..a5321fb 100644 --- a/src/std/mem.c +++ b/src/std/mem.c @@ -1,8 +1,10 @@ -#include "mem.h" +#include <assert.h> #include <stddef.h> #include <stdint.h> #include <string.h> + #include "log.h" +#include "mem.h" #ifndef DEFAULT_ALIGNMENT #define DEFAULT_ALIGNMENT (2 * sizeof(void*)) @@ -58,3 +60,66 @@ void_pool void_pool_create(arena* a, u64 capacity, u64 entry_size) { return pool; } + +void void_pool_free_all(void_pool* pool) { + // set all entries to be free + for (u64 i = 0; i < pool->capacity; i++) { + void* ptr = &pool->backing_buffer[i * pool->entry_size]; + void_pool_header* free_node = + (void_pool_header*)ptr; // we reuse the actual entry itself to hold the header + if (i == (pool->capacity - 1)) { + // if the last one we make its next pointer NULL indicating its full + free_node->next = NULL; + } + free_node->next = pool->free_list_head; + // now the head points to this entry + pool->free_list_head = free_node; + } +} + +void* void_pool_get(void_pool* pool, u32 raw_handle) { + // An handle is an index into the array essentially + void* ptr = pool->backing_buffer + (raw_handle * pool->entry_size); + return ptr; +} + +void* void_pool_alloc(void_pool* pool, u32* out_raw_handle) { + // get the next free node + if (pool->count == pool->capacity) { + WARN("Pool is full!"); + return NULL; + } + if (pool->free_list_head == NULL) { + ERROR("Pool is full (head = null)"); + return NULL; + } + void_pool_header* free_node = pool->free_list_head; + + // What index does this become? + uintptr_t start = (uintptr_t)pool->backing_buffer; + uintptr_t cur = (uintptr_t)free_node; + TRACE("%ld %ld ", start, cur); + /* assert(cur > start); */ + u32 index = (u32)((cur - start) / pool->entry_size); + printf("Index %d\n", index); + if (out_raw_handle != NULL) { + *out_raw_handle = index; + } + + pool->free_list_head = free_node->next; + + memset(free_node, 0, pool->entry_size); + pool->count++; + return (void*)free_node; +} + +void void_pool_dealloc(void_pool* pool, u32 raw_handle) { + // push free node back onto the free list + void* ptr = void_pool_get(pool, raw_handle); + void_pool_header* freed_node = (void_pool_header*)ptr; + + freed_node->next = pool->free_list_head; + pool->free_list_head = freed_node; + + pool->count--; +} diff --git a/src/std/mem.h b/src/std/mem.h index eef97a0..26da778 100644 --- a/src/std/mem.h +++ b/src/std/mem.h @@ -54,6 +54,28 @@ void_pool void_pool_create(arena* a, u64 capacity, u64 entry_size); void void_pool_free_all(void_pool* pool); bool void_pool_is_empty(void_pool* pool); bool void_pool_is_full(void_pool* pool); -void* void_pool_get(u32 raw_handle); +void* void_pool_get(void_pool* pool, u32 raw_handle); +void* void_pool_alloc(void_pool* pool, u32* out_raw_handle); +void void_pool_dealloc(void_pool* pool, u32 raw_handle); // TODO: macro that lets us specialise + +/* typedef struct Name##_handle Name##_handle; \ */ +#define TYPED_POOL(T, Name) \ + typedef struct Name##_pool { \ + void_pool inner; \ + } Name##_pool; \ + \ + static Name##_pool Name##_pool_create(arena* a, u64 cap, u64 entry_size) { \ + void_pool p = void_pool_create(a, cap, entry_size); \ + return (Name##_pool){ .inner = p }; \ + } \ + static inline T* Name##_pool_get(Name##_pool* pool, Name##_handle handle) { \ + return (T*)void_pool_get(&pool->inner, handle.raw); \ + } \ + static inline T* Name##_pool_alloc(Name##_pool* pool, Name##_handle* out_handle) { \ + return (T*)void_pool_alloc(&pool->inner, &out_handle->raw); \ + } \ + static inline void Name##_pool_dealloc(Name##_pool* pool, Name##_handle handle) { \ + void_pool_dealloc(&pool->inner, handle.raw); \ + }\ diff --git a/tests/pool_test_runner.c b/tests/pool_test_runner.c new file mode 100644 index 0000000..a6eff69 --- /dev/null +++ b/tests/pool_test_runner.c @@ -0,0 +1,12 @@ +#include "unity.h" +#include "unity_fixture.h" + +TEST_GROUP_RUNNER(Pool) { + // TODO: test cases + RUN_TEST_CASE(Pool, Initialisation); + RUN_TEST_CASE(Pool, TypedPool); +} + +static void RunAllTests(void) { RUN_TEST_GROUP(Pool); } + +int main(int argc, const char* argv[]) { return UnityMain(argc, argv, RunAllTests); } diff --git a/tests/pool_tests.c b/tests/pool_tests.c new file mode 100644 index 0000000..df65773 --- /dev/null +++ b/tests/pool_tests.c @@ -0,0 +1,72 @@ +#include <stdbool.h> +#include <stdlib.h> +#include "defines.h" +#include "unity.h" +#include "unity_fixture.h" + +#include "mem.h" + +#define ARENA_SIZE (1024 * 1024) + +static arena a; + +TEST_GROUP(Pool); + +TEST_SETUP(Pool) { a = arena_create(malloc(ARENA_SIZE), ARENA_SIZE); } + +TEST_TEAR_DOWN(Pool) { arena_free_all(&a); } + +TEST(Pool, SanityCheckTest) { TEST_ASSERT_EQUAL(true, true); } + +TEST(Pool, Initialisation) { + // u32 pool + void_pool pool = void_pool_create(&a, 256, sizeof(u32)); + u32 x_handle; + u32* x_ptr = (u32*)void_pool_alloc(&pool, &x_handle); + // store something in it + *x_ptr = 1024; + u32* x = void_pool_get(&pool, x_handle); + + TEST_ASSERT_EQUAL_UINT32(1024, *x); + /* TEST_ASSERT_EQUAL_MEMORY(&expected, &actual, sizeof(vec3)); */ +} + +typedef struct foo { + u32 a; + f32 b; + char c; +} foo; + +CORE_DEFINE_HANDLE(bar); +typedef struct bar_handle { + u32 raw; +} bar_handle; +TYPED_POOL(foo, bar); + +TEST(Pool, TypedPool) { + printf("Typed pool test\n"); + // create pool + bar_pool pool = bar_pool_create(&a, 2, sizeof(foo)); + + bar_handle first_handle, second_handle, third_handle; + foo* first = bar_pool_alloc(&pool, &first_handle); + foo* second = bar_pool_alloc(&pool, &second_handle); + // Third one shouldnt work + foo* third = bar_pool_alloc(&pool, &third_handle); + TEST_ASSERT_NULL(third); + + first->a = 32; + first->b = 2.0; + first->c = 'X'; + + foo* my_foo = bar_pool_get(&pool, first_handle); + TEST_ASSERT_EQUAL_UINT32(32, my_foo->a); + TEST_ASSERT_EQUAL(2.0, my_foo->b); + TEST_ASSERT_EQUAL_CHAR('X', my_foo->c); + + bar_pool_dealloc(&pool, first_handle); + + // next alloc should succeed + third = bar_pool_alloc(&pool, &third_handle); + TEST_ASSERT_NOT_NULL(third); +} @@ -68,6 +68,12 @@ local core_sources = { "src/systems/*.c", } +local unity_sources = { + "deps/Unity/src/unity.c", + "deps/Unity/extras/fixture/src/unity_fixture.c", + "deps/Unity/extras/memory/src/unity_memory.c", +} + rule("compile_glsl_vert_shaders") set_extensions(".vert") on_buildcmd_file(function (target, batchcmds, sourcefile, opt) @@ -229,3 +235,14 @@ target("cube") -- add_deps("core_static") -- add_files("examples/demo/demo.c") -- set_rundir("$(projectdir)") + +target("pool_tests") + set_kind("binary") + set_group("tests") + add_deps("core_static") + add_files(unity_sources) + add_includedirs("deps/Unity/src", {public = true}) + add_includedirs("deps/Unity/extras/fixture/src", {public = true}) + add_includedirs("deps/Unity/extras/memory/src", {public = true}) + add_files("tests/pool_tests.c") + add_files("tests/pool_test_runner.c") |