summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core.h1
-rw-r--r--src/defines.h4
-rw-r--r--src/renderer/backends/backend_vulkan.c116
-rw-r--r--src/renderer/backends/vulkan_helpers.h19
-rw-r--r--src/renderer/render.h17
-rw-r--r--src/renderer/render_backend.h9
-rw-r--r--src/renderer/render_types.h6
-rw-r--r--src/std/containers/darray.h44
-rw-r--r--xmake.lua2
9 files changed, 177 insertions, 41 deletions
diff --git a/src/core.h b/src/core.h
index 1b3e28b..f54631e 100644
--- a/src/core.h
+++ b/src/core.h
@@ -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 { \
diff --git a/xmake.lua b/xmake.lua
index 611b537..386f3bb 100644
--- a/xmake.lua
+++ b/xmake.lua
@@ -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