From e5495790aeba905505152ad3b6690f459a44df03 Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Fri, 5 Apr 2024 00:28:24 +1100 Subject: close. --- src/std/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/std/mem.c') diff --git a/src/std/mem.c b/src/std/mem.c index d7c0f4c..25c9563 100644 --- a/src/std/mem.c +++ b/src/std/mem.c @@ -15,7 +15,7 @@ void* arena_alloc_align(arena* a, size_t size, size_t align) { if (available < 0 || (ptrdiff_t)size > available) { ERROR_EXIT("Arena ran out of memory\n"); } - void* p = a->begin + padding; + void* p = a->curr + padding; a->curr += padding + size; return memset(p, 0, size); } -- cgit v1.2.3-70-g09d2 From aed7d1b7ac340c19656059c9cbd94aff40952f83 Mon Sep 17 00:00:00 2001 From: Omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Fri, 3 May 2024 21:37:51 +1000 Subject: create logical device --- src/defines.h | 4 +- src/renderer/backends/backend_dx11.h | 1 - src/renderer/backends/backend_vulkan.c | 237 +++++++++++++++++++++++++++++---- src/renderer/backends/vulkan_helpers.h | 42 +++++- src/renderer/bind_group_layouts.h | 4 +- src/renderer/cleanroom/types.h | 2 +- src/renderer/immediate.h | 6 +- src/renderer/ral.h | 7 +- src/renderer/ral_types.h | 14 +- src/renderer/render.h | 2 +- src/renderer/render_types.h | 16 +-- src/renderer/renderpasses.h | 7 +- src/scene.h | 10 +- src/std/buf.h | 6 +- src/std/mem.c | 9 +- src/std/mem.h | 7 + src/systems/terrain.h | 2 +- xmake.lua | 2 +- 18 files changed, 299 insertions(+), 79 deletions(-) (limited to 'src/std/mem.c') diff --git a/src/defines.h b/src/defines.h index ec526e0..4b6f8c7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -66,8 +66,8 @@ Renderer backend defines: // Platform will inform renderer backend (unless user overrides) #if defined(CEL_PLATFORM_LINUX) -#define CEL_REND_BACKEND_OPENGL 1 -// #define CEL_REND_BACKEND_VULKAN 1 +// #define CEL_REND_BACKEND_OPENGL 1 +#define CEL_REND_BACKEND_VULKAN 1 #endif #if defined(CEL_PLATFORM_WINDOWS) diff --git a/src/renderer/backends/backend_dx11.h b/src/renderer/backends/backend_dx11.h index 8e3a513..53738aa 100644 --- a/src/renderer/backends/backend_dx11.h +++ b/src/renderer/backends/backend_dx11.h @@ -8,7 +8,6 @@ // typedef struct gpu_swapchain gpu_swapchain; typedef struct gpu_device { - // VkPhysicalDevice physical_device; // VkDevice logical_device; // VkPhysicalDeviceProperties properties; diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index ae857a0..c21a6b9 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -5,6 +5,7 @@ #include #include "backend_vulkan.h" +#include "maths_types.h" #include "mem.h" #include "vulkan_helpers.h" @@ -31,6 +32,8 @@ typedef struct vulkan_context { u32 screen_width; u32 screen_height; + + VkDebugUtilsMessengerEXT vk_debugger; } vulkan_context; static vulkan_context context; @@ -39,6 +42,13 @@ static vulkan_context context; /** @brief Enumerates and selects the most appropriate graphics device */ bool select_physical_device(gpu_device* out_device); + +bool is_physical_device_suitable(VkPhysicalDevice device); + +queue_family_indices find_queue_families(VkPhysicalDevice device); + +bool create_logical_device(gpu_device* out_device); + /** @brief Helper function for creating array of all extensions we want */ cstr_darray* get_all_extensions(); @@ -49,7 +59,7 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { // Create an allocator size_t temp_arena_size = 1024 * 1024; - arena_create(malloc(temp_arena_size), temp_arena_size); + context.temp_arena = arena_create(malloc(temp_arena_size), temp_arena_size); // Setup Vulkan instance VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; @@ -63,20 +73,61 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { create_info.pApplicationInfo = &app_info; // Extensions - // FIXME: Use my own extension choices - // cstr_darray* required_extensions = cstr_darray_new(2); + cstr_darray* required_extensions = cstr_darray_new(2); // cstr_darray_push(required_extensions, VK_KHR_SURFACE_EXTENSION_NAME); - // create_info.enabledExtensionCount = cstr_darray_len(required_extensions); - // create_info.ppEnabledExtensionNames = required_extensions->data; + uint32_t count; const char** extensions = glfwGetRequiredInstanceExtensions(&count); - create_info.enabledExtensionCount = count; - create_info.ppEnabledExtensionNames = extensions; + for (u32 i = 0; i < count; i++) { + cstr_darray_push(required_extensions, extensions[i]); + } + + cstr_darray_push(required_extensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + + DEBUG("Required extensions:"); + for (u32 i = 0; i < cstr_darray_len(required_extensions); i++) { + DEBUG(" %s", required_extensions->data[i]); + } + + create_info.enabledExtensionCount = cstr_darray_len(required_extensions); + create_info.ppEnabledExtensionNames = required_extensions->data; // TODO: Validation layers create_info.enabledLayerCount = 0; create_info.ppEnabledLayerNames = NULL; + INFO("Validation layers enabled"); + cstr_darray* desired_validation_layers = cstr_darray_new(1); + cstr_darray_push(desired_validation_layers, "VK_LAYER_KHRONOS_validation"); + + u32 n_available_layers = 0; + VK_CHECK(vkEnumerateInstanceLayerProperties(&n_available_layers, 0)); + TRACE("%d available layers", n_available_layers); + VkLayerProperties* available_layers = + arena_alloc(&context.temp_arena, n_available_layers * sizeof(VkLayerProperties)); + VK_CHECK(vkEnumerateInstanceLayerProperties(&n_available_layers, available_layers)); + + for (int i = 0; i < cstr_darray_len(desired_validation_layers); i++) { + // look through layers to make sure we can find the ones we want + bool found = false; + for (int j = 0; j < n_available_layers; j++) { + if (str8_equals(str8_cstr_view(desired_validation_layers->data[i]), + str8_cstr_view(available_layers[j].layerName))) { + found = true; + TRACE("Found layer %s", desired_validation_layers->data[i]); + break; + } + } + + if (!found) { + FATAL("Required validation is missing %s", desired_validation_layers->data[i]); + return false; + } + } + INFO("All validation layers are present"); + create_info.enabledLayerCount = cstr_darray_len(desired_validation_layers); + create_info.ppEnabledLayerNames = desired_validation_layers->data; + VkResult result = vkCreateInstance(&create_info, NULL, &context.instance); if (result != VK_SUCCESS) { ERROR("vkCreateInstance failed with result: %u", result); @@ -84,6 +135,25 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { } TRACE("Vulkan Instance created"); + DEBUG("Creating Vulkan debugger"); + u32 log_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; + VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT + }; + debug_create_info.messageSeverity = log_severity; + debug_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT; + debug_create_info.pfnUserCallback = vk_debug_callback; + + PFN_vkCreateDebugUtilsMessengerEXT func = + (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(context.instance, + "vkCreateDebugUtilsMessengerEXT"); + assert(func); + VK_CHECK(func(context.instance, &debug_create_info, context.allocator, &context.vk_debugger)); + DEBUG("Vulkan Debugger created"); + // Surface creation VkSurfaceKHR surface; VK_CHECK(glfwCreateWindowSurface(context.instance, window, NULL, &surface)); @@ -96,39 +166,43 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { void gpu_backend_shutdown() { arena_free_storage(&context.temp_arena); } bool gpu_device_create(gpu_device* out_device) { + // First things first store this poitner from the renderer + context.device = out_device; + + arena_save savept = arena_savepoint(&context.temp_arena); // Physical device if (!select_physical_device(out_device)) { return false; } TRACE("Physical device selected"); - // Features - VkPhysicalDeviceFeatures device_features = { 0 }; - device_features.samplerAnisotropy = VK_TRUE; // request anistrophy - // Logical device - VkDeviceQueueCreateInfo queue_create_info[2]; - //.. - VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; - device_create_info.queueCreateInfoCount = VULKAN_QUEUES_COUNT; - device_create_info.pQueueCreateInfos = queue_create_info; - device_create_info.pEnabledFeatures = &device_features; - device_create_info.enabledExtensionCount = 1; - const char* extension_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME; - device_create_info.ppEnabledExtensionNames = &extension_names; - - VkResult result = vkCreateDevice(out_device->physical_device, &device_create_info, - context.allocator, &out_device->logical_device); - if (result != VK_SUCCESS) { - FATAL("Error creating logical device with status %u\n", result); - exit(1); - } - TRACE("Logical device created"); + create_logical_device(out_device); + // VkDeviceQueueCreateInfo queue_create_info = {}; + + // queue_family_indices indices = find_queue_families(context.device->physical_device); + // //.. + // VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + // device_create_info.queueCreateInfoCount = VULKAN_QUEUES_COUNT; + // device_create_info.pQueueCreateInfos = queue_create_info; + // device_create_info.pEnabledFeatures = &device_features; + // device_create_info.enabledExtensionCount = 1; + // const char* extension_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME; + // device_create_info.ppEnabledExtensionNames = &extension_names; + + // VkResult result = vkCreateDevice(out_device->physical_device, &device_create_info, + // context.allocator, &out_device->logical_device); + // if (result != VK_SUCCESS) { + // FATAL("Error creating logical device with status %u\n", result); + // exit(1); + // } + // TRACE("Logical device created"); // Queues // Create the command pool + arena_rewind(savept); // Free any temp data return true; } @@ -316,4 +390,109 @@ inline void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count) { vkCmdDrawIndexed(encoder->cmd_buffer, index_count, 1, 0, 0, 0); } -bool select_physical_device(gpu_device* out_device) {} \ No newline at end of file +bool select_physical_device(gpu_device* out_device) { + u32 physical_device_count = 0; + VK_CHECK(vkEnumeratePhysicalDevices(context.instance, &physical_device_count, 0)); + if (physical_device_count == 0) { + FATAL("No devices that support vulkan were found"); + return false; + } + TRACE("Number of devices found %d", physical_device_count); + + VkPhysicalDevice* physical_devices = + arena_alloc(&context.temp_arena, physical_device_count * sizeof(VkPhysicalDevice)); + VK_CHECK(vkEnumeratePhysicalDevices(context.instance, &physical_device_count, physical_devices)); + + bool found = false; + for (u32 device_i = 0; device_i < physical_device_count; device_i++) { + if (is_physical_device_suitable(physical_devices[device_i])) { + out_device->physical_device = physical_devices[device_i]; + found = true; + break; + } + } + + if (!found) { + FATAL("Couldn't find a suitable physical device"); + return false; + } + + return true; +} + +bool is_physical_device_suitable(VkPhysicalDevice device) { + VkPhysicalDeviceProperties properties; + vkGetPhysicalDeviceProperties(device, &properties); + + VkPhysicalDeviceFeatures features; + vkGetPhysicalDeviceFeatures(device, &features); + + VkPhysicalDeviceMemoryProperties memory; + vkGetPhysicalDeviceMemoryProperties(device, &memory); + + // TODO: Check against these device properties + + queue_family_indices indices = find_queue_families(device); + + return indices.has_graphics; +} + +queue_family_indices find_queue_families(VkPhysicalDevice device) { + queue_family_indices indices = { 0 }; + + u32 queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, 0); + + VkQueueFamilyProperties* queue_families = + arena_alloc(&context.temp_arena, queue_family_count * sizeof(VkQueueFamilyProperties)); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families); + + for (u32 queue_i = 0; queue_i < queue_family_count; queue_i++) { + // Graphics queue + if (queue_families[queue_i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { + indices.graphics_queue_index = queue_i; + indices.has_graphics = true; + } + } + + return indices; +} + +bool create_logical_device(gpu_device* out_device) { + queue_family_indices indices = find_queue_families(out_device->physical_device); + + f32 prio_one = 1.0; + VkDeviceQueueCreateInfo queue_create_info = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; + queue_create_info.queueFamilyIndex = indices.graphics_queue_index; + queue_create_info.queueCount = 1; + queue_create_info.pQueuePriorities = &prio_one; + queue_create_info.flags = 0; + queue_create_info.pNext = 0; + + // Features + VkPhysicalDeviceFeatures device_features = { 0 }; + device_features.samplerAnisotropy = VK_TRUE; // request anistrophy + + // Device itself + VkDeviceCreateInfo device_create_info = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + device_create_info.queueCreateInfoCount = 1; + device_create_info.pQueueCreateInfos = &queue_create_info; + device_create_info.pEnabledFeatures = &device_features; + device_create_info.enabledExtensionCount = 1; + const char* extension_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME; + device_create_info.ppEnabledExtensionNames = &extension_names; + + // deprecated + device_create_info.enabledLayerCount = 0; + device_create_info.ppEnabledLayerNames = 0; + + VkResult result = vkCreateDevice(context.device->physical_device, &device_create_info, + context.allocator, &context.device->logical_device); + if (result != VK_SUCCESS) { + printf("error creating logical device with status %u\n", result); + ERROR_EXIT("Unable to create vulkan logical device. Exiting.."); + } + TRACE("Logical device created"); + + return true; +} \ No newline at end of file diff --git a/src/renderer/backends/vulkan_helpers.h b/src/renderer/backends/vulkan_helpers.h index 4bd02f1..baff4e7 100644 --- a/src/renderer/backends/vulkan_helpers.h +++ b/src/renderer/backends/vulkan_helpers.h @@ -20,16 +20,27 @@ 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", res); \ - } \ + } \ } while (0) // TODO: typedef struct vk_debugger {} vk_debugger; +typedef struct queue_family_indices { + u32 graphics_queue_index; + u32 present_queue_index; + u32 compute_queue_index; + u32 transfer_queue_index; + bool has_graphics; + bool has_present; + bool has_compute; + bool has_transfer; +} queue_family_indices; + typedef struct vulkan_physical_device_requirements { bool graphics; bool present; @@ -168,4 +179,25 @@ static bool physical_device_meets_requirements( } return false; +} + +VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback( + VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, + const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { + switch (severity) { + default: + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + ERROR("%s", callback_data->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + WARN("%s", callback_data->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + INFO("%s", callback_data->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + TRACE("%s", callback_data->pMessage); + break; + } + return VK_FALSE; } \ No newline at end of file diff --git a/src/renderer/bind_group_layouts.h b/src/renderer/bind_group_layouts.h index d163fab..d2571ef 100644 --- a/src/renderer/bind_group_layouts.h +++ b/src/renderer/bind_group_layouts.h @@ -4,9 +4,9 @@ * @brief Common bindgroups (descriptor set layouts) * @version 0.1 * @date 2024-04-28 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once #include "defines.h" diff --git a/src/renderer/cleanroom/types.h b/src/renderer/cleanroom/types.h index 7360ebe..6686be5 100644 --- a/src/renderer/cleanroom/types.h +++ b/src/renderer/cleanroom/types.h @@ -2,5 +2,5 @@ #include "darray.h" #include "defines.h" #include "maths_types.h" -#include "str.h" #include "render_types.h" +#include "str.h" diff --git a/src/renderer/immediate.h b/src/renderer/immediate.h index 6d93c53..b9d7c61 100644 --- a/src/renderer/immediate.h +++ b/src/renderer/immediate.h @@ -14,7 +14,7 @@ void imm_draw_camera_frustum(); // const char* model_filepath); // tracks internally whether the model is loaded // static void imm_draw_model(const char* model_filepath) { - // check that model is loaded - // if not loaded, load model and upload to gpu - LRU cache for models - // else submit draw call +// check that model is loaded +// if not loaded, load model and upload to gpu - LRU cache for models +// else submit draw call // } \ No newline at end of file diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 8e49dbe..7c143f2 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -11,10 +11,10 @@ */ #pragma once -#include "ral_types.h" +#include "buf.h" #include "defines.h" +#include "ral_types.h" #include "str.h" -#include "buf.h" // Unrelated forward declares typedef struct arena arena; @@ -60,7 +60,6 @@ struct graphics_pipeline_desc { }; typedef struct gpu_renderpass_desc { - } gpu_renderpass_desc; // --- Lifecycle functions @@ -97,7 +96,7 @@ void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline); void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); -void encode_set_bind_group(); // TODO +void encode_set_bind_group(); // TODO void encode_draw(gpu_cmd_encoder* encoder); void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count); diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index d6c5865..ae54b53 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -1,18 +1,18 @@ /** * @file ral_types.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once +#include "darray.h" #include "defines.h" #include "maths_types.h" -#include "darray.h" #ifndef RENDERER_TYPED_HANDLES CORE_DEFINE_HANDLE(buffer_handle); @@ -99,11 +99,7 @@ KITC_DECL_TYPED_ARRAY(u32) #define TYPED_VERTEX_ARRAY #endif -typedef enum gpu_cull_mode { - CULL_BACK_FACE, - CULL_FRONT_FACE, - CULL_COUNT -} gpu_cull_mode; +typedef enum gpu_cull_mode { CULL_BACK_FACE, CULL_FRONT_FACE, CULL_COUNT } gpu_cull_mode; // ? How to tie together materials and shaders diff --git a/src/renderer/render.h b/src/renderer/render.h index a9370e0..e6dd8b8 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -10,8 +10,8 @@ */ #pragma once -#include "render_types.h" #include "ral_types.h" +#include "render_types.h" bool renderer_init(renderer* ren); void renderer_shutdown(renderer* ren); diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 4866ef4..a5c0c1a 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -1,21 +1,21 @@ /** * @file render_types.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once -#include "ral_types.h" #include "ral.h" +#include "ral_types.h" #if defined(CEL_PLATFORM_WINDOWS) // #include "backend_dx11.h" -#include "backend_vulkan.h" #endif +#include "backend_vulkan.h" struct GLFWwindow; @@ -37,7 +37,7 @@ typedef struct renderer { typedef struct geometry_data { vertex_format format; - vertex_darray* vertices; // TODO: make it not a pointer + vertex_darray* vertices; // TODO: make it not a pointer bool has_indices; u32_darray indices; vec3 colour; /** Optional: set vertex colours */ @@ -66,8 +66,8 @@ typedef struct model { typedef struct texture { u32 texture_id; char name[256]; - void *image_data; - void *backend_data; + void* image_data; + void* backend_data; u32 width; u32 height; u8 channel_count; diff --git a/src/renderer/renderpasses.h b/src/renderer/renderpasses.h index 67badaa..91970d8 100644 --- a/src/renderer/renderpasses.h +++ b/src/renderer/renderpasses.h @@ -4,9 +4,9 @@ * @brief Built-in renderpasses to the engine * @version 0.1 * @date 2024-04-28 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once #include "maths_types.h" @@ -25,7 +25,8 @@ typedef struct render_entity { // Don't need to pass in *anything*. gpu_renderpass* renderpass_blinn_phong_create(); -void renderpass_blinn_phong_execute(gpu_renderpass* pass, render_entity* entities, size_t entity_count); +void renderpass_blinn_phong_execute(gpu_renderpass* pass, render_entity* entities, + size_t entity_count); gpu_renderpass* renderpass_shadows_create(); void renderpass_shadows_execute(gpu_renderpass* pass, render_entity* entities, size_t entity_count); \ No newline at end of file diff --git a/src/scene.h b/src/scene.h index 2cc4d8a..6cac061 100644 --- a/src/scene.h +++ b/src/scene.h @@ -1,12 +1,12 @@ /** * @file scene.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-27 - * + * * @copyright Copyright (c) 2024 - * + * */ #include "defines.h" #include "types.h" @@ -24,7 +24,7 @@ bool scene_add_point_light(scene* s /* TODO */); bool scene_add_heightmap(scene* s /* TODO */); bool scene_delete_heightmap(scene* s); -bool scene_add_model(scene *s, model_handle model); -void scene_remove_model(scene *s, model_handle model); +bool scene_add_model(scene* s, model_handle model); +void scene_remove_model(scene* s, model_handle model); // TODO: functions to load and save scenes from disk \ No newline at end of file diff --git a/src/std/buf.h b/src/std/buf.h index b0f8b85..de093ec 100644 --- a/src/std/buf.h +++ b/src/std/buf.h @@ -1,12 +1,12 @@ /** * @file buf.h * @author your name (you@domain.com) - * @brief + * @brief * @version 0.1 * @date 2024-04-28 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once #include "defines.h" diff --git a/src/std/mem.c b/src/std/mem.c index 5468898..4886d72 100644 --- a/src/std/mem.c +++ b/src/std/mem.c @@ -31,4 +31,11 @@ void arena_free_all(arena* a) { a->curr = a->begin; // pop everything at once and reset to the start. } -void arena_free_storage(arena* a) { free(a->begin); } \ No newline at end of file +void arena_free_storage(arena* a) { free(a->begin); } + +arena_save arena_savepoint(arena* a) { + arena_save savept = { .arena = a, .savepoint = a->curr }; + return savept; +} + +void arena_rewind(arena_save savepoint) { savepoint.arena->curr = savepoint.savepoint; } \ No newline at end of file diff --git a/src/std/mem.h b/src/std/mem.h index 2f92894..bbfb852 100644 --- a/src/std/mem.h +++ b/src/std/mem.h @@ -18,9 +18,16 @@ typedef struct arena { char* end; } arena; +typedef struct arena_save { + arena* arena; + char* savepoint; +} arena_save; + arena arena_create(void* backing_buffer, size_t capacity); void* arena_alloc(arena* a, size_t size); void* arena_alloc_align(arena* a, size_t size, size_t align); void arena_free_all(arena* a); void arena_free_storage(arena* a); +arena_save arena_savepoint(arena* a); +void arena_rewind(arena_save savepoint); // TODO: arena_resize \ No newline at end of file diff --git a/src/systems/terrain.h b/src/systems/terrain.h index 3d6f1c1..a8bff17 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -29,7 +29,7 @@ typedef struct heightmap { typedef struct terrain_state { arena terrain_allocator; - heightmap* heightmap; // NULL = no heightmap + heightmap* heightmap; // NULL = no heightmap } terrain_state; bool terrain_system_init(terrain_state* state); diff --git a/xmake.lua b/xmake.lua index ab6a7a6..949dd76 100644 --- a/xmake.lua +++ b/xmake.lua @@ -1,6 +1,6 @@ set_project("celeritas") set_version("0.1.0") -set_config("cc", "clang-cl") +set_config("cc", "gcc") add_rules("mode.debug", "mode.release") -- we have two modes: debug & release -- cgit v1.2.3-70-g09d2 From 9df999df385b74be5096218d206dd39988784237 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 17 May 2024 09:39:57 +1000 Subject: starting on pool allocator --- assets/shaders/triangle.frag | 4 +--- src/renderer/backends/backend_vulkan.c | 14 ++++++++------ src/renderer/ral.h | 5 +++++ src/std/mem.c | 21 ++++++++++++++++++++- src/std/mem.h | 28 +++++++++++++++++++++++++++- 5 files changed, 61 insertions(+), 11 deletions(-) (limited to 'src/std/mem.c') diff --git a/assets/shaders/triangle.frag b/assets/shaders/triangle.frag index a8c6e69..c3ff328 100644 --- a/assets/shaders/triangle.frag +++ b/assets/shaders/triangle.frag @@ -3,6 +3,4 @@ layout(location = 0) in vec3 fragColor; layout(location = 0) out vec4 outColor; -void main() { - outColor = vec4(fragColor, 0.0); -} +void main() { outColor = vec4(fragColor, 0.0); } diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 3a9c4e1..1db9803 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -411,12 +411,13 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip frag_shader_stage_info }; // TODO: Attributes - VkVertexInputAttributeDescription attribute_descs[2] = {0}; + VkVertexInputAttributeDescription attribute_descs[2] = { 0 }; /* u32 offset = 0; */ /* for (u32 i = 0; i < description.vertex_desc.attributes_count; i++) { */ /* attribute_descs[i].binding = 0; */ /* attribute_descs[i].location = i; */ - /* attribute_descs[i].format = format_from_vertex_attr(description.vertex_desc.attributes[i]); */ + /* attribute_descs[i].format = format_from_vertex_attr(description.vertex_desc.attributes[i]); + */ /* attribute_descs[i].offset = offset; */ /* size_t this_offset = vertex_attrib_size(description.vertex_desc.attributes[i]); */ /* printf("offset total %d this attr %ld\n", offset, this_offset); */ @@ -428,12 +429,12 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip attribute_descs[0].binding = 0; attribute_descs[0].location = 0; attribute_descs[0].format = VK_FORMAT_R32G32B32_SFLOAT; - attribute_descs[0].offset = 0; // offsetof(custom_vertex, pos); + attribute_descs[0].offset = 0; // offsetof(custom_vertex, pos); attribute_descs[1].binding = 0; attribute_descs[1].location = 1; attribute_descs[1].format = VK_FORMAT_R32G32B32_SFLOAT; - attribute_descs[1].offset = 12; // offsetof(custom_vertex, color); + attribute_descs[1].offset = 12; // offsetof(custom_vertex, color); // Vertex input // TODO: Generate this from descroiption now @@ -447,7 +448,8 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip }; vertex_input_info.vertexBindingDescriptionCount = 1; vertex_input_info.pVertexBindingDescriptions = &binding_desc; - vertex_input_info.vertexAttributeDescriptionCount = 2; // description.vertex_desc.attributes_count; + vertex_input_info.vertexAttributeDescriptionCount = + 2; // description.vertex_desc.attributes_count; vertex_input_info.pVertexAttributeDescriptions = attribute_descs; // Input Assembly @@ -628,7 +630,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip VK_CHECK(vkCreateDescriptorSetLayout(context.device->logical_device, &desc_set_layout_info, context.allocator, &desc_set_layouts[i])); } - printf("Descriptor set layouts\n"); + printf("Descriptor set layouts\n"); // Layout VkPipelineLayoutCreateInfo pipeline_layout_create_info = { diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 30d5413..ee65233 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -78,6 +78,11 @@ 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); diff --git a/src/std/mem.c b/src/std/mem.c index 4886d72..7d768c9 100644 --- a/src/std/mem.c +++ b/src/std/mem.c @@ -8,6 +8,8 @@ #define DEFAULT_ALIGNMENT (2 * sizeof(void*)) #endif +// --- Arena + void* arena_alloc_align(arena* a, size_t size, size_t align) { ptrdiff_t padding = -(uintptr_t)a->curr & (align - 1); ptrdiff_t available = a->end - a->curr - padding; @@ -38,4 +40,21 @@ arena_save arena_savepoint(arena* a) { return savept; } -void arena_rewind(arena_save savepoint) { savepoint.arena->curr = savepoint.savepoint; } \ No newline at end of file +void arena_rewind(arena_save savepoint) { savepoint.arena->curr = savepoint.savepoint; } + +// --- Pool + +void_pool void_pool_create(arena* a, u64 capacity, u64 entry_size) { + size_t memory_requirements = capacity * entry_size; + void* backing_buf = arena_alloc(a, memory_requirements); + + void_pool pool = { .capacity = capacity, + .entry_size = entry_size, + .count = 0, + .backing_buffer = backing_buf, + .free_list_head = NULL }; + + void_pool_free_all(&pool); + + return pool; +} diff --git a/src/std/mem.h b/src/std/mem.h index bbfb852..eef97a0 100644 --- a/src/std/mem.h +++ b/src/std/mem.h @@ -10,6 +10,9 @@ #pragma once #include +#include "defines.h" + +// --- Arena // Inspired by https://nullprogram.com/blog/2023/09/27/ typedef struct arena { @@ -30,4 +33,27 @@ void arena_free_all(arena* a); void arena_free_storage(arena* a); arena_save arena_savepoint(arena* a); void arena_rewind(arena_save savepoint); -// TODO: arena_resize \ No newline at end of file +// TODO: arena_resize + +// --- Pool + +typedef struct void_pool_header void_pool_header; +struct void_pool_header { + void_pool_header* next; +}; + +typedef struct void_pool { + u64 capacity; + u64 entry_size; + u64 count; + void* backing_buffer; + void_pool_header* free_list_head; +} void_pool; + +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); + +// TODO: macro that lets us specialise -- cgit v1.2.3-70-g09d2 From 519329e98467d0cdcc39720cef0f69c9936b6d55 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 17 May 2024 13:50:33 +1000 Subject: pool tests and try get macro working --- src/physics/broadphase.h | 6 +-- src/physics/collision.h | 8 ++-- src/physics/narrowphase.h | 6 +-- src/renderer/backends/backend_vulkan.h | 3 +- src/renderer/backends/vulkan_helpers.h | 10 ++--- src/renderer/ral.c | 22 +++++++++++ src/renderer/ral.h | 9 ++--- src/renderer/ral_types.h | 30 ++++++++++---- src/renderer/render.h | 16 ++++---- src/std/mem.c | 67 ++++++++++++++++++++++++++++++- src/std/mem.h | 24 +++++++++++- tests/pool_test_runner.c | 12 ++++++ tests/pool_tests.c | 72 ++++++++++++++++++++++++++++++++++ xmake.lua | 17 ++++++++ 14 files changed, 261 insertions(+), 41 deletions(-) create mode 100644 src/renderer/ral.c create mode 100644 tests/pool_test_runner.c create mode 100644 tests/pool_tests.c (limited to 'src/std/mem.c') 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 #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 #include #include #include + #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 +#include +#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") -- cgit v1.2.3-70-g09d2