summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmniscient <omniscient.oce@gmail.com>2024-05-17 13:50:33 +1000
committerOmniscient <omniscient.oce@gmail.com>2024-05-17 13:50:33 +1000
commit519329e98467d0cdcc39720cef0f69c9936b6d55 (patch)
tree2837063ce51984dee00c6e2194e6f58ba189e8d8
parent9df999df385b74be5096218d206dd39988784237 (diff)
pool tests and try get macro working
-rw-r--r--src/physics/broadphase.h6
-rw-r--r--src/physics/collision.h8
-rw-r--r--src/physics/narrowphase.h6
-rw-r--r--src/renderer/backends/backend_vulkan.h3
-rw-r--r--src/renderer/backends/vulkan_helpers.h10
-rw-r--r--src/renderer/ral.c22
-rw-r--r--src/renderer/ral.h9
-rw-r--r--src/renderer/ral_types.h30
-rw-r--r--src/renderer/render.h16
-rw-r--r--src/std/mem.c67
-rw-r--r--src/std/mem.h24
-rw-r--r--tests/pool_test_runner.c12
-rw-r--r--tests/pool_tests.c72
-rw-r--r--xmake.lua17
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);
+}
diff --git a/xmake.lua b/xmake.lua
index 1d576c7..9b06db0 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -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")