diff options
-rw-r--r-- | src/core.h | 1 | ||||
-rw-r--r-- | src/defines.h | 4 | ||||
-rw-r--r-- | src/renderer/backends/backend_vulkan.c | 116 | ||||
-rw-r--r-- | src/renderer/backends/vulkan_helpers.h | 19 | ||||
-rw-r--r-- | src/renderer/render.h | 17 | ||||
-rw-r--r-- | src/renderer/render_backend.h | 9 | ||||
-rw-r--r-- | src/renderer/render_types.h | 6 | ||||
-rw-r--r-- | src/std/containers/darray.h | 44 | ||||
-rw-r--r-- | xmake.lua | 2 |
9 files changed, 177 insertions, 41 deletions
@@ -8,6 +8,7 @@ #include "threadpool.h" typedef struct core { + // TODO: Add application name renderer renderer; threadpool threadpool; input_state input; diff --git a/src/defines.h b/src/defines.h index 52aa7b0..4459e1a 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) || defined(CEL_PLATFORM_WINDOWS) -#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_MAC) diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index bf2234d..c21dfc2 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -1,10 +1,14 @@ +#include "str.h" #define CEL_PLATFORM_LINUX +#include "darray.h" #include "defines.h" #include "file.h" #include "log.h" #include "maths_types.h" +#include "render_backend.h" #include "render_types.h" +#include "vulkan_helpers.h" #include <stdlib.h> @@ -13,10 +17,118 @@ #include <glad/glad.h> #include <glfw3.h> +#include <vulkan/vulkan.h> +#include <vulkan/vulkan_core.h> + +typedef struct vulkan_context { + VkInstance instance; + VkAllocationCallbacks* allocator; +} vulkan_context; -typedef struct vulkan_context vulkan_context; static vulkan_context context; /** @brief Internal backend state */ typedef struct vulkan_state { -} vulkan_state;
\ No newline at end of file +} vulkan_state; + +KITC_DECL_TYPED_ARRAY(VkLayerProperties) + +bool gfx_backend_init(renderer* ren) { + INFO("loading Vulkan backend"); + + vulkan_state* internal = malloc(sizeof(vulkan_state)); + ren->backend_state = (void*)internal; + + context.allocator = 0; // TODO: custom allocator + + // Setup Vulkan instance + VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; + app_info.apiVersion = VK_API_VERSION_1_3; + app_info.pApplicationName = ren->config.window_name; + app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + app_info.pEngineName = "Celeritas Engine"; + app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0); + + VkInstanceCreateInfo create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; + create_info.pApplicationInfo = &app_info; + + cstr_darray* required_extensions = cstr_darray_new(2); + cstr_darray_push(required_extensions, VK_KHR_SURFACE_EXTENSION_NAME); + + plat_get_required_extension_names(required_extensions); + +#if defined(DEBUG) + 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]); + } +#endif + + create_info.enabledExtensionCount = cstr_darray_len(required_extensions); + create_info.ppEnabledExtensionNames = required_extensions->data; + + // Validation layers + create_info.enabledLayerCount = 0; + create_info.ppEnabledLayerNames = 0; +#if defined(DEBUG) + 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_darray* available_layers = VkLayerProperties_darray_new(n_available_layers); + VK_CHECK(vkEnumerateInstanceLayerProperties(&n_available_layers, available_layers->data)); + + 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->data[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; +#endif + + VkResult result = vkCreateInstance(&create_info, NULL, &context.instance); + if (result != VK_SUCCESS) { + ERROR("vkCreateInstance failed with result: %u", result); + return false; + } + + INFO("Vulkan renderer initialisation succeeded"); + return true; +} + +void gfx_backend_shutdown(renderer* ren) {} + +void clear_screen(vec3 colour) {} + +void bind_texture(shader s, texture* tex, u32 slot) {} +void bind_mesh_vertex_buffer(void* backend, mesh* mesh) {} +void draw_primitives(cel_primitive_topology primitive, u32 start_index, u32 count) {} + +shader shader_create_separate(const char* vert_shader, const char* frag_shader) {} +void set_shader(shader s) {} + +void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value) {} +void uniform_f32(u32 program_id, const char* uniform_name, f32 value) {} +void uniform_i32(u32 program_id, const char* uniform_name, i32 value) {} +void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value) {} + +#endif
\ No newline at end of file diff --git a/src/renderer/backends/vulkan_helpers.h b/src/renderer/backends/vulkan_helpers.h new file mode 100644 index 0000000..058ea91 --- /dev/null +++ b/src/renderer/backends/vulkan_helpers.h @@ -0,0 +1,19 @@ +#pragma once + +#include <assert.h> +#include <vulkan/vulkan.h> + +#include "darray.h" +#include "defines.h" + +DECL_TYPED_ARRAY(const char*, cstr) + +static void plat_get_required_extension_names(cstr_darray* extensions) { +#ifdef CEL_PLATFORM_LINUX + cstr_darray_push(extensions, "VK_KHR_xcb_surface"); +#endif +} + +// TODO(omni): port to using internal assert functions +#define VK_CHECK(vulkan_expr) \ + { assert(vulkan_expr == VK_SUCCESS); }
\ No newline at end of file diff --git a/src/renderer/render.h b/src/renderer/render.h index db74acc..6cd9701 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -4,9 +4,9 @@ * @brief Renderer frontend * @version 0.1 * @date 2024-03-21 - * + * * @copyright Copyright (c) 2024 - * + * */ #pragma once @@ -20,7 +20,7 @@ bool renderer_init(renderer* ren); /** @brief shutdown the render system frontend */ void renderer_shutdown(renderer* ren); -void renderer_on_resize(renderer *ren); +void renderer_on_resize(renderer* ren); struct render_packet; @@ -38,14 +38,3 @@ void draw_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, mat4* vie // --- texture texture_data_load(const char* path, bool invert_y); // #frontend void texture_data_upload(texture* tex); // #backend - -// --- Uniforms - -/** @brief upload a vec3 of f32 to a uniform */ -void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value); -/** @brief upload a single f32 to a uniform */ -void uniform_f32(u32 program_id, const char* uniform_name, f32 value); -/** @brief upload a integer to a uniform */ -void uniform_i32(u32 program_id, const char* uniform_name, i32 value); -/** @brief upload a mat4 of f32 to a uniform */ -void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value);
\ No newline at end of file diff --git a/src/renderer/render_backend.h b/src/renderer/render_backend.h index 9644f07..8c351c6 100644 --- a/src/renderer/render_backend.h +++ b/src/renderer/render_backend.h @@ -22,3 +22,12 @@ shader shader_create_separate(const char* vert_shader, const char* frag_shader); void set_shader(shader s); // --- Uniforms + +/** @brief upload a vec3 of f32 to a uniform */ +void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value); +/** @brief upload a single f32 to a uniform */ +void uniform_f32(u32 program_id, const char* uniform_name, f32 value); +/** @brief upload a integer to a uniform */ +void uniform_i32(u32 program_id, const char* uniform_name, i32 value); +/** @brief upload a mat4 of f32 to a uniform */ +void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value);
\ No newline at end of file diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 02eac6f..7bb6e60 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -34,9 +34,13 @@ typedef struct renderer_config { vec3 clear_colour; /** colour that the screen gets cleared to every frame */ } renderer_config; +typedef struct frame_stats { + u64 last_time; +} frame_stats; + typedef struct renderer { struct GLFWwindow *window; /** Currently all platforms use GLFW*/ - void* backend_state; /** Graphics API-specific state */ + void *backend_state; /** Graphics API-specific state */ renderer_config config; // shaders shader blinn_phong; diff --git a/src/std/containers/darray.h b/src/std/containers/darray.h index 25bf846..8eb00cb 100644 --- a/src/std/containers/darray.h +++ b/src/std/containers/darray.h @@ -39,15 +39,17 @@ /* } else {\ */ /* }\ */ -#define KITC_DECL_TYPED_ARRAY(T) \ - typedef typed_array(T) T##_darray; \ - typedef typed_array_iterator(T) T##_darray_iter; \ +#define KITC_DECL_TYPED_ARRAY(T) DECL_TYPED_ARRAY(T, T) + +#define DECL_TYPED_ARRAY(T, Type) \ + typedef typed_array(T) Type##_darray; \ + typedef typed_array_iterator(Type) Type##_darray_iter; \ \ /* Create a new one growable array */ \ - PREFIX T##_darray *T##_darray_new(size_t starting_capacity) { \ - T##_darray *d; \ + PREFIX Type##_darray *Type##_darray_new(size_t starting_capacity) { \ + Type##_darray *d; \ T *data; \ - d = malloc(sizeof(T##_darray)); \ + d = malloc(sizeof(Type##_darray)); \ data = malloc(starting_capacity * sizeof(T)); \ \ d->len = 0; \ @@ -57,14 +59,14 @@ return d; \ } \ \ - PREFIX void T##_darray_free(T##_darray *d) { \ + PREFIX void Type##_darray_free(Type##_darray *d) { \ if (d != NULL) { \ free(d->data); \ free(d); \ } \ } \ \ - PREFIX T *T##_darray_resize(T##_darray *d, size_t capacity) { \ + PREFIX T *Type##_darray_resize(Type##_darray *d, size_t capacity) { \ /* resize the internal data block */ \ T *new_data = realloc(d->data, sizeof(T) * capacity); \ /* TODO: handle OOM error */ \ @@ -74,22 +76,22 @@ return new_data; \ } \ \ - PREFIX void T##_darray_push(T##_darray *d, T value) { \ + PREFIX void Type##_darray_push(Type##_darray *d, T value) { \ if (d->len >= d->capacity) { \ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ - T *resized = T##_darray_resize(d, new_capacity); \ + T *resized = Type##_darray_resize(d, new_capacity); \ } \ \ d->data[d->len] = value; \ d->len += 1; \ } \ \ - PREFIX void T##_darray_push_copy(T##_darray *d, const T *value) { \ + PREFIX void Type##_darray_push_copy(Type##_darray *d, const T *value) { \ if (d->len >= d->capacity) { \ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ - T *resized = T##_darray_resize(d, new_capacity); \ + T *resized = Type##_darray_resize(d, new_capacity); \ } \ \ T *place = d->data + d->len; \ @@ -97,18 +99,18 @@ memcpy(place, value, sizeof(T)); \ } \ \ - PREFIX void T##_darray_pop(T##_darray *d, T *dest) { \ + PREFIX void Type##_darray_pop(Type##_darray *d, T *dest) { \ T *item = d->data + (d->len - 1); \ d->len -= 1; \ memcpy(dest, item, sizeof(T)); \ } \ \ - PREFIX void T##_darray_ins(T##_darray *d, const T *value, size_t index) { \ + PREFIX void Type##_darray_ins(Type##_darray *d, const T *value, size_t index) { \ /* check if requires resize */ \ if (d->len + 1 > d->capacity) { \ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ - T *resized = T##_darray_resize(d, new_capacity); \ + T *resized = Type##_darray_resize(d, new_capacity); \ } \ \ /* shift existing data after index */ \ @@ -122,14 +124,14 @@ memcpy(insert_dest, value, sizeof(T)); \ } \ \ - PREFIX void T##_darray_clear(T##_darray *d) { \ + PREFIX void Type##_darray_clear(Type##_darray *d) { \ d->len = 0; \ memset(d->data, 0, d->capacity * sizeof(T)); \ } \ \ - PREFIX size_t T##_darray_len(T##_darray *d) { return d->len; } \ + PREFIX size_t Type##_darray_len(Type##_darray *d) { return d->len; } \ \ - PREFIX void T##_darray_print(T##_darray *d) { \ + PREFIX void Type##_darray_print(Type##_darray *d) { \ printf("len: %zu ", d->len); \ printf("capacity: %zu\n", d->capacity); \ for (int i = 0; i < d->len; i++) { \ @@ -137,14 +139,14 @@ } \ } \ \ - PREFIX T##_darray_iter T##_darray_iter_new(T##_darray *d) { \ - T##_darray_iter iterator; \ + PREFIX Type##_darray_iter Type##_darray_iter_new(Type##_darray *d) { \ + Type##_darray_iter iterator; \ iterator.array = d; \ iterator.current_idx = 0; \ return iterator; \ } \ \ - PREFIX void *T##_darray_iter_next(T##_darray_iter *iterator) { \ + PREFIX void *Type##_darray_iter_next(Type##_darray_iter *iterator) { \ if (iterator->current_idx < iterator->array->len) { \ return &iterator->array->data[iterator->current_idx++]; \ } else { \ @@ -22,7 +22,7 @@ end -- Platform defines and system packages if is_plat("linux") then add_defines("CEL_PLATFORM_LINUX") - add_syslinks("dl", "X11", "pthread") + add_syslinks("vulkan", "dl", "X11", "pthread") elseif is_plat("windows") then add_defines("CEL_PLATFORM_WINDOWS") elseif is_plat("macosx") then |